docs: revamp World documentation pages#763
Conversation
|
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
📊 Benchmark Results
workflow with no steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express workflow with 1 step💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express workflow with 10 sequential steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express | Nitro Promise.all with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Nitro | Next.js (Turbopack) | Express Promise.all with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) | Nitro Promise.race with 10 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Express | Nitro Promise.race with 25 concurrent steps💻 Local Development
▲ Production (Vercel)
🔍 Observability: Express | Next.js (Turbopack) | Nitro Stream Benchmarks (includes TTFB metrics)workflow with stream💻 Local Development
▲ Production (Vercel)
🔍 Observability: Next.js (Turbopack) | Nitro | Express SummaryFastest Framework by WorldWinner determined by most benchmark wins
Fastest World by FrameworkWinner determined by most benchmark wins
Column Definitions
Worlds:
|
🧪 E2E Test Results❌ Some tests failed Summary
❌ Failed Tests💻 Local Development (2 failed)astro-stable (2 failed):
🌍 Community Worlds (161 failed)mongodb (40 failed):
redis (40 failed):
starter (41 failed):
turso (40 failed):
Details by Category✅ ▲ Vercel Production
❌ 💻 Local Development
✅ 📦 Local Production
✅ 🐘 Local Postgres
✅ 🪟 Windows
❌ 🌍 Community Worlds
❌ Some E2E test jobs failed:
Check the workflow run for details. |
There was a problem hiding this comment.
Pull request overview
This PR revamps the World documentation by creating dedicated detail pages for official worlds (local, postgres, vercel) with MDX-driven content. It introduces new components for world detail pages, benchmark history visualization with interactive charts, and a redesigned worlds index page with a 3D globe visual.
Changes:
- Created dedicated
/worlds/[id]routes with MDX content for official worlds and template components for community worlds - Added benchmark history charts showing performance trends over releases/commits with clickable data points
- Restructured world documentation with cleaner h3 headings for configuration options instead of tables
- Added TOC generation from MDX headings and world data provider context for component communication
Reviewed changes
Copilot reviewed 31 out of 32 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| worlds-manifest.json | Added example field for linking to example repositories |
| package.json | Added cobe dependency (0.6.5) for 3D globe visualization |
| next.config.ts | Added redirects from old /docs/deploying/world/* paths to new /worlds/* routes |
| worlds-data.ts | Enhanced to extract framework-specific E2E data, workflow timing metrics, and added single world lookup functions |
| types.ts | Added framework E2E breakdown types, workflow timing fields, benchmark10SeqMs metric, and formatTime utility |
| WorldDetailHero.tsx | New hero component for world detail pages with E2E/benchmark summary and quick links |
| WorldDetailToc.tsx | New TOC component with intersection observer for active section highlighting |
| WorldTestingPerformance.tsx | New component displaying E2E test results and benchmark tables with history chart integration |
| WorldDataProvider.tsx | New context provider for sharing world data between MDX and client components |
| WorldCardSimple.tsx | New simplified card component for worlds index page with E2E/PERF metrics footer |
| Globe.tsx | New interactive 3D globe component using COBE library |
| BenchmarkHistoryChart.tsx | New dialog component showing performance trends over time with releases/commits toggle |
| local-world.mdx | Rewritten with cleaner structure, h3 config options, and Testing & Performance section |
| postgres-world.mdx | Rewritten with installation steps, framework-specific examples, and detailed configuration |
| vercel-world.mdx | Rewritten with simplified auto-configuration explanation and versioning details |
| worlds/page.tsx | New worlds index page with globe hero, world cards grid, and "What is a World?" section |
| worlds/[id]/page.tsx | New dynamic world detail page supporting both MDX and template rendering |
| worlds/compare/page.tsx | New benchmark comparison page with tables and charts |
| benchmark-history/route.ts | New API route fetching historical benchmark data from gh-pages commits |
| generate-docs-data.js | Enhanced to extract workflow timing metrics (min/max/ttfb/slurp) from benchmark results |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| return ( | ||
| <nav className="space-y-1"> | ||
| <p className="font-medium text-sm mb-2">On this page</p> | ||
| {items.map((item) => ( | ||
| <a | ||
| key={item.id} | ||
| href={`#${item.id}`} | ||
| className={cn( | ||
| 'block text-sm py-1 border-l-2 pl-3 transition-colors', | ||
| activeId === item.id | ||
| ? 'border-primary text-foreground font-medium' | ||
| : 'border-transparent text-muted-foreground hover:text-foreground hover:border-muted-foreground' | ||
| )} | ||
| > | ||
| {item.title} | ||
| </a> | ||
| ))} | ||
| </nav> | ||
| ); | ||
| } |
There was a problem hiding this comment.
When items array is empty, this component renders a nav with just the "On this page" heading but no links. While not necessarily broken, consider adding a conditional render or early return if items.length === 0 to avoid rendering an empty navigation section.
| const fileRes = await fetch( | ||
| `https://raw.githubusercontent.com/${REPO}/${ghPagesSha}/${FILE_PATH}`, | ||
| { next: { revalidate: 3600 } } | ||
| ); | ||
|
|
||
| if (!fileRes.ok) return null; | ||
|
|
||
| return (await fileRes.json()) as CIResultsData; |
There was a problem hiding this comment.
The JSON parsing at line 87 doesn't handle malformed JSON responses. If the GitHub API returns invalid JSON, this will throw an unhandled error. Consider wrapping the await fileRes.json() in a try-catch or adding validation.
| const ghPagesCommits = (await ghPagesCommitsRes.json()) as GitHubCommit[]; | ||
|
|
||
| // Fetch benchmark data for each gh-pages commit in batches | ||
| const BATCH_SIZE = 10; | ||
| for (let i = 0; i < ghPagesCommits.length; i += BATCH_SIZE) { | ||
| const batch = ghPagesCommits.slice(i, i + BATCH_SIZE); | ||
| const results = await Promise.all( | ||
| batch.map(async (ghCommit) => { | ||
| const data = await fetchBenchmarkFile(ghCommit.sha); | ||
| if (!data || !data.commit) return null; | ||
|
|
||
| return { | ||
| ghPagesSha: ghCommit.sha, | ||
| mainCommitSha: data.commit, | ||
| timestamp: data.lastUpdated, | ||
| data, | ||
| }; | ||
| }) | ||
| ); | ||
|
|
||
| for (const result of results) { | ||
| if (result && !snapshotMap.has(result.mainCommitSha)) { | ||
| // Only keep the first (most recent) benchmark for each main commit | ||
| snapshotMap.set(result.mainCommitSha, result); | ||
| } | ||
| } |
There was a problem hiding this comment.
Similarly, the JSON parsing at line 120 for gh-pages commits doesn't handle malformed JSON responses. Consider adding error handling for the await ghPagesCommitsRes.json() call.
| const ghPagesCommits = (await ghPagesCommitsRes.json()) as GitHubCommit[]; | |
| // Fetch benchmark data for each gh-pages commit in batches | |
| const BATCH_SIZE = 10; | |
| for (let i = 0; i < ghPagesCommits.length; i += BATCH_SIZE) { | |
| const batch = ghPagesCommits.slice(i, i + BATCH_SIZE); | |
| const results = await Promise.all( | |
| batch.map(async (ghCommit) => { | |
| const data = await fetchBenchmarkFile(ghCommit.sha); | |
| if (!data || !data.commit) return null; | |
| return { | |
| ghPagesSha: ghCommit.sha, | |
| mainCommitSha: data.commit, | |
| timestamp: data.lastUpdated, | |
| data, | |
| }; | |
| }) | |
| ); | |
| for (const result of results) { | |
| if (result && !snapshotMap.has(result.mainCommitSha)) { | |
| // Only keep the first (most recent) benchmark for each main commit | |
| snapshotMap.set(result.mainCommitSha, result); | |
| } | |
| } | |
| try { | |
| const ghPagesCommits = (await ghPagesCommitsRes.json()) as GitHubCommit[]; | |
| // Fetch benchmark data for each gh-pages commit in batches | |
| const BATCH_SIZE = 10; | |
| for (let i = 0; i < ghPagesCommits.length; i += BATCH_SIZE) { | |
| const batch = ghPagesCommits.slice(i, i + BATCH_SIZE); | |
| const results = await Promise.all( | |
| batch.map(async (ghCommit) => { | |
| const data = await fetchBenchmarkFile(ghCommit.sha); | |
| if (!data || !data.commit) return null; | |
| return { | |
| ghPagesSha: ghCommit.sha, | |
| mainCommitSha: data.commit, | |
| timestamp: data.lastUpdated, | |
| data, | |
| }; | |
| }) | |
| ); | |
| for (const result of results) { | |
| if (result && !snapshotMap.has(result.mainCommitSha)) { | |
| // Only keep the first (most recent) benchmark for each main commit | |
| snapshotMap.set(result.mainCommitSha, result); | |
| } | |
| } | |
| } | |
| } catch (error) { | |
| console.error('Failed to parse gh-pages commits JSON', error); | |
| return snapshotMap; |
| // Fetch benchmark data for each gh-pages commit in batches | ||
| const BATCH_SIZE = 10; | ||
| for (let i = 0; i < ghPagesCommits.length; i += BATCH_SIZE) { | ||
| const batch = ghPagesCommits.slice(i, i + BATCH_SIZE); | ||
| const results = await Promise.all( | ||
| batch.map(async (ghCommit) => { | ||
| const data = await fetchBenchmarkFile(ghCommit.sha); | ||
| if (!data || !data.commit) return null; | ||
|
|
||
| return { | ||
| ghPagesSha: ghCommit.sha, | ||
| mainCommitSha: data.commit, | ||
| timestamp: data.lastUpdated, | ||
| data, | ||
| }; | ||
| }) | ||
| ); | ||
|
|
||
| for (const result of results) { | ||
| if (result && !snapshotMap.has(result.mainCommitSha)) { | ||
| // Only keep the first (most recent) benchmark for each main commit | ||
| snapshotMap.set(result.mainCommitSha, result); | ||
| } | ||
| } | ||
| } | ||
|
|
||
| return snapshotMap; |
There was a problem hiding this comment.
The batch processing loop processes all gh-pages commits (up to 100) without any upper bound on memory usage. If there are many commits, this could create a large number of parallel fetch requests. Consider adding a limit to the total number of commits processed or adding more granular error handling to prevent memory issues.
| const globe = createGlobe(canvasRef.current!, globeConfig); | ||
|
|
There was a problem hiding this comment.
The canvasRef.current could be null when createGlobe is called. While the non-null assertion operator (!) is used, this could cause a runtime error if the component unmounts or the ref isn't set before the effect runs. Add a null check before calling createGlobe.
| const globe = createGlobe(canvasRef.current!, globeConfig); | |
| const canvas = canvasRef.current; | |
| if (!canvas) { | |
| return () => { | |
| window.removeEventListener('resize', onResize); | |
| }; | |
| } | |
| const globe = createGlobe(canvas, globeConfig); |
| samples: latestPoint?.samples, | ||
| current, | ||
| trendPercent, | ||
| ttfb: latestPoint?.ttfb, |
| const pointerInteracting = useRef<number | null>(null); | ||
| const pointerInteractionMovement = useRef(0); | ||
| const [size, setSize] = useState(1200); | ||
| const { resolvedTheme } = useTheme(); |
- Add dedicated world detail pages at /worlds/[id] with MDX-driven content - Create WorldDetailHero, WorldDetailToc, WorldTestingPerformance components - Add benchmark history charts and test summary links - Rewrite local-world, postgres-world, and vercel-world MDX with cleaner structure - Use h3 headings for configuration options instead of tables/accordions - Add WorldDataProvider context for passing world data to MDX components - Add example field to worlds-manifest for linking to example repos - Update worlds index page design
- Globe now scales with container width up to 1200px max - Increased opacity from 20% to 30% for better visibility - Positioned globe 30% down to show north pole behind header - Globe component now auto-sizes based on container width
- Update title format to '{Name} World | Workflow DevKit'
- Update worlds index page title to 'Worlds | Workflow DevKit'
- Improve world descriptions in worlds-manifest.json for better SEO
- Add dynamic OG image generation at /worlds/[id]/og
- Add openGraph and twitter metadata to world detail pages
- Replace route-based og/route.tsx with opengraph-image.tsx file convention - Remove runtime = 'edge' to allow generateStaticParams for static generation - Simplify page.tsx metadata (Next.js auto-detects opengraph-image.tsx)
- Fix globe visibility in light/dark mode - Fix tooltip positioning on mobile breakpoints - Remove redundant Documentation button for community worlds - Add missing pages to Foundations index (streaming, serialization, idempotency) - Restructure deploying section with new index and building-a-world guide - Restore original MDX content for official worlds (local, vercel, postgres) - Auto-expand sidebar folders when child page is active
|
|
||
| // Check if any child is active (current path starts with folder's index URL) | ||
| const hasActiveChild = item.index?.url | ||
| ? pathname.startsWith(item.index.url + '/') |
| <Card href="/docs/foundations/hooks" title="Webhooks (and hooks)"> | ||
| Respond to external events in your workflow using hooks and webhooks. | ||
| </Card> | ||
| <Card href="/docs/foundations/streaming" title="Streaming"> |
There was a problem hiding this comment.
unrelated change - the foundations page was missing cards for these (they were only in meta)
| // Redirect old world docs to new /worlds routes | ||
| { | ||
| source: '/docs/deploying/world/local-world', | ||
| destination: '/worlds/local', | ||
| permanent: true, | ||
| }, | ||
| { | ||
| source: '/docs/deploying/world/postgres-world', | ||
| destination: '/worlds/postgres', | ||
| permanent: true, | ||
| }, | ||
| { | ||
| source: '/docs/deploying/world/vercel-world', | ||
| destination: '/worlds/vercel', | ||
| permanent: true, | ||
| }, | ||
| { | ||
| source: '/docs/worlds', | ||
| destination: '/worlds', | ||
| permanent: true, | ||
| }, |
There was a problem hiding this comment.
this is so we don't break existing links on twitter, etc.
- Fix /docs/deploying/world link to /docs/deploying/building-a-world - Fix /docs/deploying#what-are-worlds invalid anchor to /docs/deploying - Add @skip-typecheck markers to interface definition code blocks Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- benchmark-history/route.ts: Add error handling for JSON parsing, distinguish 404s from actual errors - Globe.tsx: Fix hydration mismatch by deferring theme-dependent rendering until component is mounted - sidebar.tsx: Improve path check robustness for active child detection Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
|
Review the following changes in direct dependencies. Learn more about Socket for GitHub.
|
Added dedicated worlds page to show all available worlds incuding e2e testbench pass rate and performance benchmarking
Added historic performance benchmarking over last 30 commits/releases on github with request caching (should probably be ISR / PPR since these can be caluclated at build time and don't need to be re-fetched)
Rewrote the Local, Postgres and Vercel world documentation pages to follow a standard structure with config, observability, benchmarking notes
TODOs
Additional Changes
Deploying Section Restructure:
Worlds Page UI Improvements:
Sidebar Navigation:
Other Fixes:
Preview
Worlds Page
Postgres Docs (also check the other worlds)


