Skip to content

chore: migrate to fumadocs and nextjs app router#2606

Open
ArkuVonSymfon wants to merge 203 commits intolangfuse:mainfrom
Altalogy:to-fumadocs
Open

chore: migrate to fumadocs and nextjs app router#2606
ArkuVonSymfon wants to merge 203 commits intolangfuse:mainfrom
Altalogy:to-fumadocs

Conversation

@ArkuVonSymfon
Copy link

Motivation

Migrate the Langfuse docs site from Nextra (Pages Router) to Fumadocs (App Router) while keeping all existing content, styles, and redirects intact.


Description

Framework

  • Replaced nextra to fumadocs
  • Updated next.config.mjs, source.config.ts, tsconfig.json for Fumadocs; upgraded Tailwind v3 → v4
  • Switched production build to Turbopack

App Router

  • New app/ structure: (home), (wide) marketing pages, docs/[[...slug]], blog/, changelog/, and a generic [section]/[[...slug]] catch-all for guides, self-hosting, handbook, users, etc.

Content

  • All content moved from pages/content/<section>/ with meta.json nav files
  • /customers renamed to /users; old URLs covered by permanent redirects

Testing

  • pnpm run build completes without errors — TypeScript, MDX validation, and Turbopack all pass
  • Verified affected pages render correctly in dev server
  • All /customers/*/users/* redirects confirmed in lib/redirects.js

ArkuVonSymfon and others added 30 commits February 18, 2026 18:08
- Switch PostCSS plugin from tailwindcss to @tailwindcss/postcss
- Rewrite style.css for Tailwind v4 syntax (import, @theme, @variant dark)
- Fix fumadocs-ui CSS import order: neutral.css before preset.css
- Fix @apply !important syntax to Tailwind v4 suffix (!), e.g. bg-background!
- Move tailwind.config.js plugins from inside theme to top level (was bug)
- Remove dead nextra-specific CSS from src/overrides.css
- Add turbopack.root to fix Turbopack panic in git worktrees
- Add webpack NormalModuleReplacementPlugin for node: URI scheme
- Add remarkImageOptions: false to prevent remote image fetch at compile time

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: upgrade Tailwind CSS v3→v4 and resolve fumadocs-ui CSS issues
- Wrap NavbarLogo in flex-1 div to balance both sides of the flex layout,
  ensuring NavLinks is truly centered between logo and action buttons
- Update nav link styles to use explicit gray text colors with hover text-only
  transitions (no background on hover) matching Nextra link conventions

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix: center navbar and remove hover background from nav links
… fetching in customer components

Turbopack (used by `next dev`) does not apply webpack resolve.alias, so
`nextra/context` could not be resolved and CustomerCarousel/CustomerIndex
returned 0 stories, leaving the homepage slider empty.

- Refactor CustomerCarousel to accept `stories` prop instead of fetching
  internally via `getPagesUnderRoute`
- Refactor CustomerIndex similarly to accept `stories` prop
- CustomerStories (server component) now calls `getPagesForRoute` and
  passes data down to CustomerCarousel
- Add CustomerCarouselWrapper + CustomerIndexWrapper server components for
  MDX pages (enterprise, customers, press) that relied on the old path prop
- Update enterprise.mdx, customers.mdx, press.mdx to use wrapper components

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…arousel

The default fumadocs pageSchema strips all unknown fields via Zod strict parsing,
so CustomerCarousel received pages with empty frontMatter — no logos, quotes, or
authors — causing blank carousel cards.

Added customerFrontmatterSchema extending the base schema with all custom fields:
customerLogo, customerLogoDark, customerQuote, quoteAuthor, quoteRole,
quoteCompany, quoteAuthorImage, showInCustomerIndex, date, ogImage, tag, author.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ContentWrapper

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…er values

ogImage and other optional fields can be written as bare 'ogImage:' in YAML,
which parses as null. z.string().optional() only accepts string|undefined, so
swap all custom fields to .nullish() (string|null|undefined).

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Changelog.tsx: replace module-level nextra getPagesUnderRoute (which
  returns [] with Turbopack) with getPagesForRoute from @/lib/source
  called inside the component function
- source.config.ts: add changelogFrontmatterSchema extending default
  schema with date, author, ogImage so Fumadocs no longer strips those
  fields from changelog frontmatter
- OpenSource.tsx: duplicate discussions array ([...d, ...d]) in
  ScrollingDiscussions so the marquee loop is truly seamless with no
  visible jump at the end

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…imation

- source.config.ts: add yamlDateField helper using z.union([z.string(),
  z.date().transform(...)]) so unquoted YAML dates (e.g. `date: 2023-07-19`)
  which are parsed as JS Date objects pass schema validation and are
  normalised to YYYY-MM-DD strings; applied to both changelog and customer
  schemas
- shimmer-button.tsx: change animate-spin → animate-spin-custom so the
  spinning conic gradient uses the step-based keyframe defined in style.css
  (--animate-spin-custom / @Keyframes spin-custom) matching the Tailwind v3
  behaviour that was lost when migrating to Tailwind v4

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…ailwind v4

Tailwind v4 generates animation utilities as `animation: var(--animate-*)`,
where the custom property value itself contains another var() (e.g. var(--speed),
var(--duration)). This nested var() substitution inside an animation shorthand
is unreliable in some browser/engine combinations and can silently produce an
invalid animation declaration.

Changes:
- style.css: add explicit @layer utilities overrides for all affected
  animation classes (animate-slide, animate-spin-custom, animate-marquee,
  animate-marquee-vertical, animate-border-beam, animate-grid) that use
  direct shorthand values instead of var(--animate-*). These rules come
  after the auto-generated ones in cascade order and win cleanly.

- OpenSource.tsx ScrollingDiscussions: replace animate-marquee-vertical
  class + animationDirection inline-style (which conflict because the
  animation shorthand in the class resets animation-direction) with a
  single inline `animation` shorthand that includes `reverse` directly.
  This is unambiguous and immune to specificity/cascade issues.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
In Nextra (main branch) details/summary elements in MDX content were
styled as polished accordions by Nextra built-in CSS (border, chevron,
hover state). Fumadocs provides no default styling for them, so they
fell back to the browsers unstyled native disclosure widget.

- components/MdxDetails.tsx: new MdxDetails + MdxSummary components
  using Tailwind - rounded border, hidden native marker, ChevronRight
  icon that rotates 90 when open via group-open variant
- mdx-components.tsx: map details to MdxDetails and summary to MdxSummary
- style.css: add padding for content children of details elements

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…rdions

Two root causes caused FAQ accordions to show browser-default 'Details' label:

1. MdxParagraph wraps summary in a p when MDX sees no blank line between
   closing summary tag and body text. React does not auto-correct invalid DOM
   nesting (unlike the HTML parser), so summary stays inside p inside details
   and the browser never recognises it as the disclosure widget.

2. The BLOCK_TAGS check in MdxParagraph only matches string element types.
   Once summary is mapped to MdxSummary (a function) the check silently falls
   through and a p is emitted instead of a transparent Fragment.

Fixes applied:
- Add hasSummary guard in MdxParagraph: when MdxSummary is detected among
  children, return React Fragment so summary surfaces as a direct child of
  details in the DOM.
- Add blank lines after closing summary tag in all affected content files
  (observability/overview.mdx, security-and-guardrails.mdx,
  llm-as-a-judge.mdx, chatbot-analytics.mdx, testing-llm-applications.mdx)
  so MDX v3 parses summary JSX and body text as separate block elements.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
The entire testimonial card is wrapped in an <a> tag so users can click
through to the original post. Without explicit no-underline, the browser
default text-decoration:underline applies to all text inside the anchor
(name, handle, and quote content). Adding no-underline to the anchor
class removes the unwanted underline while keeping the card fully
clickable.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…lines

- TestimonialsGrid: constrain platform badge to w-5 h-5 with overflow-hidden,
  flex-center, and proper dark mode bg so the logo sits cleanly inside the circle
- TestimonialsGrid: add no-underline to card anchor (browser default was
  underlining all text inside the link)
- CustomerIndex: reorder Tailwind classes (linter)
- pagination: add list-none to PaginationContent/PaginationItem (linter)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@dosubot dosubot bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:XXL This PR changes 1000+ lines, ignoring generated files. labels Mar 13, 2026
ArkuVonSymfon and others added 3 commits March 17, 2026 09:58
- Remove upgrade-path.mdx (single file conflicted with new upgrade-path/ directory)
- Replace upgrade-path/_meta.tsx (Nextra) with meta.json (Fumadocs format)
- Move content/jp-cloud.mdx → content/marketing/jp-cloud.mdx and register as marketing page
- Fix jp-cloud.mdx import: relative ../components → @/components/jp-cloud
- Add jp-cloud to MARKETING_SLUGS (lib/source.ts) and content/marketing/meta.json
- Add claude-agent-sdk-js to content/integrations/frameworks/meta.json
- Add v4 to content/docs/meta.json sidebar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add langfuse.com to images.remotePatterns in next.config.mjs
- Change dev script from -H localhost to -H 127.0.0.1

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request size:XL This PR changes 500-999 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants