Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 2 additions & 0 deletions .changeset/docs-v5-default-version.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
---
---
2 changes: 1 addition & 1 deletion docs/app/[lang]/cookbook/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ const docsPage = createDocsPage({
...config,
github: config.github && {
...config.github,
editPath: 'docs/content/docs/v4/{path}',
editPath: 'docs/content/docs/v5/{path}',
},
},
source: cookbookSource,
Expand Down
2 changes: 1 addition & 1 deletion docs/app/[lang]/docs/[[...slug]]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const docsPage = createDocsPage({
...config,
github: config.github && {
...config.github,
editPath: 'docs/content/docs/v4/{path}',
editPath: 'docs/content/docs/v5/{path}',
},
},
source: geistdocsSource,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,40 @@ import { Card, type CardProps } from 'fumadocs-ui/components/card';
import type { ComponentProps, ComponentType } from 'react';
import { getMDXComponents } from '@/components/geistdocs/mdx-components';
import { config } from '@/lib/geistdocs/config';
import { v5CookbookSource } from '@/lib/geistdocs/source';
import { v4CookbookSource } from '@/lib/geistdocs/source';
import { rewriteHrefForVersion } from '@/lib/geistdocs/version-href';

const VERSION_PREFIX = '/v5';
const VERSION_PREFIX = '/v4';

// Content links are authored against the raw `/docs/...` and `/worlds/...`
// URL spaces; rewrite them into the v5 view so navigation doesn't escape to
// the v4 route. Card renders its own Link (not the `a` component), so it
// needs the same rewrite applied separately.
function v5Href<T>(href: T): T {
// URL spaces; rewrite them into the v4 view so navigation doesn't escape to
// the current-version route. Card renders its own Link (not the `a`
// component), so it needs the same rewrite applied separately.
function v4Href<T>(href: T): T {
return rewriteHrefForVersion(href, VERSION_PREFIX);
}

function V5CookbookCard(props: CardProps) {
return <Card {...props} href={v5Href(props.href)} />;
function V4CookbookCard(props: CardProps) {
return <Card {...props} href={v4Href(props.href)} />;
}

const docsPage = createDocsPage({
config: {
...config,
github: config.github && {
...config.github,
editPath: 'docs/content/docs/v5/{path}',
editPath: 'docs/content/docs/v4/{path}',
},
},
source: v5CookbookSource,
mdx: ({ link }) => getMDXComponents({ a: link, Card: V5CookbookCard }),
source: v4CookbookSource,
mdx: ({ link }) => getMDXComponents({ a: link, Card: V4CookbookCard }),
resolveLink: ({ link }) => {
const Link = link as ComponentType<ComponentProps<'a'>>;
const V5CookbookLink = (props: ComponentProps<'a'>) => (
<Link {...props} href={v5Href(props.href)} />
const V4CookbookLink = (props: ComponentProps<'a'>) => (
<Link {...props} href={v4Href(props.href)} />
);

return V5CookbookLink;
return V4CookbookLink;
},
openGraph: {
images: true,
Expand All @@ -47,14 +47,14 @@ const docsPage = createDocsPage({
},
renderTop: ({ data }) => <MobileDocsBar toc={data.toc} />,
metadata: ({ metadata, page }) => {
const stableUrl = page.url.replace(/^\/v5(?=\/cookbook(?:\/|$))/, '');
const currentUrl = page.url.replace(/^\/v4(?=\/cookbook(?:\/|$))/, '');

return {
...metadata,
title: `${page.data.title} · Pre-release`,
title: `${page.data.title} · v4`,
alternates: {
...metadata.alternates,
canonical: stableUrl,
canonical: currentUrl,
types: {
...metadata.alternates?.types,
'text/markdown': `${page.url}.md`,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { DocsLayout } from '@/components/geistdocs/docs-layout';
import { PreReleaseBanner } from '@/components/geistdocs/pre-release-banner';
import { MaintenanceBanner } from '@/components/geistdocs/maintenance-banner';
import { getCookbookTree } from '@/lib/geistdocs/cookbook-source';
import { PRE_RELEASE_VERSION } from '@/lib/geistdocs/versions';
import { MAINTENANCE_VERSION } from '@/lib/geistdocs/versions';

const Layout = async ({
children,
params,
}: LayoutProps<'/[lang]/v5/cookbook'>) => {
}: LayoutProps<'/[lang]/v4/cookbook'>) => {
const { lang } = await params;
return (
<div className="bg-background-200">
<PreReleaseBanner pathname={`/${lang}/v5/cookbook`} />
<MaintenanceBanner pathname={`/${lang}/v4/cookbook`} />
<DocsLayout
currentVersion={PRE_RELEASE_VERSION.id}
currentVersion={MAINTENANCE_VERSION.id}
lang={lang}
tree={getCookbookTree(lang, PRE_RELEASE_VERSION.prefix)}
tree={getCookbookTree(lang, MAINTENANCE_VERSION.prefix)}
>
{children}
</DocsLayout>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,29 @@
import { DocsLayout } from '@/components/geistdocs/docs-layout';
import { PreReleaseBanner } from '@/components/geistdocs/pre-release-banner';
import { MaintenanceBanner } from '@/components/geistdocs/maintenance-banner';
import { getDocsTreeForVersion } from '@/lib/geistdocs/version-source';
import { PRE_RELEASE_VERSION } from '@/lib/geistdocs/versions';
import { MAINTENANCE_VERSION } from '@/lib/geistdocs/versions';

// This layout lives inside `[[...slug]]` rather than next to it so that
// `params.slug` is available: the sidebar needs the active page to decide
// whether to drill into a section. See `DocsLayout`.
const Layout = async ({
children,
params,
}: LayoutProps<'/[lang]/v5/docs/[[...slug]]'>) => {
}: LayoutProps<'/[lang]/v4/docs/[[...slug]]'>) => {
const { lang, slug } = await params;
return (
<div className="bg-background-200">
<PreReleaseBanner pathname={`/${lang}/v5/docs`} />
{/* Deep-link the banner to the same page on the latest version; pages
that only exist in v4 are caught by the version-switcher fallback
redirects in next.config.ts. */}
<MaintenanceBanner
pathname={`/${lang}/v4/docs${slug?.length ? `/${slug.join('/')}` : ''}`}
/>
<DocsLayout
activeSlug={slug}
currentVersion={PRE_RELEASE_VERSION.id}
currentVersion={MAINTENANCE_VERSION.id}
lang={lang}
tree={getDocsTreeForVersion(lang, PRE_RELEASE_VERSION)}
tree={getDocsTreeForVersion(lang, MAINTENANCE_VERSION)}
>
{children}
</DocsLayout>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,61 +8,61 @@ import { getMDXComponents } from '@/components/geistdocs/mdx-components';
import { config } from '@/lib/geistdocs/config';
import { rewriteCookbookUrl } from '@/lib/geistdocs/cookbook-source';
import { resolveSectionChildren } from '@/lib/geistdocs/section-children';
import { source, v5GeistdocsSource } from '@/lib/geistdocs/source';
import { source, v4GeistdocsSource } from '@/lib/geistdocs/source';
import { rewriteHrefForVersion } from '@/lib/geistdocs/version-href';
import { getDocsTreeForVersion } from '@/lib/geistdocs/version-source';
import { PRE_RELEASE_VERSION } from '@/lib/geistdocs/versions';
import { MAINTENANCE_VERSION } from '@/lib/geistdocs/versions';

const VERSION_PREFIX = '/v5';
const VERSION_PREFIX = '/v4';
const DEFAULT_LANG = config.defaultLanguage ?? 'en';

const getPageUrl = ({ page }: { page: { url: string } }) =>
`${VERSION_PREFIX}${page.url}`;

// Content links are authored against the raw `/docs/...` and `/worlds/...`
// URL spaces; rewrite them into the v5 view so navigation doesn't escape to
// the v4 route. Card renders its own Link (not the `a` component), so it
// needs the same rewrite applied separately.
function v5Href<T>(href: T): T {
// URL spaces; rewrite them into the v4 view so navigation doesn't escape to
// the current-version route. Card renders its own Link (not the `a`
// component), so it needs the same rewrite applied separately.
function v4Href<T>(href: T): T {
return rewriteHrefForVersion(href, VERSION_PREFIX);
}

function V5Card(props: CardProps) {
return <Card {...props} href={v5Href(props.href)} />;
function V4Card(props: CardProps) {
return <Card {...props} href={v4Href(props.href)} />;
}

const docsPage = createDocsPage({
config: {
...config,
github: config.github && {
...config.github,
editPath: 'docs/content/docs/v5/{path}',
editPath: 'docs/content/docs/v4/{path}',
},
},
source: v5GeistdocsSource,
source: v4GeistdocsSource,
getPageUrl,
mdx: ({ link, page }) =>
getMDXComponents({
a: link,
Card: V5Card,
// Cards render in the v5 URL space (`/v5/docs/...`), matching the
// sidebar tree so hrefs don't escape to the v4 route.
Card: V4Card,
// Cards render in the v4 URL space (`/v4/docs/...`), matching the
// sidebar tree so hrefs don't escape to the current-version route.
AutoCards: () => (
<AutoCards
items={resolveSectionChildren(
getDocsTreeForVersion(DEFAULT_LANG, PRE_RELEASE_VERSION),
getDocsTreeForVersion(DEFAULT_LANG, MAINTENANCE_VERSION),
`${VERSION_PREFIX}${page.url}`
)}
/>
),
}),
resolveLink: ({ link }) => {
const Link = link as ComponentType<ComponentProps<'a'>>;
const V5Link = (props: ComponentProps<'a'>) => (
<Link {...props} href={v5Href(props.href)} />
const V4Link = (props: ComponentProps<'a'>) => (
<Link {...props} href={v4Href(props.href)} />
);

return V5Link;
return V4Link;
},
openGraph: {
images: true,
Expand All @@ -76,9 +76,11 @@ const docsPage = createDocsPage({

return {
...metadata,
title: `${page.data.title} · Pre-release`,
title: `${page.data.title} · v4`,
alternates: {
...metadata.alternates,
// Prefer the current-version page when the same path exists there so
// search engines consolidate on the latest docs.
canonical: source.getPage(params.slug, params.lang)
? page.url
: pageUrl,
Expand All @@ -95,7 +97,7 @@ const docsPage = createDocsPage({
},
});

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

// Cookbook recipes moved out of `/docs/cookbook/...` into their own
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@ export async function generateMetadata({
params,
}: PageProps): Promise<Metadata> {
const { id } = await params;
return generateWorldMetadata(id, 'v5');
return generateWorldMetadata(id, 'v4');
}

export default async function Page({ params }: PageProps) {
const { id } = await params;
return <WorldDetailPage id={id} version="v5" />;
return <WorldDetailPage id={id} version="v4" />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
} from '@/components/worlds/worlds-guide-page';

export function generateMetadata(): Promise<Metadata> {
return generateWorldsGuideMetadata('building-a-world', 'v5');
return generateWorldsGuideMetadata('building-a-world', 'v4');
}

export default function Page() {
return <WorldsGuidePage slug="building-a-world" version="v5" />;
return <WorldsGuidePage slug="building-a-world" version="v4" />;
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { source } from '@/lib/geistdocs/source';
const Layout = async ({
children,
params,
}: LayoutProps<'/[lang]/v5/worlds'>) => {
}: LayoutProps<'/[lang]/v4/worlds'>) => {
const { lang } = await params;
return (
<HomeLayout tree={source.pageTree[lang]}>
Expand Down
4 changes: 2 additions & 2 deletions docs/app/[lang]/worlds/[id]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ export async function generateMetadata({
params,
}: PageProps): Promise<Metadata> {
const { id } = await params;
return generateWorldMetadata(id, 'v4');
return generateWorldMetadata(id, 'v5');
}

export default async function Page({ params }: PageProps) {
const { id } = await params;
return <WorldDetailPage id={id} version="v4" />;
return <WorldDetailPage id={id} version="v5" />;
}
4 changes: 2 additions & 2 deletions docs/app/[lang]/worlds/building-a-world/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import {
} from '@/components/worlds/worlds-guide-page';

export function generateMetadata(): Promise<Metadata> {
return generateWorldsGuideMetadata('building-a-world', 'v4');
return generateWorldsGuideMetadata('building-a-world', 'v5');
}

export default function Page() {
return <WorldsGuidePage slug="building-a-world" version="v4" />;
return <WorldsGuidePage slug="building-a-world" version="v5" />;
}
2 changes: 1 addition & 1 deletion docs/components/geistdocs/docs-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ type DocsTreeNode = DocsTree['children'][number];

const SIDEBAR_ITEM_BADGES: Array<{ suffix: string; label: string }> = [
{ suffix: '/docs/getting-started/python', label: 'Beta' },
{ suffix: '/v5/docs/getting-started/python', label: 'Beta' },
{ suffix: '/v4/docs/getting-started/python', label: 'Beta' },
];

const getSidebarBadge = (url?: string) =>
Expand Down
59 changes: 59 additions & 0 deletions docs/components/geistdocs/maintenance-banner.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Link from 'next/link';
import {
buildVersionUrl,
LATEST_VERSION,
MAINTENANCE_VERSION,
} from '@/lib/geistdocs/versions';

interface MaintenanceBannerProps {
pathname: string;
}

const ClockRewind = ({ className }: { className?: string }) => (
<svg
aria-hidden="true"
className={className}
fill="none"
height="16"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
viewBox="0 0 16 16"
width="16"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M8 4.5V8l2.5 1.5" />
<path d="M1.5 6.5V2.75" />
<path d="M1.5 6.5h3.75" />
<path d="M2.6 5.2A6.5 6.5 0 1 1 8 14.5a6.5 6.5 0 0 1-5.9-3.8" />
</svg>
);

/**
* Shown on the maintenance-version docs routes (`/v4/...`) so readers who
* landed there from an old link know they aren't on the current docs, with a
* one-click path to the same page on the latest version.
*/
export const MaintenanceBanner = ({ pathname }: MaintenanceBannerProps) => {
const latestHref = buildVersionUrl(pathname, LATEST_VERSION);
return (
<div className="border-b bg-amber-100 px-4 py-2 text-center text-sm dark:bg-amber-950/40">
<div className="mx-auto flex max-w-[1448px] flex-wrap items-center justify-center gap-x-3 gap-y-1">
<div className="flex items-center gap-2 text-amber-900 dark:text-amber-200">
<ClockRewind className="size-4 shrink-0" />
<span>
Viewing Workflow {MAINTENANCE_VERSION.id.replace(/^v/, '')}.x
documentation. This version only receives stability fixes.
</span>
</div>
<Link
className="font-medium text-amber-900 underline underline-offset-4 decoration-amber-900/40 transition-colors hover:decoration-amber-900 dark:text-amber-200 dark:decoration-amber-200/40 dark:hover:decoration-amber-200"
href={latestHref}
>
Go to Workflow {LATEST_VERSION.id.replace(/^v/, '')} (Latest)
</Link>
</div>
</div>
);
};
Loading
Loading