diff --git a/docs/app/[lang]/(home)/components/cta.tsx b/docs/app/[lang]/(home)/components/cta.tsx index d97a89aa1d..8285ad0259 100644 --- a/docs/app/[lang]/(home)/components/cta.tsx +++ b/docs/app/[lang]/(home)/components/cta.tsx @@ -1,5 +1,5 @@ import Link from 'next/link'; -import { Button } from '@/components/ui/button'; +import { Button } from '@vercel/geistdocs/components/button'; export const CTA = () => (
diff --git a/docs/app/[lang]/(home)/components/hero.tsx b/docs/app/[lang]/(home)/components/hero.tsx index 268a446aeb..0a8966ea4d 100644 --- a/docs/app/[lang]/(home)/components/hero.tsx +++ b/docs/app/[lang]/(home)/components/hero.tsx @@ -13,7 +13,7 @@ import { } from '@/components/ui/command-prompt'; const COMMAND_FOR_HUMANS = 'npm install workflow'; -const COMMAND_FOR_AGENTS = 'npx skills add vercel/workflow@workflow-init'; +const COMMAND_FOR_AGENTS = 'npx skills add vercel/workflow'; type HeroProps = { title: string; diff --git a/docs/app/[lang]/(home)/components/preview-badge.tsx b/docs/app/[lang]/(home)/components/preview-badge.tsx index 75257aedc0..0182aea166 100644 --- a/docs/app/[lang]/(home)/components/preview-badge.tsx +++ b/docs/app/[lang]/(home)/components/preview-badge.tsx @@ -4,7 +4,7 @@ import { CheckIcon, CopyIcon, ExternalLinkIcon, EyeIcon } from 'lucide-react'; import { useState } from 'react'; import { toast } from 'sonner'; import { Badge } from '@/components/ui/badge'; -import { Button } from '@/components/ui/button'; +import { Button } from '@vercel/geistdocs/components/button'; import { Dialog, DialogContent, @@ -12,7 +12,7 @@ import { DialogHeader, DialogTitle, DialogTrigger, -} from '@/components/ui/dialog'; +} from '@vercel/geistdocs/components/dialog'; type PreviewBadgeProps = { deploymentUrl: string; diff --git a/docs/app/[lang]/(home)/components/run-anywhere.tsx b/docs/app/[lang]/(home)/components/run-anywhere.tsx index da4c20877b..3ed898a1c4 100644 --- a/docs/app/[lang]/(home)/components/run-anywhere.tsx +++ b/docs/app/[lang]/(home)/components/run-anywhere.tsx @@ -1,7 +1,7 @@ import Link from 'next/link'; import type { ComponentProps } from 'react'; import { CodeBlock } from '@/app/[lang]/(home)/components/code-block'; -import { Button } from '@/components/ui/button'; +import { Button } from '@vercel/geistdocs/components/button'; import { cn } from '@/lib/utils'; const DigitalOcean = (props: ComponentProps<'svg'>) => ( diff --git a/docs/app/[lang]/(home)/components/templates/index.tsx b/docs/app/[lang]/(home)/components/templates/index.tsx index 84bf555560..35c13a98f6 100644 --- a/docs/app/[lang]/(home)/components/templates/index.tsx +++ b/docs/app/[lang]/(home)/components/templates/index.tsx @@ -1,6 +1,6 @@ import Image from 'next/image'; import Link from 'next/link'; -import { Button } from '@/components/ui/button'; +import { Button } from '@vercel/geistdocs/components/button'; import { examplesRepositoryUrl } from '@/geistdocs'; import { cn } from '@/lib/utils'; import Flight from './flight-v2.png'; diff --git a/docs/app/[lang]/(home)/components/vercel-com-visuals/downtime-visual.tsx b/docs/app/[lang]/(home)/components/vercel-com-visuals/downtime-visual.tsx index 5cf5a3de2c..939fc5d142 100644 --- a/docs/app/[lang]/(home)/components/vercel-com-visuals/downtime-visual.tsx +++ b/docs/app/[lang]/(home)/components/vercel-com-visuals/downtime-visual.tsx @@ -4,7 +4,7 @@ import type { JSX } from 'react'; import { cn } from '@/lib/utils'; import { useState, useEffect, useRef } from 'react'; import { AnimatePresence, motion, useInView } from 'motion/react'; -import { Spinner } from '@/components/ui/spinner'; +import { Spinner } from '@vercel/geistdocs/components/spinner'; export function DowntimeVisual(): JSX.Element { return ( diff --git a/docs/app/[lang]/(home)/components/vercel-com-visuals/feature-grid.tsx b/docs/app/[lang]/(home)/components/vercel-com-visuals/feature-grid.tsx index 3c5f9f54c6..5867584101 100644 --- a/docs/app/[lang]/(home)/components/vercel-com-visuals/feature-grid.tsx +++ b/docs/app/[lang]/(home)/components/vercel-com-visuals/feature-grid.tsx @@ -1,7 +1,7 @@ import Link from 'next/link'; import type { JSX, ReactNode } from 'react'; -import { Button } from '@/components/ui/button'; +import { Button } from '@vercel/geistdocs/components/button'; import { AgentsVisual } from './agents-visual'; import { AiSdkVisual } from './ai-sdk-visual'; import { O11yVisual } from './o11y-visual'; diff --git a/docs/app/[lang]/(home)/components/vercel-com-visuals/vercel-section.tsx b/docs/app/[lang]/(home)/components/vercel-com-visuals/vercel-section.tsx index 273dc24090..e4b14dc43a 100644 --- a/docs/app/[lang]/(home)/components/vercel-com-visuals/vercel-section.tsx +++ b/docs/app/[lang]/(home)/components/vercel-com-visuals/vercel-section.tsx @@ -1,6 +1,6 @@ import Link from 'next/link'; import type { JSX } from 'react'; -import { Button } from '@/components/ui/button'; +import { Button } from '@vercel/geistdocs/components/button'; import { O11yDashboard } from './o11y-dashboard'; export function VercelSection(): JSX.Element { diff --git a/docs/app/[lang]/.well-known/mcp.json/route.ts b/docs/app/[lang]/.well-known/mcp.json/route.ts new file mode 100644 index 0000000000..195a69b4d7 --- /dev/null +++ b/docs/app/[lang]/.well-known/mcp.json/route.ts @@ -0,0 +1,8 @@ +import { createMcpManifestRoute } from '@vercel/geistdocs/routes/mcp'; +import { config } from '@/lib/geistdocs/config'; + +export const { GET, generateStaticParams, revalidate } = createMcpManifestRoute( + { + config, + } +); diff --git a/docs/app/[lang]/agents.md/route.ts b/docs/app/[lang]/agents.md/route.ts new file mode 100644 index 0000000000..72423584e4 --- /dev/null +++ b/docs/app/[lang]/agents.md/route.ts @@ -0,0 +1,6 @@ +import { createAgentsRoute } from '@vercel/geistdocs/routes/agents'; +import { config } from '@/lib/geistdocs/config'; + +export const { GET, generateStaticParams, revalidate } = createAgentsRoute({ + config, +}); diff --git a/docs/app/[lang]/cookbook/[[...slug]]/page.tsx b/docs/app/[lang]/cookbook/[[...slug]]/page.tsx index cd0afcb8d3..71d101c1ea 100644 --- a/docs/app/[lang]/cookbook/[[...slug]]/page.tsx +++ b/docs/app/[lang]/cookbook/[[...slug]]/page.tsx @@ -1,135 +1,49 @@ -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 { MobileDocsBar } from '@/components/geistdocs/mobile-docs-bar'; -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 { MobileDocsBar } from '@vercel/geistdocs/mobile-docs-bar'; +import { createDocsPage } from '@vercel/geistdocs/pages/docs'; +import type { ComponentProps, ComponentType } from 'react'; 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) => { - const href = - typeof props.href === 'string' - ? rewriteCookbookUrl(props.href) - : props.href; - return ; - }; - - return ( - - - - - - - - - - ), - }} - tableOfContentPopover={{ enabled: false }} - toc={page.data.toc} - > - - {page.data.title} - {page.data.description} - - - - - ); -}; - -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, - }, +import { config } from '@/lib/geistdocs/config'; +import { rewriteCookbookUrl } from '@/lib/geistdocs/cookbook-source'; +import { cookbookSource } from '@/lib/geistdocs/source'; + +const docsPage = createDocsPage({ + config, + source: cookbookSource, + mdx: ({ link }) => getMDXComponents({ a: link }), + resolveLink: ({ link }) => { + const Link = link as ComponentType>; + const PublicCookbookLink = (props: ComponentProps<'a'>) => { + const href = + typeof props.href === 'string' + ? rewriteCookbookUrl(props.href) + : props.href; + + return ; + }; + + return PublicCookbookLink; + }, + openGraph: { + images: true, + }, + tableOfContentPopover: { + enabled: false, + }, + renderTop: ({ data }) => , + metadata: ({ metadata, page }) => ({ + ...metadata, alternates: { - canonical: publicPath, + ...metadata.alternates, + canonical: page.url, types: { - 'text/markdown': `${publicPath}.md`, + ...metadata.alternates?.types, + 'text/markdown': + page.url === '/cookbook' ? '/cookbook.md' : `${page.url}.md`, }, }, - }; - - return metadata; -}; + }), +}); -export default Page; +export default docsPage.Page; +export const generateStaticParams = docsPage.generateStaticParams; +export const generateMetadata = docsPage.generateMetadata; diff --git a/docs/app/[lang]/cookbook/layout.tsx b/docs/app/[lang]/cookbook/layout.tsx index f200f06b19..19b36e29e7 100644 --- a/docs/app/[lang]/cookbook/layout.tsx +++ b/docs/app/[lang]/cookbook/layout.tsx @@ -1,5 +1,6 @@ import { DocsLayout } from '@/components/geistdocs/docs-layout'; import { getCookbookTree } from '@/lib/geistdocs/cookbook-source'; +import { LATEST_VERSION } from '@/lib/geistdocs/versions'; const Layout = async ({ children, @@ -9,7 +10,12 @@ const Layout = async ({ return (
- {children} + + {children} +
); }; diff --git a/docs/app/[lang]/docs/[[...slug]]/page.tsx b/docs/app/[lang]/docs/[[...slug]]/page.tsx index e39633e784..6833bd583c 100644 --- a/docs/app/[lang]/docs/[[...slug]]/page.tsx +++ b/docs/app/[lang]/docs/[[...slug]]/page.tsx @@ -1,134 +1,33 @@ -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, 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 { PreviewInstallServer } from '@/components/preview-install-server'; -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 { MobileDocsBar } from '@vercel/geistdocs/mobile-docs-bar'; +import { createDocsPage } from '@vercel/geistdocs/pages/docs'; import { getMDXComponents } from '@/components/geistdocs/mdx-components'; -import { MobileDocsBar } from '@/components/geistdocs/mobile-docs-bar'; -import { OpenInChat } from '@/components/geistdocs/open-in-chat'; -import { ScrollTop } from '@/components/geistdocs/scroll-top'; -import * as AccordionComponents from '@/components/ui/accordion'; -import { Badge } from '@/components/ui/badge'; -import { Separator } from '@/components/ui/separator'; -import { getLLMText, getPageImage, source } from '@/lib/geistdocs/source'; -import { TSDoc } from '@/lib/tsdoc'; - -// No-op component for world MDX files rendered outside /worlds/ context -// These pages redirect to /worlds/[id] but still get statically generated -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) { - notFound(); - } - - const markdown = await getLLMText(page); - const MDX = page.data.body; - - return ( - - - - - - - - - - ), - }} - tableOfContentPopover={{ enabled: false }} - toc={page.data.toc} - > - - {page.data.title} - {page.data.description} - - - - - ); -}; - -export const generateStaticParams = () => - source - .generateParams() - .filter( - (params) => !(Array.isArray(params.slug) && params.slug[0] === 'cookbook') - ); - -export const generateMetadata = async ({ - params, -}: PageProps<'/[lang]/docs/[[...slug]]'>) => { - const { slug, lang } = await params; - const page = source.getPage(slug, lang); - - if (!page) { - notFound(); - } - - const metadata: Metadata = { - title: page.data.title, - description: page.data.description, - openGraph: { - images: getPageImage(page).url, - }, +import { config } from '@/lib/geistdocs/config'; +import { geistdocsSource } from '@/lib/geistdocs/source'; + +const docsPage = createDocsPage({ + config, + source: geistdocsSource, + mdx: ({ link }) => getMDXComponents({ a: link }), + openGraph: { + images: true, + }, + tableOfContentPopover: { + enabled: false, + }, + renderTop: ({ data }) => , + metadata: ({ metadata, page }) => ({ + ...metadata, alternates: { + ...metadata.alternates, canonical: page.url, types: { - 'text/markdown': `${page.url}.md`, + ...metadata.alternates?.types, + 'text/markdown': page.url === '/docs' ? '/docs.md' : `${page.url}.md`, }, }, - }; - - return metadata; -}; + }), +}); -export default Page; +export default docsPage.Page; +export const generateStaticParams = docsPage.generateStaticParams; +export const generateMetadata = docsPage.generateMetadata; diff --git a/docs/app/[lang]/docs/layout.tsx b/docs/app/[lang]/docs/layout.tsx index 8173e821a5..2854a8f29c 100644 --- a/docs/app/[lang]/docs/layout.tsx +++ b/docs/app/[lang]/docs/layout.tsx @@ -7,7 +7,10 @@ const Layout = async ({ children, params }: LayoutProps<'/[lang]/docs'>) => { return (
- + {children}
diff --git a/docs/app/[lang]/layout.tsx b/docs/app/[lang]/layout.tsx index 0f0e27c0fa..36623138ff 100644 --- a/docs/app/[lang]/layout.tsx +++ b/docs/app/[lang]/layout.tsx @@ -1,9 +1,9 @@ import '../global.css'; +import { Footer } from '@vercel/geistdocs/footer'; +import { Navbar } from '@vercel/geistdocs/navbar'; import type { Metadata } from 'next'; -import { Footer } from '@/components/geistdocs/footer'; -import { Navbar } from '@/components/geistdocs/navbar'; import { GeistdocsProvider } from '@/components/geistdocs/provider'; -import { basePath } from '@/geistdocs'; +import { config } from '@/lib/geistdocs/config'; import { mono, sans } from '@/lib/geistdocs/fonts'; import { cn } from '@/lib/utils'; @@ -33,10 +33,10 @@ const Layout = async ({ children, params }: LayoutProps<'/[lang]'>) => { suppressHydrationWarning > - - + + {children} -