Section index card grids (e.g. foundations) were hand-written and drifted
from the sidebar (meta.json) and the actual pages. Make them derive from
the fumadocs page tree (single source of truth) and add CI lint so the
card grid and navigation can't fall out of sync again.
- resolveSectionChildren + <AutoCards/>, bound in both v4 and v5 docs
routes (correct /docs vs /v5/docs URL spaces)
- getLLMText expands <AutoCards/> so llms.txt/.md/copy-page keep child links
- manualCards frontmatter opt-out for curated pages (source.config.ts)
- checkSectionCards (card<->nav completeness) + checkMetaEntriesResolve
(dangling meta entries) in scripts/lint.ts
- convert foundations + errors (drift fixes) and v5 observability to AutoCards
- mark deploying + ai as manualCards (intentionally curated)
- remove dangling meta entries: v4 cancellation (x2), root introduction
(x2), v4/internal serializable-abort-controller
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
* docs: split v4/v5 content, fix version switcher end-to-end
## Content restructuring
- Split `docs/content/docs/` into `docs/content/docs/v4/` and
`docs/content/docs/v5/` so each version is a fully independent
content tree with no shared-file coupling
- v4 excludes the four pages that are v5-only (AbortController
cancellation docs and the serializable-abort-controller internal page)
- v5 retains all pages; `preRelease` frontmatter field removed (no
longer needed now that each version is its own folder)
- Removed `AbortController` / `AbortSignal` from v4 serialization page
(section moved to v5 only)
## Fumadocs source
- Added `v4docs` and `v5docs` as separate `defineDocs()` collections in
`source.config.ts`; shared `docsSchema` (no more `preRelease` field)
- `source.ts` exports both `source` (v4, `baseUrl: /docs`) and
`v5Source` (v5, same base URL)
## Version routing
- `version-source.ts` simplified: `filterPreReleaseFromNodes` and
`isPreReleaseUrl` logic removed; v4 tree uses `source`, v5 tree uses
`v5Source` + `rewriteNodeUrls`
- v4 `page.tsx`: removed `preRelease` guard (v4Source has no such pages)
- v5 `page.tsx`: uses `v5Source` for `getPage` / `generateStaticParams`
/ `generateMetadata`; `v5Link` wrapper rewrites `/docs/…` hrefs to
`/v5/docs/…` so inline MDX links stay in the v5 context
## Versioned cookbook
- Added `app/[lang]/v5/cookbook/` layout + page (mirrors v4 but uses
`v5Source`, `rewriteCookbookUrlForVersion`, and `V5CookbookLink`)
- `getCookbookTree` accepts a `versionPrefix` parameter; sidebar URLs
are prefixed accordingly (`/v5/cookbook/…`)
- `cookbook-tree.ts`: added `skipVersions?: string[]` per-recipe field
for version-specific exclusions; `distributed-abort-controller` is
marked `skipVersions: ['v5']`
## Version switcher — state & navigation
- New `VersionProvider` context (`hooks/geistdocs/use-version.tsx`)
backed by `localStorage`: URL is source of truth on versioned pages,
`localStorage` carries the preference across non-versioned pages
(cookbook overview, worlds, etc.)
- `VersionSwitcher` uses `useVersion()` context instead of URL-only
detection; now visible on all pages including cookbook
- `DesktopMenu` and `MobileMenu` use `activeVersion` from context so
the "Docs" and "Cookbook" navbar links resolve to the correct version
prefix on every page
- `buildVersionUrl` expanded to handle `/cookbook/…` paths alongside
`/docs/…`; non-versioned routes (worlds, api) return unchanged
- `switchVersion` does a `HEAD` probe before navigating; falls back to
the versioned cookbook or docs home if the target page doesn't exist
in that version (handles v4-only → v5 and v5-only → v4 cases)
## Cookbook content (v5)
- Rewrote `agent-cancellation` recipe using a single `AbortController`
pattern; removed Hard Cancellation vs Stop Signal two-approach
comparison
- Deleted `distributed-abort-controller` recipe from v5 (native
`AbortController` serialization makes it unnecessary)
- Removed references to distributed-abort-controller from
`cookbook/index.mdx` and `common-patterns/timeouts.mdx`
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(docs): use abortSignal (not signal) in DurableAgent.stream() options
Co-authored-by: Cursor <cursoragent@cursor.com>
* fix(docs): update prepack scripts to use versioned content paths
Content moved from docs/content/docs/ to docs/content/docs/v5/ on main
(pre-release channel). Stable branch will use v4/ after backport.
Co-authored-by: Cursor <cursoragent@cursor.com>
---------
Co-authored-by: Cursor <cursoragent@cursor.com>
* changeset
Signed-off-by: voyager14 <21mh124@queensu.ca>
* refactor OG image generation into shared utility
Signed-off-by: voyager14 <21mh124@queensu.ca>
* fix og image height mismatch
Signed-off-by: voyager14 <21mh124@queensu.ca>
* fix: add missing getPageImage and include OG assets in Vercel output
Signed-off-by: voyager14 <21mh124@queensu.ca>
* exclude og in middleware
Signed-off-by: voyager14 <21mh124@queensu.ca>
* fix(docs): wire up OpenGraph images for docs pages
Complete the OG image integration that was started in PR #858:
- Add openGraph.images metadata to docs page generateMetadata using
the getPageImage helper from source.ts
- Add metadataBase to the root layout so Next.js can resolve OG URLs
- Remove unused generatePageMetadata helper from docs-page.tsx
This ensures docs pages like /docs/how-it-works/event-sourcing have
proper OpenGraph images when shared on social media.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
* fix(docs): use dynamic OG image for homepage
The static opengraph-image.png at the app root wasn't being served
because all routes are under [lang]/. Next.js OG images need to be
in the same route segment as the page they apply to.
- Create dynamic opengraph-image.tsx in [lang]/(home)/ using the
shared createOgImage utility
- Remove the unused static opengraph-image.png from app root
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): use dynamic metadataBase for preview deployments
The metadataBase was hardcoded to useworkflow.dev, which caused
preview deployments to generate OG image URLs pointing to production
instead of the preview URL.
Now uses:
- Production: https://useworkflow.dev
- Preview: https://${VERCEL_URL}
- Local dev: http://localhost:3000
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): address PR review comments for OG images
- Fix semibold font weight from 500 to 600 (semibold is weight 600)
- Extract OG_IMAGE_SIZE constant to lib/og/index.tsx for consistency
- Use shared constant in all opengraph-image.tsx files
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): match OG image styling to production design
- Fix title styling: "Workflow:" in white, rest in grey (#888888)
- Remove description from homepage OG image
- Adjust positioning and font size to match expected design
- Reduce text width to prevent overflow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): add display flex for Satori multi-child divs
Satori requires explicit display: flex on divs with multiple children.
Added flex flex-wrap to the title div containing the two spans.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): simplify OG image layout with stacked title
Use separate divs for "Workflow:" and title instead of trying to
inline them with flex-wrap, which was causing layout issues in Satori.
- "Workflow:" on first line in white
- Title on second line in grey
- Reduced font size slightly to prevent overflow
- Properly stacked with flex-col layout
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): correct OG image positioning below background Workflow: text
The background.png already contains "Workflow:" text, so we only need
to render the dynamic title positioned below it.
- Remove hardcoded "Workflow:" from JSX (it's in the background image)
- Adjust top positioning to 290px to place title below background text
- Restore textWrap: balance for proper text flow
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): align OG title with background Workflow: text
Position and size title to match background image's Workflow: text,
using non-breaking spaces for horizontal offset so title flows inline.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): restore debug border on OG image container
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): add homepage OG route and fix positioning
- Add /og route for homepage OG image (avoids i18n middleware conflict)
- Remove broken opengraph-image.tsx that conflicted with middleware
- Add explicit openGraph metadata to homepage
- Restore debug border for positioning
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): add OG routes for worlds pages
- Add /og/worlds route for worlds listing page
- Add /og/worlds/[id] route for individual world pages
- Remove broken opengraph-image.tsx that conflicted with i18n middleware
- Add explicit openGraph metadata to worlds pages
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix(docs): remove badge from worlds OG images
Badge was causing layout issues with title positioning.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add descriptions to AI, foundations, how-it-works, deploying, and observability pages
Add terse descriptions for OG image rendering to:
- 8 AI docs
- 9 foundations docs
- 4 how-it-works docs
- 5 deploying docs
- 1 observability doc
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: add descriptions to API reference, errors, and remaining getting-started pages
Add terse descriptions for OG image rendering to:
- 23 API reference docs (workflow, workflow/api, @workflow/ai, workflow/next)
- 9 errors docs
- 5 getting-started docs (Astro, Express, Fastify, NestJS, Vite)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Signed-off-by: voyager14 <21mh124@queensu.ca>
Signed-off-by: Pranay Prakash <pranay.gp@gmail.com>
Co-authored-by: voyager14 <21mh124@queensu.ca>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>