Files
Rich Haines b7e4bbfbb0 chore(docs): upgrade Geistdocs to 1.22.0 (#855)
## Summary

Upgrades the chat-sdk.dev docs app from `@vercel/geistdocs` **1.20.4 →
1.22.0** (published 2026-08-21, Apache-2.0) and `next` **16.2.11 →
16.3.1**, following the bundled 1.22.0 template as the source of truth.

The target release includes all of the behavior-changing PRs for this
round:

- vercel/geistdocs#245 — require Next.js 16.3, scaffold 16.3.1, drop the
dev filesystem-cache flag (shipped in 1.21.1)
- vercel/geistdocs#246 — Cache Components across Geistdocs
- vercel/geistdocs#249 — Partial Prefetching + instant docs navigation
- vercel/geistdocs#250 — stable Next 16.3 APIs, retryable page/Ask AI
error boundaries, full prefetch of package links, no generic page shell
- vercel/geistdocs#251 — tree sidebar preserves scroll position on
folder toggles

## Adapter and configuration changes

- `next.config.ts`: `cacheComponents: true`, `partialPrefetching: true`;
removed `experimental.turbopackFileSystemCacheForDev` (default in 16.3).
Redirects, `/sitemap.xml` rewrite, and image config unchanged.
- New `lib/geistdocs/root-params.ts`; all layouts read `[lang]` via
`next/root-params` instead of `params`. Route handlers keep
route-context `params`.
- Root layout gains `generateStaticParams` returning every configured
language (`en`) — home (`/`), `/adapters`, and `/resources` now
prerender statically (previously dynamic).
- Route adapters no longer re-export `revalidate`/`dynamic` from package
factories (`agents.md`, `sitemap.md`, `llms.mdx`), and custom routes
drop their own `revalidate` exports (`llms.txt`, `llms-full.txt`,
`adapters.mdx`, `rss.xml`, `resources`).
- `llms.mdx` adopts the template form: `sources: [geistdocsSource]` +
`notFound: {}`, enabling smart agent-readable 404/410 responses with
real HTTP statuses.
- `rss.xml` migrated to the template's `"use cache"` +
`cacheLife("max")` form with `getPublicPath` base-path handling.
- `resources` page: `revalidate = 86400` → `"use cache"` +
`cacheLife("days")` (same 1-day lifetime).
- App-owned data fetching moved off `next: { revalidate }` (unsupported
under Cache Components): GitHub README fetches and homepage OSS stats
now use `"use cache"` + `cacheLife("hours")`.
- Homepage Shiki highlighting (`Demo`, `CodePreview`, `highlightCode`)
runs inside `"use cache"` scopes — Shiki reads `Date.now()` internally,
which otherwise fails prerendering.
- App-owned links to statically generated docs pages get
`prefetch={true}` (platform grid, feature matrix, adapter slug list,
"Visit Documentation") per the template's agent guidance; package-owned
sidebar/prev-next links already prefetch fully in 1.22.0.
- `Analytics`/`SpeedInsights` moved into
`components/geistdocs/provider.tsx` per the template.
- CSS: `styles/geistdocs.css` now imports `@vercel/geistdocs/theme.css`
(self-sourcing package dist/streamdown) instead of layering on
`styles.css` from `global.css`; updated the mobile breadcrumb selector
for the new package DOM; kept the site-specific shadcn tokens, dark
background-scale override, prose, TOC, and streamdown fixes.
- Added `apps/docs/AGENTS.md` capturing the packaged-architecture
conventions (cache-components rules, root-params, markdown contract,
proxy mappings).

## PR #251 (tree sidebar scroll) verification

The fix is package-internal (`manualToggleRef` in `SidebarTree`); no
consumer change is needed. This site's sidebars render no collapsible
folder rows (content uses spread folders, `...api` etc.), so I verified
the shipped behavior against the bundled 1.22.0 template with
`sidebarMode="tree"` enabled locally: expanding/collapsing a folder
preserves the exact sidebar scroll position (772 → 772), and a route
change into a collapsed folder still scrolls the active item into view.
8/8 checks pass.

## Static-generation coverage

Production build: 290/290 static pages generated. Every intended
parameter tuple is prerendered with complete content (verified H1/body
in emitted HTML):

- `/en` home, `/en/adapters` listing, `/en/resources` — now fully static
(were `ƒ` on main)
- `/en/docs/*` — 45 pages, complete static HTML + one generic
`[[...slug]]` fallback entry (allowed)
- `/en/adapters/{official,community,vendor-official}/*` — 44 detail
pages + `/en/adapters.mdx/*` markdown for all 44
- `/en/sitemap.md` — SSG

Intentional contract differences (match the 1.22.0 template's own build
output):

- OG image routes (`/og/[...slug]`, adapter `*/og`) render on demand
under Cache Components instead of build-time SSG; Next 16.3 caches the
rendered image per route. URLs and content types verified unchanged.
- `llms.txt`, `llms-full.txt`, `llms.mdx`, `rss.xml`, `agents.md` remain
on-demand route handlers (same as main); `agents.md` reads the request
origin by package design.
- Unknown HTML routes: browsers receive the docs shell with 200 before
not-found UI resolves; crawlers get a real 404. Machine-readable unknown
routes return the new smart 404 body with real 404 status and
`X-Robots-Tag: noindex`.

## Lockfile

`pnpm-lock.yaml` delta: the `docs` importer's `@vercel/geistdocs`
(1.20.4 → 1.22.0) and `next` (16.2.11 → 16.3.1) bumps, their
peer-context re-resolutions, and one mechanical re-keying of `@swc/core`
peer contexts to include `@swc/helpers` across existing entries (no
version changes outside the docs app). Verified with `pnpm install
--frozen-lockfile`.

## Test results

- `pnpm install --frozen-lockfile` ✓
- `pnpm check` ✓ (1 pre-existing warning in untouched
`lib/read-more.ts`)
- `pnpm typecheck` — 43/43 ✓
- `pnpm knip` ✓, `pnpm konsistent` ✓
- `pnpm test` — 47/47 turbo tasks ✓
- Clean production build (removed `.next`/`.source`) ✓ 290/290
- Production-server (`next start`) contract checks: HTML docs,
`.md`/`.mdx`, `Accept: text/markdown`, agent-UA negotiation, `llms.txt`,
`llms-full.txt`, `sitemap.md`, `agents.md`, `/.well-known/mcp.json`
(intentional 404), `rss.xml`, `robots.txt`, `/sitemap.xml` rewrite, OG
images, `AGENTS.md`, all redirects (308s), `/api/search` JSON and not
rewritten as markdown, `/docs.md` section root ✓
- Browser checks (Playwright, Chrome, `next start`) — 16/16: instant
sidebar + prev/next client navigation with complete content and no
loading shell, single visible H1 (Activity-preserved routes stay
hidden), Copy Page, page actions menu, search → result navigation, Ask
AI panel with suggestions, theme switch (dark applies the site's
background scale), mobile navbar menu and docs sheet navigation, unknown
page shows not-found UI, zero console/page errors and failed requests
- Ask AI scoped failure: with no local AI Gateway credentials the chat
surfaces the error, the surrounding page stays intact, and resubmission
retries cleanly
- Visual parity screenshots vs production (home/docs/adapters, light +
dark) match

## Preview

- Preview:
https://chat-git-richardhaines-geistdocs-122-upgrade.vercel.sh —
deployment **Ready**, build passed on Vercel.
- The preview sits behind Vercel SSO (Fork Protection), so automated
route checks aren't possible without a bypass token; please spot-check
through SSO: `/docs/getting-started`, `/docs/getting-started.md`,
`/adapters`, `/llms.txt`, and a client navigation between docs pages.

Signed-off-by: molebox <rich@vercel.com>
2026-08-24 12:22:40 +02:00

7.8 KiB

Geistdocs agent instructions

This app (chat-sdk.dev) uses the packaged Geistdocs architecture. The @vercel/geistdocs package owns shared runtime behavior; this app owns local content, configuration, adapters, and site-specific routes.

Use these instructions when an AI coding agent edits this app.

Architecture

  • Runtime features come from @vercel/geistdocs, including the docs page renderer, layout helpers, MDX components, search, Ask AI, markdown routes, proxy helpers, and source helpers.
  • @vercel/geistdocs owns the Ask AI client, server route behavior, and AI SDK v6 runtime dependencies. Do not fork package internals to fit an older app-level ai version.
  • Local files are user-owned adapters. They should stay thin and call public package exports from @vercel/geistdocs/*.
  • Do not copy package internals into the app to make a customization. Prefer configuring an adapter file or upgrading @vercel/geistdocs.
  • Do not deep import from @vercel/geistdocs/dist or edit files in node_modules/@vercel/geistdocs.
  • Do not edit generated directories such as .source/, .next/, node_modules/, or build output.

Package docs for agents

  • When package API behavior is unclear, read the installed package docs in node_modules/@vercel/geistdocs/docs before guessing.
  • Start with node_modules/@vercel/geistdocs/docs/agents.md and node_modules/@vercel/geistdocs/docs/sitemap.md to identify the relevant focused page.
  • Use node_modules/@vercel/geistdocs/docs/pages/*.md for task-specific guidance and node_modules/@vercel/geistdocs/docs/llms.txt only when you need broad package context.
  • These package docs are read-only generated artifacts. Do not edit files under node_modules/@vercel/geistdocs; change local adapter files or update the package instead.

Common edit targets

Task Edit
Configure site title, logo, nav, GitHub links, AI prompt, suggestions, translations, basePath, siteId, or agent-readiness metadata geistdocs.tsx
Add or update documentation pages content/docs/**/*.mdx
Add or update adapter listing pages content/adapters/**/*.mdx and adapters.json
Control sidebar order, groups, and folder labels content/docs/meta.json, content/adapters/meta.json
Give a page a shorter navigation label Set navTitle in the page's frontmatter
Override MDX components components/geistdocs/mdx-components.tsx
Wrap the site provider, analytics, or global client behavior components/geistdocs/provider.tsx
Customize the docs layout shells components/geistdocs/docs-layout.tsx, components/geistdocs/adapters-docs-layout.tsx, components/geistdocs/home-layout.tsx
Configure the Fumadocs source adapters lib/geistdocs/source.ts, lib/geistdocs/adapters-source.ts
Configure Fumadocs collections and source-safe MDX processing source.config.ts
Configure the docs page renderer app/[lang]/docs/[[...slug]]/page.tsx
Configure AI-readable markdown output app/[lang]/agents.md/route.ts, app/[lang]/llms.txt/route.ts (curated index), app/[lang]/llms-full.txt/route.ts, app/[lang]/llms.mdx/[[...slug]]/route.ts, app/[lang]/adapters.mdx/[[...slug]]/route.ts, app/[lang]/sitemap.md/route.ts
Configure chat or search APIs app/api/chat/route.ts, app/api/search/route.ts
Add request handling before or after Geistdocs routing proxy.ts
Edit the marketing home page app/[lang]/(home)/**
Edit shared styles app/global.css, app/styles/geistdocs.css

Content guidelines

  • Put docs in content/docs and adapter pages in content/adapters.
  • Add each new page to the directory's meta.json so it appears in the sidebar.
  • Use MDX frontmatter with at least title and description for documentation pages. Set navTitle only when the navigation label should differ from the page heading.
  • Keep slugs stable unless the task explicitly includes redirects or link updates.
  • Use CopyPrompt when a page should give readers a prompt they can copy into a coding agent.

Routing and proxy guidelines

  • Keep App Router route files as thin adapters around package helpers such as createDocsPage, createChatRoute, createProxy, and the route factories under @vercel/geistdocs/routes/*.
  • Keep cacheComponents: true and partialPrefetching: true in next.config.ts. Do not export dynamic, revalidate, or fetchCache from App Router pages or route handlers; package route factories may still return them, so destructure only GET and generateStaticParams. Cache custom data with "use cache" and cacheLife instead.
  • Read [lang] from next/root-params (via lib/geistdocs/root-params.ts) in Server Components. Keep route context params in Route Handlers and Server Actions.
  • Keep generateStaticParams for the root lang param in app/[lang]/layout.tsx; it must return every configured language.
  • Use prefetch={true} for app-owned links to fully static documentation pages so navigation does not stop at the generic route shell.
  • Keep export const config in proxy.ts as a static object. Next.js must parse proxy matchers at build time.
  • Use proxy matcher exclusions that only match /api and /api/..., such as api(?:/|$). Do not exclude broad prefixes like api, because that also excludes routes such as /api-reference.
  • Preserve markdown negotiation unless the task explicitly changes AI-readable output. This site serves /agents.md, /llms.txt, /llms-full.txt, /sitemap.md, and per-page Markdown for .md, .mdx, Accept: text/markdown, and AI-agent requests across both the /docs and /adapters families.
  • When adding custom proxy behavior, prefer before, after, and markdownRoutes options on createProxy instead of replacing the proxy. This site maps /docs/* and /adapters/* explicitly because the two families use different markdown route handlers.
  • llms.txt is a curated index with section descriptions; do not replace it with the concatenated createLlmsRoute output. llms-full.txt serves the concatenated corpus.
  • /.well-known/mcp.json intentionally returns 404; no MCP server is configured for this site.
  • /sitemap.xml is served by an external rewrite in next.config.ts, not an app route.

Ask AI guidelines

  • Leave GEISTDOCS_CHAT_PROXY_URL unset to use the default AI Gateway path. The route adapter pins the model with createChatRoute({ model }).
  • Geistdocs Ask AI targets AI SDK v6: ai v6 and @ai-sdk/react v3. Keep those dependencies on the package-pinned versions unless a @vercel/geistdocs release changes them.
  • Keep app/api/chat/route.ts as a thin adapter around createChatRoute.

Package updates

  • Use pnpm exec geistdocs update to update the @vercel/geistdocs dependency. It does not overwrite local adapter files — diff them against the bundled template in node_modules/@vercel/geistdocs/template after every upgrade.
  • Review dependency changes and run the verification commands before committing an update.

Commands

Run from the repository root:

  • Start development: pnpm --filter docs dev
  • Build for production: pnpm --filter docs build
  • Start the built app: pnpm --filter docs start
  • Regenerate Fumadocs output after dependency installation: pnpm --filter docs postinstall

Verification

  • Run pnpm --filter docs build after changing routes, config, source setup, MDX components, or package versions, and confirm every known docs and adapter URL still has a complete static prerender.
  • Run pnpm --filter docs start and open the changed pages when visual layout, navigation, or MDX rendering changes.
  • Check both /docs and AI-readable routes such as /agents.md, /llms.txt, /sitemap.md, or a page-level .md URL when changing content routing or proxy behavior.
  • Confirm no secrets were added to source files. Use .env.local for local values and keep it out of Git.