Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
0c7e602
Add cookbook section with 50 workflow pattern recipes
johnlindquist Mar 30, 2026
1ece03c
ploop: iteration 1 checkpoint
johnlindquist Mar 31, 2026
b0d41ff
fix: polish cookbook public routing
johnlindquist Mar 31, 2026
ee038ac
docs: canonicalize cookbook doc routes
johnlindquist Mar 31, 2026
74f39e2
ploop: iteration 4 checkpoint
johnlindquist Mar 31, 2026
7d8df61
fix(docs): finalize cookbook route split
johnlindquist Mar 31, 2026
19ae735
docs: improve cookbook discovery
johnlindquist Mar 31, 2026
11ce0b4
docs: refine cookbook pattern examples
johnlindquist Mar 31, 2026
dda6cbc
docs: decouple cookbook sidebar tree
johnlindquist Mar 31, 2026
2082142
fix(docs): align cookbook public nav
johnlindquist Mar 31, 2026
eb3245f
refactor(docs): decouple cookbook routing
johnlindquist Mar 31, 2026
acc7132
docs: improve cookbook explorer accessibility
johnlindquist Mar 31, 2026
e8b0371
ploop: iteration 12 checkpoint
johnlindquist Mar 31, 2026
896a793
docs: rename cookbooks route to cookbook (singular)
johnlindquist Mar 31, 2026
4870833
docs: add 5 cookbook overview design variations
johnlindquist Mar 31, 2026
24b5678
docs: remove unrelated package.json bumps and generated artifacts
johnlindquist Mar 31, 2026
e52b219
docs: restructure cookbook from 50 recipes into 27 consolidated pages
johnlindquist Mar 31, 2026
b5d2ff1
docs: add workflow migration guides
johnlindquist Apr 1, 2026
2956876
ploop: iteration 2 checkpoint
johnlindquist Apr 1, 2026
62d28bc
docs: refine workflow migration guides
johnlindquist Apr 1, 2026
d2601c5
ploop: iteration 1 checkpoint
johnlindquist Apr 1, 2026
df53e0c
docs(skill): refine workflow migration guidance
johnlindquist Apr 1, 2026
22f9bf3
ploop: iteration 3 checkpoint
johnlindquist Apr 1, 2026
0bb7dbb
docs(skills): refine workflow migration guidance
johnlindquist Apr 1, 2026
aaae3ca
docs: add workflow deep-dive references
johnlindquist Apr 1, 2026
a0df63f
ploop: iteration 5 checkpoint
johnlindquist Apr 1, 2026
e606078
docs: normalize deep-dive related links
johnlindquist Apr 1, 2026
eb7100e
docs(skill): refine workflow migration routing
johnlindquist Apr 1, 2026
2c87fcc
docs: refine workflow migration skill guidance
johnlindquist Apr 1, 2026
e0e5e28
docs: checkpoint deep-dive drafts
johnlindquist Apr 1, 2026
a3a86c0
docs(skills): tighten workflow migration routing
johnlindquist Apr 1, 2026
6c2fc01
docs: finalize workflow deep dives
johnlindquist Apr 1, 2026
8cba095
docs(skills): refine workflow migration routing
johnlindquist Apr 1, 2026
2f66de2
docs: sync compiler deep-dive runtime details
johnlindquist Apr 1, 2026
9fb5fcd
docs(skill): tighten workflow migration guidance
johnlindquist Apr 1, 2026
727fa65
docs: tighten workflow migration guidance
johnlindquist Apr 1, 2026
977075f
docs: refine streaming and cost deep dives
johnlindquist Apr 1, 2026
294acf6
ploop: iteration 12 checkpoint
johnlindquist Apr 1, 2026
59f58f0
docs: tighten deep-dive streaming accuracy
johnlindquist Apr 1, 2026
c359fed
docs(skills): refine callback resume taxonomy
johnlindquist Apr 1, 2026
0bf15f0
docs: refine deep-dive runtime wording
johnlindquist Apr 1, 2026
c927115
docs: clarify webhook response mode defaults
johnlindquist Apr 1, 2026
7892c40
docs: align cost model wake-up semantics
johnlindquist Apr 1, 2026
110dc1d
ploop: iteration 10 checkpoint
johnlindquist Apr 1, 2026
4ed153e
docs: clarify webhook resume choices
johnlindquist Apr 1, 2026
0ed7525
docs: tighten cost model deep dives
johnlindquist Apr 1, 2026
ac73ba7
docs(skills): tighten resume routing guidance
johnlindquist Apr 1, 2026
cb2173c
docs: tighten deep-dive runtime claims
johnlindquist Apr 1, 2026
195a12d
docs: correct cost model deep dive claims
johnlindquist Apr 1, 2026
bf10a7f
chore: remove non-cookbook files from cookbook branch
johnlindquist Apr 1, 2026
151747c
docs: address toolbar feedback on cookbook pages
johnlindquist Apr 6, 2026
59d2c66
docs: simplify cookbook index to plain MDX listing
johnlindquist Apr 6, 2026
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
132 changes: 132 additions & 0 deletions docs/app/[lang]/cookbook/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { Step, Steps } from 'fumadocs-ui/components/steps';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import type { ComponentProps } from 'react';
import {
rewriteCookbookUrl,
rewriteCookbookUrlsInText,
} from '@/lib/geistdocs/cookbook-source';
import { AskAI } from '@/components/geistdocs/ask-ai';
import { CopyPage } from '@/components/geistdocs/copy-page';
import {
DocsBody,
DocsDescription,
DocsPage,
DocsTitle,
} from '@/components/geistdocs/docs-page';
import { EditSource } from '@/components/geistdocs/edit-source';
import { Feedback } from '@/components/geistdocs/feedback';
import { getMDXComponents } from '@/components/geistdocs/mdx-components';
import { OpenInChat } from '@/components/geistdocs/open-in-chat';
import { ScrollTop } from '@/components/geistdocs/scroll-top';
import { Badge } from '@/components/ui/badge';
import { Separator } from '@/components/ui/separator';
import { getLLMText, getPageImage, source } from '@/lib/geistdocs/source';

