Blueprint

System Data Flow

Entry Point
Process Node
Data Store
Output
Productionv2.0.0

Zero-FOUC Theme Engine

Performance / DX

A synchronously-executed IIFE injected into the document <head> that resolves theme state before React hydrates — eliminating the flash of unstyled content (FOUC) entirely.

Logic Breakdown

The engine reads from localStorage first, then falls back to the OS-level `prefers-color-scheme` media query if no stored preference exists. The resolved theme token is written directly to `document.documentElement` as both a `data-theme` attribute and a CSS custom property, ensuring the design token cascade is authoritative before any stylesheet or React tree is evaluated.

Architecture Decisions

  • 01IIFE injected as a blocking `<script>` tag before any stylesheets in the document `<head>`.
  • 02`localStorage.getItem('bc-theme')` resolves a stored user preference synchronously.
  • 03If no stored value, `window.matchMedia('(prefers-color-scheme: dark)')` provides the OS default.
  • 04`document.documentElement` receives both a `data-theme` attribute and CSS custom property before first paint.

Code Snippet

typescript
zero-fouc-theme-engine.ts
// Injected as a blocking <script> in app/layout.tsx
// Runs synchronously before React hydrates — zero FOUC.
(function () {
  try {
    const stored = localStorage.getItem("bc-theme");
    const prefersDark = window.matchMedia(
      "(prefers-color-scheme: dark)"
    ).matches;
    const theme = stored ?? (prefersDark ? "dark" : "light");
    document.documentElement.setAttribute("data-theme", theme);
    document.documentElement.style.setProperty(
      "--bg-primary",
      theme === "dark" ? "#000000" : "#FFFFFF"
    );
  } catch (_) {}
})();

Key Dependencies

No external depsPure browser APIs only
localStorage APInativeTheme preference persistence
matchMedia APInativeOS-level color scheme detection

Known Limitations

  • Blocking execution adds ~0.5ms to TTFB — acceptable for zero FOUC; do not add async work inside.
  • localStorage is unavailable in SSR context — the try/catch guard is non-negotiable.

Technical Spec

Pattern
Blocking IIFE
Storage
localStorage
Fallback
matchMedia
Injection
<head> pre-hydration
Token
CSS Custom Property
Framework
Next.js App Router
Flash Events
0
Status
Production

Tags

TypeScriptlocalStorageCSS VariablesSSRNext.js

Live Sandbox

Interactive runtime environment — Zero-FOUC Theme Engine v2.0.0

Production
zero-fouc-theme-engine-sandbox

$ npm run sandbox

> Initialising Zero-FOUC Theme Engine v2.0.0

> Status: Production

// Live iframe mounted once sandboxUrl is configured.