All docs

Docs

Next.js migration — Design Library (completed)

This document describes the migration of apps/design-library from Vite + React Router to Next.js (App Router), including folder structure and token strictness decisions.


What changed (baseline → target)

  • App: apps/design-libraryNext.js 16 with src/app routes; removed Vite, index.html, main.tsx, and App.tsx.
  • Routing: URLs under /library/... are implemented as src/app/library/**/page.tsx files plus src/app/library/layout.tsx wrapping LibraryAppLayout.
  • Tokens import: Vite alias @tokens replaced by package export @spring/ds-react/tokens (packages/spring-ds-react/package.json).
  • Tailwind: tailwind.config.mjs imports tokens from @spring/ds-react/tokens (no deep relative path to index.mjs).
  • CSS variables: Root src/app/layout.tsx imports @spring/ds-react/tokens/generated/css-variables.css (SSR-friendly; no runtime <style> injection).
  • Fonts: Inter via next/font/google; globals.css no longer @imports Google Fonts. Tailwind :root --font-sans uses var(--font-inter), ….
  • Token validation: scripts/sync-tokens.js runs Zod shape checks and verifies every string path in figmaMap sections resolves via getByPath (root devDependency zod).
  • Logos: SpringLogo assets live in packages/spring-ds-react/src/assets/ (no Vite ?url, no dependency on apps/design-library paths).

Target folder structure

Monorepo unchanged: apps/*, packages/*.

Inside the design-library app:

apps/design-library/
  next.config.ts
  postcss.config.js
  tailwind.config.mjs
  tsconfig.json
  package.json
  public/                    # static assets (if any)
  src/
    app/                     # Next.js App Router
      layout.tsx             # root: metadata, Inter, token CSS, globals.css
      page.tsx               # redirect → /library/getting-started
      not-found.tsx
      library/
        layout.tsx             # LibraryAppLayout + {children}
        page.tsx               # redirect → getting-started
        getting-started/page.tsx
        design-tokens/...
        icons/page.tsx
        components/.../page.tsx
        patterns/.../page.tsx
        design-libraries/.../page.tsx
    gallery/                 # existing docs UI (layouts, nav, pages)
    lib/                     # tokenDatasets, useHash, utils
    styles/globals.css
    middleware.ts            # at src/middleware.ts — redirects / and non-/library/*

Note: middleware.ts lives under src/ per Next.js. Next 16 may warn that the middleware file convention is deprecated in favor of “proxy”; revisit when upgrading.


Token strictness

  1. Single source of truth (unchanged): design-tokens.mjs / core.mjs; generation via npm run tokens:syncgenerated/css-variables.css.

  2. Public export: @spring/ds-react/tokens and @spring/ds-react/tokens/generated/css-variables.css are declared in package exports.

  3. sideEffects: @spring/ds-react lists **/*.css and token **/*.mjs so bundlers do not drop CSS side effects.

  4. Build-time Zod validation: On node scripts/sync-tokens.js build, after importing the token bundle, validateTokenBundle runs:

    • Zod schema for primitive, semantic, and figmaMap (with passthrough for extra keys).
    • For each figmaMap section (except nodes), every string value must resolve with getByPath(tokens, path) (non-undefined).
  5. TypeScript: App tsconfig.json remains strict: true (Next may adjust jsx / includes automatically).


Next.js wiring (checklist)

  • transpilePackages: ['@spring/ds-react']next.config.ts.
  • Path aliases: @/*./src/*; explicit @spring/ds-react/tokens and icons paths in tsconfig.
  • Tailwind content: src/**/* and packages/spring-ds-react/src/**/* (see tailwind config).
  • Client boundaries: Interactive gallery modules use 'use client' (including pages that pass render props into client components, e.g. input anatomy blocks).

Migration sequence (as executed)

  1. Add @spring/ds-react/tokens export; switch Tailwind and TS imports off @tokens / relative index.mjs.
  2. Scaffold Next (layout, page, library layout, transpilePackages, token CSS import).
  3. Port every React Router segment to src/app/library/.../page.tsx; remove Vite entry and router.
  4. Add Zod validation to scripts/sync-tokens.js; add zod to root devDependencies.
  5. Update manual browser preview script for next start on port 5180.
  6. Record this document at docs/history/migration-vite-to-next.md.

Risks and follow-ups

TopicNotes
Next middleware deprecationNext 16 warns about middleware → “proxy”; monitor upgrade guide.
Duplicate logo assetsapps/design-library/src/assets/SpringLogo*.svg may still exist; canonical copies are under packages/spring-ds-react/src/assets/.
React Server ComponentsPrefer server page.tsx wrappers; keep interactive docs in client gallery modules.

Out of scope (still)

  • Repo-wide RSC refactors for every spring-ds-react component.
  • Splitting tokens into a dedicated @spring/tokens package.
  • Deploy / basePath specifics (Vercel, static export, etc.).