const Page = async ({ params }: PageProps<'/[lang]/cookbook/[[...slug]]'>) => {
const { slug, lang } = await params;

// Prepend 'cookbook' to resolve from the docs source
const resolvedSlug = slug ? ['cookbook', ...slug] : ['cookbook'];
const page = source.getPage(resolvedSlug, lang);

if (!page) {
notFound();
}

const publicUrl = rewriteCookbookUrl(page.url);
const publicPage = { ...page, url: publicUrl } as typeof page;

const markdown = rewriteCookbookUrlsInText(await getLLMText(page));
const MDX = page.data.body;

const RelativeLink = createRelativeLink(source, publicPage);
const PublicCookbookLink = (props: ComponentProps<typeof RelativeLink>) => {
const href =
typeof props.href === 'string'
? rewriteCookbookUrl(props.href)
: props.href;
return <RelativeLink {...props} href={href} />;
};

return (
<DocsPage
full={page.data.full}
tableOfContent={{
style: 'clerk',
footer: (
<div className="my-3 space-y-3">
<Separator />
<EditSource path={page.path} />
<ScrollTop />
<Feedback />
<CopyPage text={markdown} />
<AskAI href={publicUrl} />
<OpenInChat href={publicUrl} />
</div>
),
}}
toc={page.data.toc}
>
<DocsTitle>{page.data.title}</DocsTitle>
<DocsDescription>{page.data.description}</DocsDescription>
<DocsBody>
<MDX
components={getMDXComponents({
a: PublicCookbookLink,
Badge,
Step,
Steps,
Tabs,
Tab,
})}
/>
</DocsBody>
</DocsPage>
);
};

export const generateStaticParams = () => {
// Generate params for all cookbook pages
const allParams = source.generateParams();
return allParams
.filter((p) => Array.isArray(p.slug) && p.slug[0] === 'cookbook')
.map((p) => ({
...p,
slug: (p.slug as string[]).slice(1), // Remove 'cookbook' prefix
}));
};

