Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { defineConfig } from 'astro/config';
import tailwindcss from '@tailwindcss/vite';
import { remarkRewriteLinks } from './src/plugins/remark-rewrite-links.mjs';
import { rehypePagefindAttrs } from './src/plugins/rehype-pagefind-attrs.mjs';

export default defineConfig({
site: 'https://bradygaster.github.io',
Expand All @@ -10,6 +11,7 @@ export default defineConfig({
},
markdown: {
remarkPlugins: [remarkRewriteLinks],
rehypePlugins: [rehypePagefindAttrs],
shikiConfig: {
themes: {
light: 'github-light',
Expand Down
5 changes: 4 additions & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
"dev": "astro dev",
"build": "astro build && npx pagefind --site dist",
"preview": "astro preview",
"astro": "astro"
"astro": "astro",
"test": "node --test tests/build-output.test.mjs && npx playwright test",
"test:build": "node --test tests/build-output.test.mjs",
"test:e2e": "npx playwright test"
},
"dependencies": {
"@tailwindcss/vite": "^4.1.0",
Expand Down
12 changes: 12 additions & 0 deletions docs/pagefind.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Pagefind configuration for Squad docs
# See: https://pagefind.app/docs/config-options/

# Exclude navigation, footers, and code blocks from indexing
exclude_selectors:
- "nav"
- "footer"
- "aside"
- "pre"
- ".astro-code"


13 changes: 13 additions & 0 deletions docs/playwright.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { defineConfig } from '@playwright/test';

export default defineConfig({
testDir: './tests',
testMatch: '**/*.spec.mjs',
timeout: 30_000,
retries: 0,
use: {
baseURL: 'http://localhost:4321/squad/',
browserName: 'chromium',
headless: true,
},
});
Binary file added docs/screenshots/before-search-agent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/before-search-ceremony.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/before-search-install.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/search-agent.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/search-ceremony.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/screenshots/search-install.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion docs/src/components/Footer.astro
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import squadLogo from '../assets/images/squad-logo.png';
const base = import.meta.env.BASE_URL;
---

<footer class="border-t border-surface-200 dark:border-surface-800 mt-16">
<footer class="border-t border-surface-200 dark:border-surface-800 mt-16" data-pagefind-ignore>
<div class="max-w-7xl mx-auto px-4 py-8 sm:px-6 lg:px-8">
<div class="grid grid-cols-1 md:grid-cols-4 gap-8">
<div>
Expand Down
4 changes: 2 additions & 2 deletions docs/src/components/Header.astro
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ const mobileNavBase = "block px-3 py-2 rounded-md text-base transition-colors";
</a>

<!-- Top nav links (desktop) -->
<nav class="hidden md:flex items-center gap-1 text-base">
<nav class="hidden md:flex items-center gap-1 text-base" data-pagefind-ignore>
<a href={`${base}docs/get-started/installation/`} class:list={[navBase, isDocsActive ? navActive : navInactive]}>Docs</a>
<a href={`${base}blog/`} class:list={[navBase, isBlogActive ? navActive : navInactive]}>Blog</a>
<a href="https://github.com/bradygaster/squad" class:list={[navBase, navInactive]} target="_blank" rel="noopener">GitHub</a>
Expand All @@ -71,7 +71,7 @@ const mobileNavBase = "block px-3 py-2 rounded-md text-base transition-colors";
</div>

<!-- Mobile nav dropdown -->
<nav id="mobile-nav" class="hidden md:hidden border-t border-surface-200 dark:border-surface-800 bg-white dark:bg-surface-950">
<nav id="mobile-nav" class="hidden md:hidden border-t border-surface-200 dark:border-surface-800 bg-white dark:bg-surface-950" data-pagefind-ignore>
<div class="px-4 py-3 space-y-1">
<a href={`${base}docs/get-started/installation/`} class:list={[mobileNavBase, isDocsActive ? navActive : navInactive]}>Docs</a>
<a href={`${base}blog/`} class:list={[mobileNavBase, isBlogActive ? navActive : navInactive]}>Blog</a>
Expand Down
39 changes: 38 additions & 1 deletion docs/src/components/Search.astro
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,13 @@ const base = import.meta.env.BASE_URL;
/>
<kbd class="text-xs border border-surface-300 dark:border-surface-600 rounded px-1.5 py-0.5 text-surface-400 cursor-pointer" id="search-close-kbd">Esc</kbd>
</div>
<div id="search-status" class="hidden px-4 py-2 text-xs text-surface-500 dark:text-surface-400 border-b border-surface-100 dark:border-surface-800"></div>
<div id="search-results" class="max-h-[60vh] overflow-y-auto p-2">
<div class="p-8 text-center text-surface-400 text-sm" id="search-empty">
Start typing to search…
</div>
</div>

</div>
</div>
</div>
Expand Down Expand Up @@ -69,6 +71,25 @@ const base = import.meta.env.BASE_URL;
const searchResults = document.getElementById('search-results');
const searchEmpty = document.getElementById('search-empty');
const searchCloseKbd = document.getElementById('search-close-kbd');
const searchStatus = document.getElementById('search-status');

// Section badge color mapping
const SECTION_COLORS = {
'Get Started': 'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-400',
'Guide': 'bg-blue-100 text-blue-800 dark:bg-blue-900/30 dark:text-blue-400',
'Features': 'bg-purple-100 text-purple-800 dark:bg-purple-900/30 dark:text-purple-400',
'Reference': 'bg-amber-100 text-amber-800 dark:bg-amber-900/30 dark:text-amber-400',
'Scenarios': 'bg-cyan-100 text-cyan-800 dark:bg-cyan-900/30 dark:text-cyan-400',
'Concepts': 'bg-rose-100 text-rose-800 dark:bg-rose-900/30 dark:text-rose-400',
'Cookbook': 'bg-orange-100 text-orange-800 dark:bg-orange-900/30 dark:text-orange-400',
'Blog': 'bg-pink-100 text-pink-800 dark:bg-pink-900/30 dark:text-pink-400',
};

function getSectionBadge(section) {
if (!section) return '';
const colors = SECTION_COLORS[section] || 'bg-surface-100 text-surface-700 dark:bg-surface-800 dark:text-surface-300';
return `<span class="inline-flex items-center px-1.5 py-0.5 rounded text-xs font-medium ${colors}">${section}</span>`;
}

function openSearch() {
searchModal?.classList.remove('hidden');
Expand All @@ -84,13 +105,16 @@ const base = import.meta.env.BASE_URL;
searchResults?.appendChild(searchEmpty);
searchEmpty.textContent = 'Start typing to search…';
}
searchStatus?.classList.add('hidden');
document.body.style.overflow = '';
}

searchBtn?.addEventListener('click', openSearch);
searchBackdrop?.addEventListener('click', closeSearch);
searchCloseKbd?.addEventListener('click', closeSearch);



document.addEventListener('keydown', (e) => {
if ((e.metaKey || e.ctrlKey) && e.key === 'k') {
e.preventDefault();
Expand All @@ -117,6 +141,7 @@ const base = import.meta.env.BASE_URL;
searchEmpty.textContent = 'Start typing to search…';
searchResults.appendChild(searchEmpty);
}
searchStatus?.classList.add('hidden');
return;
}

Expand All @@ -133,15 +158,27 @@ const base = import.meta.env.BASE_URL;
noResults.className = 'p-8 text-center text-surface-400 text-sm';
noResults.textContent = `No results for "${query}"`;
searchResults.appendChild(noResults);
searchStatus?.classList.add('hidden');
return;
}

// Update status bar
if (searchStatus) {
searchStatus.textContent = `${search.results.length} result${search.results.length === 1 ? '' : 's'}`;
searchStatus.classList.remove('hidden');
}

// Render results with section badges
results.forEach((result) => {
const section = result.meta?.section || '';
const a = document.createElement('a');
a.href = result.url;
a.className = 'block px-3 py-2.5 rounded-lg hover:bg-surface-100 dark:hover:bg-surface-800 transition-colors group';
a.innerHTML = `
<div class="font-medium text-base text-surface-900 dark:text-white group-hover:text-squad-600 dark:group-hover:text-squad-400 transition-colors">${result.meta?.title || 'Untitled'}</div>
<div class="flex items-center gap-2">
<span class="font-medium text-base text-surface-900 dark:text-white group-hover:text-squad-600 dark:group-hover:text-squad-400 transition-colors">${result.meta?.title || 'Untitled'}</span>
${getSectionBadge(section)}
</div>
<div class="text-sm text-surface-500 dark:text-surface-400 mt-0.5 line-clamp-2">${result.excerpt || ''}</div>
`;
a.addEventListener('click', closeSearch);
Expand Down
1 change: 1 addition & 0 deletions docs/src/components/Sidebar.astro
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const base = import.meta.env.BASE_URL;
<aside
id="sidebar"
class="fixed inset-y-0 left-0 z-50 w-72 bg-white dark:bg-surface-950 border-r border-surface-200 dark:border-surface-800 transform -translate-x-full lg:translate-x-0 lg:static lg:z-auto transition-transform duration-200 ease-in-out overflow-y-auto pt-14 lg:pt-0 lg:h-[calc(100vh-3.5rem)] lg:sticky lg:top-14 lg:shrink-0"
data-pagefind-ignore
>
<div class="p-4 space-y-6">
{NAV_SECTIONS.map((section) => (
Expand Down
8 changes: 7 additions & 1 deletion docs/src/layouts/DocsLayout.astro
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import BaseLayout from './BaseLayout.astro';
import Header from '../components/Header.astro';
import Sidebar from '../components/Sidebar.astro';
import Footer from '../components/Footer.astro';
import { NAV_SECTIONS } from '../navigation';

interface Props {
title: string;
Expand All @@ -11,6 +12,11 @@ interface Props {
}

const { title, description, currentSlug } = Astro.props;

// Derive section name from the URL path for Pagefind metadata
const sectionDir = currentSlug?.split('/')[0] || '';
const navSection = NAV_SECTIONS.find(s => s.dir === sectionDir);
const section = navSection?.title || 'Docs';
---

<BaseLayout title={title} description={description}>
Expand All @@ -19,7 +25,7 @@ const { title, description, currentSlug } = Astro.props;
<Sidebar currentSlug={currentSlug} />
<main class="flex-1 min-w-0">
<div class="max-w-4xl mx-auto px-4 py-8 sm:px-6 lg:px-8">
<article class="prose" data-pagefind-body>
<article class="prose" data-pagefind-body data-pagefind-meta={`section:${section}`}>
<slot />
</article>
</div>
Expand Down
2 changes: 1 addition & 1 deletion docs/src/pages/blog/[...slug].astro
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ const title = entry.data.title || extractTitle(entry.id);
</svg>
Back to Blog
</a>
<article class="prose" data-pagefind-body>
<article class="prose" data-pagefind-body data-pagefind-meta="section:Blog">
<Content />
</article>
</main>
Expand Down
21 changes: 21 additions & 0 deletions docs/src/plugins/rehype-pagefind-attrs.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { visit } from 'unist-util-visit';

/**
* Rehype plugin that adds Pagefind attributes to rendered markdown HTML.
* - Adds data-pagefind-weight="2" to h2 and h3 for search ranking boost
* - Adds data-pagefind-ignore to pre elements to exclude code blocks
*/
export function rehypePagefindAttrs() {
return (tree) => {
visit(tree, 'element', (node) => {
if (node.tagName === 'h2' || node.tagName === 'h3') {
node.properties = node.properties || {};
node.properties.dataPagefindWeight = '2';
}
if (node.tagName === 'pre') {
node.properties = node.properties || {};
node.properties.dataPagefindIgnore = '';
}
});
};
}
Loading
Loading