This document describes the migration from Nextra (Pages Router) to Fumadocs (App Router) and the remaining steps to complete it.
-
Dependencies
- Replaced
nextraandnextra-theme-docswithfumadocs-core,fumadocs-mdx, andfumadocs-ui. - Added
@types/mdxin devDependencies.
- Replaced
-
Config
source.config.ts– Fumadocs MDX config:defineDocs({ dir: 'content/docs' }),remarkGfm,providerImportSource: '@/mdx-components'.lib/source.ts– Fumadocs source:loader()withdocs.toFumadocsSource(),baseUrl: '/docs'.next.config.mjs– Removed Nextra; wrapped config withcreateMDX()fromfumadocs-mdx/next. All existing options (headers, redirects, rewrites, images, etc.) are unchanged.tsconfig.json– Added path"fumadocs-mdx:collections/*": [".source/*"].
-
App Router
app/layout.tsx– Root layout:RootProvider(fromfumadocs-ui/provider/next), Geist fonts, global CSS (style.css, overrides, Vidstack).app/page.tsx– Temporary home: title + link to/docs. Replace with the real landing (e.g. current<Home />) when ready.app/docs/layout.tsx–DocsLayoutwithsource.getPageTree(), nav title “Langfuse”, GitHub link.app/docs/[[...slug]]/page.tsx– Doc page:source.getPage(slug),page.data.load(),DocsPage+DocsBodywith MDX andgetMDXComponents();generateMetadataandgenerateStaticParams.
-
MDX
mdx-components.tsx–getMDXComponents/useMDXComponentsusingfumadocs-ui/mdx.
-
Content
content/docs/– New Fumadocs content root:meta.json– root meta withpages: ["index", "observability"].index.mdx– overview doc.observability/meta.jsonandobservability/overview.mdx– sample observability doc.
- Fumadocs MDX 13 expects Next 15.3+ and fumadocs-core 15+. If you stay on Next 15.2.x, use:
pnpm install --legacy-peer-deps(ornpm install --legacy-peer-deps).
- Optional: upgrade to Next
^15.3.0to satisfy peer deps without--legacy-peer-deps.
- Done. Docs live in
content/docs/with Fumadocsmeta.json. The formerpages/docs/content was migrated;docs-nextra-backupwas removed after verification.
- Done. All main sections are on App Router:
- Fumadocs collections in
source.config.ts:selfHosting,blog,changelog,guides,faq,integrations,security,library,customers,handbook. - Content in
content/<section>/. - App routes:
app/docs/(docs),app/blog/,app/changelog/(index + layout), andapp/[section]/[[...slug]]for self-hosting, guides, faq, integrations, security, library, customers, handbook. - Client loaders for section MDX:
lib/section-loaders.generated.ts(generated in prebuild viascripts/generate-section-loaders.js). - Index components (
BlogIndex,ChangelogIndex) usegetPagesUnderRoutefrom nextra-shim, which now reads from Fumadocs sources viagetPagesForRouteinlib/source.ts.
- Fumadocs collections in
- Static marketing pages are in
content/marketing/and served viaapp/[section](section = about, careers, pricing, etc.).
These (and any others that import from Nextra) need to be updated or replaced:
| File | Nextra usage | Fumadocs / replacement |
|---|---|---|
theme.config.tsx |
Entire file | No longer used. Nav/sidebar/footer are in app/docs/layout.tsx and Fumadocs layout props. Replicate any custom nav/links in DocsLayout (e.g. nav, sidebar, links). |
components/* using getPagesUnderRoute, Page, useConfig, useTheme |
nextra/context, nextra-theme-docs |
Use source from @/lib/source: e.g. source.getPages(), filter by path; or build custom indexes from source.getPageTree(). For theme, use next-themes or Fumadocs theme. |
nextra/components: Cards, Tabs, Callout |
Nextra components | Use Fumadocs UI: fumadocs-ui/components/card, fumadocs-ui/components/tabs, fumadocs-ui/components/callout, or keep local wrappers that match Fumadocs props. |
Notable components to refactor:
components/home/*(Changelog, etc.) – replacegetPagesUnderRoutewithsource+ path filter.components/blog/BlogIndex.tsx,components/changelog/ChangelogIndex.tsx– same.components/faq/FaqIndex.tsx,components/customers/CustomerIndex.tsx,components/CookbookIndex.tsx,components/VideoIndex.tsx,components/integrations/IntegrationIndex.tsx– same.components/MainContentWrapper.tsx,components/LangTabs.tsx, etc. – removeuseConfig/ Nextra theme; use Fumadocs layout or local state.components/not-found-animation.tsx,components/MetabaseDashboard.tsx,components/inkeep/useInkeepSettings.ts– replaceuseThemewithnext-themesor Fumadocs theme.
app/page.tsx– Uses real<Home />from@/components/home.- Analytics and scripts – In
app/layout.tsx: PostHog (via@/components/analytics/PostHogProvider), Hubspot, and Cookieyes scripts (production only).
- Done. The
pages/directory has been removed. The site uses App Router only. - All routes are under
app/; content lives undercontent/. API routes are underapp/api/.
- Configure search (e.g. Fumadocs search or Inkeep) in the root layout or docs layout (e.g.
RootProviderorDocsLayoutsearch options), and remove any Nextra search wiring.
- Generate Fumadocs source (usually automatic with Next):
npx fumadocs-mdx(or add topostinstallif you want types on install).
- Dev:
pnpm dev(ornpm run dev). - Build:
pnpm build(ornpm run build). If you hit peer dependency errors, usepnpm install --legacy-peer-depsor upgrade Next as above.