export const generateMetadata = async ({
params,
}: PageProps<'/[lang]/cookbook/[[...slug]]'>) => {
const { slug, lang } = await params;
const resolvedSlug = slug ? ['cookbook', ...slug] : ['cookbook'];
const page = source.getPage(resolvedSlug, lang);

if (!page) {
notFound();
}

const publicPath = rewriteCookbookUrl(page.url);

const metadata: Metadata = {
title: page.data.title,
description: page.data.description,
openGraph: {
images: getPageImage(page).url,
},
alternates: {
canonical: publicPath,
types: {
'text/markdown': `${publicPath}.md`,
},
},
};

return metadata;
};

export default Page;
13 changes: 13 additions & 0 deletions docs/app/[lang]/cookbook/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { DocsLayout } from '@/components/geistdocs/docs-layout';
import { getCookbookTree } from '@/lib/geistdocs/cookbook-source';

const Layout = async ({
children,
params,
}: LayoutProps<'/[lang]/cookbook'>) => {
const { lang } = await params;

return <DocsLayout tree={getCookbookTree(lang)}>{children}</DocsLayout>;
};

export default Layout;
17 changes: 15 additions & 2 deletions docs/app/[lang]/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@ import { Step, Steps } from 'fumadocs-ui/components/steps';
import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import { createRelativeLink } from 'fumadocs-ui/mdx';
import type { Metadata } from 'next';
import { notFound } from 'next/navigation';
import { notFound, permanentRedirect } from 'next/navigation';
import { rewriteCookbookUrl } from '@/lib/geistdocs/cookbook-source';
import { AgentTraces } from '@/components/custom/agent-traces';
import { FluidComputeCallout } from '@/components/custom/fluid-compute-callout';
import { AskAI } from '@/components/geistdocs/ask-ai';
Expand Down Expand Up @@ -31,6 +32,12 @@ const WorldTestingPerformanceNoop = () => null;
const Page = async ({ params }: PageProps<'/[lang]/docs/[[...slug]]'>) => {
const { slug, lang } = await params;

if (Array.isArray(slug) && slug[0] === 'cookbook') {
const rest = slug.slice(1).join('/');
const legacyPath = `/docs/cookbook${rest ? `/${rest}` : ''}`;
permanentRedirect(`/${lang}${rewriteCookbookUrl(legacyPath)}`);
}

const page = source.getPage(slug, lang);

if (!page) {
Expand Down Expand Up @@ -85,7 +92,13 @@ const Page = async ({ params }: PageProps<'/[lang]/docs/[[...slug]]'>) => {
);
};

export const generateStaticParams = () => source.generateParams();
export const generateStaticParams = () =>
source
.generateParams()
.filter(
(params) =>
!(Array.isArray(params.slug) && params.slug[0] === 'cookbook'),
);

export const generateMetadata = async ({
params,
Expand Down
8 changes: 6 additions & 2 deletions docs/app/[lang]/docs/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { DocsLayout } from '@/components/geistdocs/docs-layout';
import { source } from '@/lib/geistdocs/source';
import { getDocsTreeWithoutCookbook } from '@/lib/geistdocs/cookbook-source';

const Layout = async ({ children, params }: LayoutProps<'/[lang]/docs'>) => {
const { lang } = await params;

return <DocsLayout tree={source.pageTree[lang]}>{children}</DocsLayout>;
return (
<DocsLayout tree={getDocsTreeWithoutCookbook(lang)}>
{children}
</DocsLayout>
);
};

export default Layout;
5 changes: 4 additions & 1 deletion docs/app/[lang]/llms.mdx/[[...slug]]/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { notFound } from 'next/navigation';
import { rewriteCookbookUrlsInText } from '@/lib/geistdocs/cookbook-source';
import { getLLMText, source } from '@/lib/geistdocs/source';
import { i18n } from '@/lib/geistdocs/i18n';

Expand All @@ -18,8 +19,10 @@ export async function GET(
const sitemapPath =
lang === i18n.defaultLanguage ? '/sitemap.md' : `/${lang}/sitemap.md`;

const text = await getLLMText(page);

return new Response(
(await getLLMText(page)) +
rewriteCookbookUrlsInText(text) +
`\n\n## Sitemap
[Overview of all docs pages](${sitemapPath})\n`,
{
Expand Down
3 changes: 2 additions & 1 deletion docs/app/[lang]/llms.txt/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { NextRequest } from 'next/server';
import { rewriteCookbookUrlsInText } from '@/lib/geistdocs/cookbook-source';
import { getLLMText, source } from '@/lib/geistdocs/source';

export const revalidate = false;
Expand All @@ -11,7 +12,7 @@ export const GET = async (
const scan = source.getPages(lang).map(getLLMText);
const scanned = await Promise.all(scan);

return new Response(scanned.join('\n\n'), {
return new Response(rewriteCookbookUrlsInText(scanned.join('\n\n')), {
headers: {
'Content-Type': 'text/markdown; charset=utf-8',
},
Expand Down
6 changes: 3 additions & 3 deletions docs/app/[lang]/sitemap.md/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Node, Root } from 'fumadocs-core/page-tree';
import { rewriteCookbookUrl } from '@/lib/geistdocs/cookbook-source';
import { source } from '@/lib/geistdocs/source';

export const revalidate = false;
Expand All @@ -16,10 +17,10 @@ export async function GET(

if ('type' in node) {
if (node.type === 'page') {
mdText += `${indent}- [${node.name}](${node.url})\n`;
mdText += `${indent}- [${node.name}](${rewriteCookbookUrl(node.url)})\n`;
} else if (node.type === 'folder') {
if (node.index) {
mdText += `${indent}- [${node.name}](${node.index.url})\n`;
mdText += `${indent}- [${node.name}](${rewriteCookbookUrl(node.index.url)})\n`;
} else {
mdText += `${indent}- ${node.name}\n`;
}
Expand All @@ -30,7 +31,6 @@ export async function GET(
}
}
} else if (node.children.length > 0) {
// Root node
for (const child of node.children) {
traverseTree(child, depth);
}
Expand Down
6 changes: 3 additions & 3 deletions docs/app/sitemap.md/route.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { Node, Root } from 'fumadocs-core/page-tree';
import { rewriteCookbookUrl } from '@/lib/geistdocs/cookbook-source';
import { i18n } from '@/lib/geistdocs/i18n';
import { source } from '@/lib/geistdocs/source';

Expand All @@ -13,10 +14,10 @@ export async function GET(_req: Request) {

if ('type' in node) {
if (node.type === 'page') {
mdText += `${indent}- [${node.name}](${node.url})\n`;
mdText += `${indent}- [${node.name}](${rewriteCookbookUrl(node.url)})\n`;
} else if (node.type === 'folder') {
if (node.index) {
mdText += `${indent}- [${node.name}](${node.index.url})\n`;
mdText += `${indent}- [${node.name}](${rewriteCookbookUrl(node.index.url)})\n`;
} else {
mdText += `${indent}- ${node.name}\n`;
}
Expand All @@ -27,7 +28,6 @@ export async function GET(_req: Request) {
}
}
} else if (node.children.length > 0) {
// Root node
for (const child of node.children) {
traverseTree(child, depth);
}
Expand Down
3 changes: 2 additions & 1 deletion docs/app/sitemap.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { MetadataRoute } from 'next';

import { rewriteCookbookUrl } from '@/lib/geistdocs/cookbook-source';
import { source } from '@/lib/geistdocs/source';

const protocol = process.env.NODE_ENV === 'production' ? 'https' : 'http';
Expand All @@ -17,7 +18,7 @@ export default function sitemap(): MetadataRoute.Sitemap {
changeFrequency: 'weekly' as const,
lastModified: undefined,
priority: 0.5,
url: url(page.url),
url: url(rewriteCookbookUrl(page.url)),
});
}

Expand Down
Loading
Loading