DEV Community

NextBlock™ CMS
NextBlock™ CMS

Posted on

Why We Ditched Hardcoded globals.css for a Database-Driven Theme Engine in NextJS

Updating CSS variables in open-source or client-hosted projects has always been a sneaky source of friction:

The Codebase Barrier: If a client or marketer wants to change a brand color, a developer has to open globals.css or tailwind.config.ts.

The Deployment Tax: Even a one-line CSS tweak triggers a full build pipeline on Vercel or Netlify.

When designing the latest feature update for NextBlock CMS, we asked a simple question: What if themes were treated as pure dynamic data instead of static assets?

The Architecture Shift
We replaced traditional hardcoded CSS declarations with a Dynamic Theme Schema:

[ CMS Dashboard Theme Controls ]
               │
               ▼
[ Supabase / PostgreSQL ] (Stores CSS Tokens & Theme JSON)
               │
               ▼
[ Next.js Root Layout (RSC) ] (Injects CSS Variables into <head>)
               │
               ▼
[ Instant Live Render across UI ] (Zero Redeploys)
Enter fullscreen mode Exit fullscreen mode

Database Schema: We store root CSS custom properties (--primary, --background, --radius, custom CSS blocks) directly in PostgreSQL.

Root Layout Injection: NextBlock’s root Server Component fetches the active theme state at runtime and injects it as scoped CSS variables into the :root document header.

Tailwind Integration: Tailwind classes reference standard CSS variables (e.g., bg-primary), making the entire UI react automatically to dynamic DB values.

Now, changing a theme or adding custom global CSS happens in milliseconds from the dashboard—with zero code edits and zero redeploys.

Graph to display old way of using globals.css instead of a CMS Theme builder

What strategies do you use for managing runtime design systems in Next.js? Let’s discuss in the comments!

Top comments (0)