Files
zitadel/apps/docs/app/[[...slug]]/layout.tsx
T
Florian ForsterandGitHub 24d0f34f39 perf: optimize docs static generation cost (#12108)
## Summary
- Switch the docs catch-all route to full static generation and prebuild
both latest and versioned docs paths.
- Prebuild OG images for all docs pages, make sitemap and LLM export
static, and remove nondeterministic sitemap timestamps.
- Reduce build-time overhead by memoizing docs sidebar trees and
skipping processed markdown generation for versioned docs.

## Testing
- `pnpm nx run @zitadel/docs:build`
- `pnpm nx run @zitadel/docs:lint`
- `pnpm nx run @zitadel/docs:check-types`
- Verified the prerender manifest contains 8,816 prerendered routes,
3,293 versioned docs routes, 4,406 OG routes, and zero revalidating docs
routes.
2026-04-27 15:34:00 +00:00

74 lines
2.3 KiB
TypeScript

import { getAllDocPages, source, versionSource } from '@/lib/source';
import { ReactNode } from 'react';
import { DocsLayout } from 'fumadocs-ui/layouts/docs';
import { baseOptions } from '@/lib/layout.shared';
import { buildCustomTree } from '@/lib/custom-tree';
import rawVersions from '@/content/versions.json';
import { VersionSelector } from '@/components/version-selector';
type DocVersion = { param: string };
type PageTree = typeof source.pageTree;
const versions = rawVersions as DocVersion[];
const versionParams = new Set(versions.map((version) => version.param));
const labelsMap = new Map<string, string>();
for (const page of getAllDocPages()) {
if (page.data.sidebar_label) {
labelsMap.set(page.url, page.data.sidebar_label);
}
}
const latestTree = buildCustomTree(source.pageTree, { labels: labelsMap });
const versionTreeCache = new Map<string, PageTree>();
function getVersionTree(currentVersion: string): PageTree {
const cached = versionTreeCache.get(currentVersion);
if (cached) return cached;
const children = (versionSource.pageTree as any).children || [];
const versionFolder = children.find((node: any) => {
if (node.type !== 'folder') return false;
if (node.index?.url && node.index.url.includes(`/${currentVersion}`)) return true;
return Boolean(node.children?.[0]?.url?.includes(`/${currentVersion}`));
});
const tree = versionFolder
? buildCustomTree(
{
name: versionFolder.name,
children: versionFolder.children,
} as any,
{
stripPrefix: `/${currentVersion}`,
labels: labelsMap,
},
)
: buildCustomTree(versionSource.pageTree, { labels: labelsMap });
versionTreeCache.set(currentVersion, tree);
return tree;
}
export default async function Layout(props: { children: ReactNode; params: Promise<{ slug?: string[] }> }) {
const params = await props.params;
const slug = params.slug || [];
const currentVersion = slug[0] && versionParams.has(slug[0]) ? slug[0] : 'latest';
const tree = currentVersion === 'latest' ? latestTree : getVersionTree(currentVersion);
return (
<DocsLayout
tree={tree}
{...baseOptions()}
sidebar={{
banner: (
<VersionSelector />
),
}}
>
{props.children}
</DocsLayout>
);
}