You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Upgrade website/ from Nextra 2.13 to Nextra 4. This is 3 stacked migrations: Nextra 2→4 API, Next.js Pages Router→App Router (v4 is App Router only, theme.config.jsx no longer exists), Tailwind 3→4 (required by nextra-theme-docs v4).
Site inventory: 86 MDX pages, 15 _meta.json, ~50 files importing Nextra components, ~44 files using next-seo, 140-line theme.config.jsx, custom marketing pages (home, /cloud/*, /news, sponsors/testimonials via GitHub API), Algolia DocSearch, next-sitemap, next-plausible proxy, middleware, redirects.js, /api/md rewrite (Markdown for AI crawlers), link-checker/. Note: docs source lives in top-level docs/, synced into website/src/pages/docs/ by the website Makefile.
Search: replace Algolia DocSearch with Pagefind (v4 default), docs-only index (exclude marketing pages). Reversible via custom search prop on theme Layout. Accepted losses: search analytics, typo tolerance, no search in next dev.
Docs design: adopt v4 default look, no pixel-matching. Matthieu reviews side-by-side screenshots before merge; big differences not acceptable.
Redirects: hard requirement. Any URL change must be flagged + get a redirect. Verify by crawling all current prod sitemap URLs against new build → assert 200-or-redirect. Hash-fragment redirects (~30, client-side) must be reimplemented in App Router.
Phase 1 — spike: all 6 unknowns answered, working build — spike report. Scaffold reusable: branch worktree-agent-a61252823a9d0f300, website/spike/, commit 5ce77963
Decision: fresh v4 scaffold + port content (in-place would leave repo unbuildable throughout; scaffold doesn't survive the v2→v4 cut). Reuse the spike skeleton
Phase A — fresh v4 scaffold in website/ (PR Migrate website to Nextra 4 #2132, build green): app/layout with full theme.config port, catch-all route + metadata, Tailwind v4 + brand palette, hash-redirect client component, middleware (moved to website root), .md route handler, Makefile sync retargeted to content/docs. Old pages staged in website/_port/pages/
Phase B — bulk docs content: 67 source docs swept, 13+2 _meta converted, full sync active, build green. URL parity: 70/70 live /docs/* URLs present. Extras: fixed icon import paths broken by the dir move (5 files), extracted serverless-costs calculator to a 'use client' component. Note: some internal .mdx-suffixed links 404 — pre-existing on live prod, not a regression (follow-up candidate)
Phase C — marketing/custom pages: all ported, build green (94 pages). Sitemap parity 91/91 vs live, 0 missing 0 extra. All routes curl-verified 200. Notes: /cloud/* per-component routes were accidental v2 pages, recreated as thin wrappers for parity (candidate to remove+redirect later); credits data now revalidates hourly instead of build-only (harmless); changelog kept as MDX + async Server Component
Phase D — Pagefind docs-only via CLI glob (70/70 index entries are /docs/*); plumbing verified: .html+path redirects 308-correct, hash-redirect coverage confirmed by static analysis, .md+content negotiation pass, sitemap 91/91 + robots byte-identical to live, Plausible proxy config identical, trailing-slash identical to live. Bug fixed: JSX comments leaked into .md crawler output
Phase E — verification: zero regressions vs prod. 91/91 sitemap URLs, 71/72 redirects + 5 .html pattern (1 failure pre-existing on prod), 66/70 .md endpoints (4 failures pre-existing on prod), browser tests 5/5 (hash redirects, docs-only search, calculator/pricing/tabs), 24 side-by-side screenshots captured
Review fixes (commit e4acf3f): independent code review found 0 high-severity issues; applied 6 fixes — /docs broken .md alternate link (only true regression), path-traversal hardening in md route, .md-source fallback (3 pages now work, 404 on prod), /docs.md now serves markdown (404 on prod), revived dead /docs/web-apps* redirects (404 on prod), removed 41 dead hash entries from server redirects
Matthieu's visual review round 1: new build looks different from prod → full visual audit of all 12 screenshot pairs: 5 defects, 9 drift items
Visual fixes (commits 5dfa175, 67c6372, bc2d3b1): hero H1 fix — real root cause was MDX wrapping multi-line JSX heading text in a docs <p> (leading-7 overriding h1 leading), fixed by inlining the text; Tailwind @source for gitignored content/docs (restored docs-only utility classes); copyPage:false on all marketing pages; credits page full-layout theme block; news image confirmed non-bug (lazy-load timing). Drift restorations per Matthieu: blue-tinted code blocks, "Search docs" placeholder; all other v4 look changes accepted (content width, green callouts, ↗ links, sidebar pill)
Full-bleed marketing pages (commit 834ae93): layout:'full' in v4 only drops the TOC column — the theme MDX wrapper still caps content at --nextra-content-width (90rem). Fix the Nextra way: resolve active layout via normalizePages in the catch-all route, tag full pages with data-full-layout, override the documented --nextra-content-width var to 100% + zero article padding on those pages only. Measured at 1920px: home/cloud heroes = 1920, navbar inner + docs unchanged at 1440
Round-3 fixes (commits 37c1076, aae06d5): React console errors on /cloud (stop-color→stopColor, missing key in tiers map; sweep of 6 pages + 43 map sites found no others); white background everywhere via <Head backgroundColor={{light:'#fff'}}>; docs blues were Nextra's default primary (hue 212) injected by <Head> overriding globals.css — fixed with <Head color={{hue:202,saturation:80,lightness:57}}> = Bref #3AA9E9 (dead CSS-var override removed)
Sidebar page+folder duplicates (commit 3ad5ecc): v4 no longer collapses X.mdx + sibling X/ into one link — 7 sections showed a duplicated nested child (setup, deploy, runtimes, case-studies, local-development, monitoring, use-cases/http). Fixed the v4 way: moved each to X/index.mdx with asIndexPage: true. Routes unchanged, all URLs 200, folder headers now clickable links, 94 pages
theme.layout:'raw' removed in v4 → layout:'full' + sidebar/toc/breadcrumb/pagination:false
layout:'full' does NOT make pages full-bleed — content stays capped at --nextra-content-width (90rem); override the var per-page (see full-bleed fix above)
Home page title needs title:{absolute} in generateMetadata, else double "– Bref"
_meta.js uses export default; separators are { type: 'separator' }
primaryHue is gone → CSS var --nextra-primary-hue
Follow-up candidates (pre-existing, not migration scope)
Some internal .mdx-suffixed links in docs 404 (already broken on live prod)
link-checker crashes on a literal http://localhost:8000/ example URL in docs prose
22 Markdown images in docs/ have empty alt text () — Next.js dev overlay flags them as a11y errors (dev-only, build unaffected); fix = write descriptive alts
Upgrade
website/from Nextra 2.13 to Nextra 4. This is 3 stacked migrations: Nextra 2→4 API, Next.js Pages Router→App Router (v4 is App Router only,theme.config.jsxno longer exists), Tailwind 3→4 (required by nextra-theme-docs v4).Site inventory: 86 MDX pages, 15
_meta.json, ~50 files importing Nextra components, ~44 files using next-seo, 140-linetheme.config.jsx, custom marketing pages (home,/cloud/*,/news, sponsors/testimonials via GitHub API), Algolia DocSearch,next-sitemap,next-plausibleproxy, middleware,redirects.js,/api/mdrewrite (Markdown for AI crawlers),link-checker/. Note: docs source lives in top-leveldocs/, synced intowebsite/src/pages/docs/by the website Makefile.Full Phase 0 migration map: see audit comment.
Decisions
searchprop on themeLayout. Accepted losses: search analytics, typo tolerance, no search innext dev.Plan
nextra/remote— mergedworktree-agent-a61252823a9d0f300,website/spike/, commit5ce77963website/(PR Migrate website to Nextra 4 #2132, build green): app/layout with full theme.config port, catch-all route + metadata, Tailwind v4 + brand palette, hash-redirect client component, middleware (moved to website root),.mdroute handler, Makefile sync retargeted tocontent/docs. Old pages staged inwebsite/_port/pages/_metaconverted, full sync active, build green. URL parity: 70/70 live/docs/*URLs present. Extras: fixed icon import paths broken by the dir move (5 files), extractedserverless-costscalculator to a'use client'component. Note: some internal.mdx-suffixed links 404 — pre-existing on live prod, not a regression (follow-up candidate)/cloud/*per-component routes were accidental v2 pages, recreated as thin wrappers for parity (candidate to remove+redirect later); credits data now revalidates hourly instead of build-only (harmless); changelog kept as MDX + async Server Component/docs/*); plumbing verified:.html+path redirects 308-correct, hash-redirect coverage confirmed by static analysis,.md+content negotiation pass, sitemap 91/91 + robots byte-identical to live, Plausible proxy config identical, trailing-slash identical to live. Bug fixed: JSX comments leaked into.mdcrawler output.htmlpattern (1 failure pre-existing on prod), 66/70.mdendpoints (4 failures pre-existing on prod), browser tests 5/5 (hash redirects, docs-only search, calculator/pricing/tabs), 24 side-by-side screenshots captured/docsbroken.mdalternate link (only true regression), path-traversal hardening in md route,.md-source fallback (3 pages now work, 404 on prod),/docs.mdnow serves markdown (404 on prod), revived dead/docs/web-apps*redirects (404 on prod), removed 41 dead hash entries from server redirects<p>(leading-7 overriding h1 leading), fixed by inlining the text; Tailwind@sourcefor gitignoredcontent/docs(restored docs-only utility classes);copyPage:falseon all marketing pages; credits page full-layout theme block; news image confirmed non-bug (lazy-load timing). Drift restorations per Matthieu: blue-tinted code blocks, "Search docs" placeholder; all other v4 look changes accepted (content width, green callouts, ↗ links, sidebar pill)layout:'full'in v4 only drops the TOC column — the theme MDX wrapper still caps content at--nextra-content-width(90rem). Fix the Nextra way: resolve active layout vianormalizePagesin the catch-all route, tag full pages withdata-full-layout, override the documented--nextra-content-widthvar to 100% + zero article padding on those pages only. Measured at 1920px: home/cloud heroes = 1920, navbar inner + docs unchanged at 1440stop-color→stopColor, missingkeyin tiers map; sweep of 6 pages + 43 map sites found no others); white background everywhere via<Head backgroundColor={{light:'#fff'}}>; docs blues were Nextra's default primary (hue 212) injected by<Head>overriding globals.css — fixed with<Head color={{hue:202,saturation:80,lightness:57}}>= Bref #3AA9E9 (dead CSS-var override removed)X.mdx+ siblingX/into one link — 7 sections showed a duplicated nested child (setup, deploy, runtimes, case-studies, local-development, monitoring, use-cases/http). Fixed the v4 way: moved each toX/index.mdxwithasIndexPage: true. Routes unchanged, all URLs 200, folder headers now clickable links, 94 pagesKnown gotchas
next@15, NOT 16 — Nextra 4.6.1 + Next 16 500s on every route (Layout children bug)zodto4.3.0— zod 4.4.x breaks nextra-theme-docs 4.6.1safeParsetheme.layout:'raw'removed in v4 →layout:'full'+sidebar/toc/breadcrumb/pagination:falselayout:'full'does NOT make pages full-bleed — content stays capped at--nextra-content-width(90rem); override the var per-page (see full-bleed fix above)title:{absolute}ingenerateMetadata, else double "– Bref"{ next: { revalidate } }over route-levelexport const revalidateexport functioninside MDX breaks component resolution → extract to.jsxfiles{/* ... */}@layer→ requires Tailwind 4 +@tailwindcss/postcss_meta.jsusesexport default; separators are{ type: 'separator' }primaryHueis gone → CSS var--nextra-primary-hueFollow-up candidates (pre-existing, not migration scope)
.mdx-suffixed links in docs 404 (already broken on live prod)http://localhost:8000/example URL in docs prosedocs/have empty alt text () — Next.js dev overlay flags them as a11y errors (dev-only, build unaffected); fix = write descriptive alts