Audience: AI coding agents (Claude Code, Cursor, etc.) and humans onboarding to the codebase.
TanStack Start app that renders public documentation for Packyard. Mounted at packyard.dev/documentation/* via Traefik path-prefix routing. Sibling to usepackyard/packyard (the product) and usepackyard/website (marketing).
The docs site is intentionally minimal: server-side markdown rendering, no DB, no auth, no client-side state beyond search. Every page is prerendered at build so Pagefind can index static HTML.
- Routing: file-based under
src/routes/documentation/.index.tsxis/documentation,$slug.tsxis/documentation/<slug>(splat). Loaders call server functions insrc/lib/docs.server.ts. - Markdown pipeline:
src/lib/markdown.server.tsruns unified (remark-parse → remark-gfm → remark-rehype → rehype-slug → rehype-autolink-headings → rehype-pretty-code → rehype-stringify).gray-matterfor frontmatter. - Routes registry:
src/lib/routes.tsis the single source of truth for which slugs exist and their sidebar order. Sidebar, sitemap, and Nitro's prerender list all import from it. - SEO:
src/lib/seo.ts:buildPageHeadmirrors the marketing site's helper so canonical / OG / Twitter / robots tags are consistent across packyard.dev. Per-page JSON-LD (TechArticle + BreadcrumbList) is added in each route'shead(). - Search: Pagefind. Static index built post-build by
scripts/pagefind.mjsagainst.output/public/. UI issrc/components/SearchBox.tsxlazy-loading/pagefind/pagefind-ui.js. - Styling: Tailwind v4 +
@tailwindcss/typographyfor prose. Brand tokens (--accent,--steel,--ink-strong, etc.) mirror the marketing site'sstyles.css.
content/ Markdown source. Add a file here + register in src/lib/routes.ts.
src/
routes/
__root.tsx Site shell (header, footer, html lang, default head meta).
documentation/
index.tsx Renders content/index.md + landing nav cards.
$slug.tsx Renders content/<slug>.md.
sitemap[.]xml.ts /documentation/sitemap.xml.
components/
BrandMark.tsx Mirrored from website/.
Header.tsx Mirrored: brand, Overview (→ packyard.dev), Docs (active), GitHub, search.
Footer.tsx Mirrored from website/.
DocsLayout.tsx Sidebar + main + ToC.
Sidebar.tsx Reads ALL_DOC_ROUTES, highlights current.
ToC.tsx Right-side, derived from H2/H3 of current page.
PrevNext.tsx Bottom-of-page sibling nav.
Breadcrumbs.tsx Site → Documentation → Page.
SearchBox.tsx Pagefind UI mount; ⌘K / Ctrl-K opens.
lib/
docs.server.ts listDocs(), getDoc(slug), getSidebar() — server-only.
markdown.server.ts unified pipeline — server-only.
routes.ts ALL_DOC_ROUTES + metadata.
seo.ts buildPageHead — mirror of website's helper.
router.tsx TanStack Router setup.
styles.css Tailwind + brand tokens.
public/
favicon.svg Mirrored.
og-image.svg Mirrored.
robots.txt Allow /documentation/, point at sitemap.
scripts/
pagefind.mjs Post-build: invoke pagefind binary against .output/public/.
bun install
bun run dev # http://localhost:3001/documentation
bun run typecheck
bun run build # vite build → prerender → pagefind
bun run preview # serve the buildtouch content/<slug>.mdwith the frontmatter:--- title: My new page description: One sentence (used for meta description + OG). order: 50 updated: 2026-04-27 ---
- Edit
src/lib/routes.tsto add the slug toALL_DOC_ROUTES(in sidebar order). bun run dev, verify/documentation/<slug>.bun run buildto confirm prerender + Pagefind succeed.
- One H1 per page (the page title from frontmatter). Markdown body should start at H2.
- Use fenced code blocks with a language so Shiki highlights correctly:
```bash,```yaml,```ts, etc. - Internal links between docs use absolute paths (
/documentation/installation) so they survive Pagefind result rendering. - Don't import client state from the markdown pipeline —
src/lib/markdown.server.tsis server-only and runs at build/SSR time. - Keep
src/lib/routes.tsandcontent/in sync. Adding a markdown file without a routes entry means it won't appear in sidebar/sitemap/prerender.
- Marketing copy (homepage, pricing, etc.) — that's
usepackyard/website. - Product code (Go binary, admin API, dashboard) — that's
usepackyard/packyard. - Hosted/managed/SaaS pitch — Packyard is self-host-only as of 2026-04-27 (paused, not removed; see
usepackyard/website/docs/dormant-routes.md). - Internal contributor docs (architecture, testing discipline) — those live in the product repo's
AGENTS.md.