@fairgarden/indicators

Put the locale, the user's preferences and the request's flags into the path, so every variant of a page is a plain static route.

/login  +  cookie theme=dark  +  X-Vercel-IP-Timezone: America/New_York
-> /en/theme~dark/tz~EST/login

Next caches by path. Cookies and headers are not part of the key, and reading them from a page makes it dynamic. Rewriting them into the path keeps the page static and gives each audience its own copy: the hot path stays one prerendered file, the long tail renders once on demand, and nothing is rendered per request.

// lib/indicators.ts
import { createIndicators } from '@fairgarden/indicators'

export const indicators = createIndicators({
  locales: ['en', 'fr'],
  defaultLocale: 'en',
  prefs: { theme: { values: ['light', 'dark'] } },
  flags: {
    tz: {
      header: 'x-vercel-ip-timezone',
      values: { EST: 'America/(New_York|Toronto|Detroit)' },
    },
  },
})
// next.config.ts
import { withFairGardenIndicators } from '@fairgarden/indicators/withFairGardenIndicators'
import { indicators } from './lib/indicators.ts'

export default withFairGardenIndicators(nextConfig, indicators)
// app/[locale]/[prefs]/[flags]/layout.tsx
export const generateStaticParams = indicators.generateStaticParams

export default indicators.layout(({ children, locale, prefs }) => (
  <html lang={locale} data-theme={prefs.theme}>
    <body>{children}</body>
  </html>
))

Start here

Install

pnpm add @fairgarden/indicators

| Import | For | | --- | --- | | @fairgarden/indicators | lib/indicators.ts, layouts and pages | | @fairgarden/indicators/withFairGardenIndicators | next.config.ts | | @fairgarden/indicators/link | a client module exporting the app's Link and hooks | | @fairgarden/indicators/proxy | proxy.ts |

Mounting several apps into one deployment is a separate concern, handled by @fairgarden/monolith; see In a monolith for how the two fit.