# How Instatic CSS Modules Work with Design Tokens: A Complete Architecture Guide

> Learn how Instatic CSS Modules leverage design tokens for a unified style architecture. Explore CSS custom properties and zero hard-coded values for efficient web design.

- Repository: [CoreBunch/Instatic](https://github.com/CoreBunch/Instatic)
- Tags: architecture
- Published: 2026-07-31

---

**Instatic uses CSS Modules scoped to individual components that reference global CSS custom properties defined in [`src/styles/globals.css`](https://github.com/CoreBunch/Instatic/blob/main/src/styles/globals.css), ensuring a single source of truth for all visual styles while enforcing zero hard-coded values or fallbacks.**

The CoreBunch/Instatic repository implements a strict design-token architecture where every visual style for the admin and editor UI flows from centralized definitions. By combining CSS Modules with globally scoped CSS custom properties, the codebase eliminates style fragmentation and guarantees consistent theming across the entire application.

## The Architecture: Global Tokens Meet Scoped Modules

Instatic's styling architecture rests on two complementary layers. The foundation is [`src/styles/globals.css`](https://github.com/CoreBunch/Instatic/blob/main/src/styles/globals.css), which declares all **design tokens** as `:root` custom properties covering colors, spacing, typography, radius, overlays, and semantic states (lines 14–96). These tokens are globally available to any stylesheet in the application.

The second layer consists of **CSS Modules**—files like [`Button.module.css`](https://github.com/CoreBunch/Instatic/blob/main/Button.module.css), [`Card.module.css`](https://github.com/CoreBunch/Instatic/blob/main/Card.module.css), and [`Tooltip.module.css`](https://github.com/CoreBunch/Instatic/blob/main/Tooltip.module.css)—that the build pipeline (Vite plus Bun) treats as locally scoped stylesheets. While class names generated from these modules are scoped to specific components, any `var(--token)` reference resolves to the global value defined in [`globals.css`](https://github.com/CoreBunch/Instatic/blob/main/globals.css). This separation ensures that component styles remain encapsulated while values remain centralized.

## How Design Tokens Are Defined

All visual primitives originate in the global stylesheet. The token definitions follow a strict naming convention using CSS custom properties:

```css
/* src/styles/globals.css */
:root {
  /* Surfaces */
  --bg-surface: #1e1e1e;
  --bg-surface-2: #282828;
  
  /* Typography */
  --text: #ffffff;
  --text-secondary: #a0a0a0;
  
  /* Spacing & Radius */
  --space-s: 0.5rem;
  --space-m: 1rem;
  --radius: 0.5rem;
  
  /* Semantic colors */
  --accent-1: #3b82f6;
}

```

According to the Instatic source code, **no hard-coded hex, RGB, or HSL values** may appear in admin UI CSS. Every color must derive from this token set, preventing arbitrary values from fragmenting the design system.

## Consuming Tokens in CSS Modules

Component-level styles import these global values using standard CSS `var()` syntax. The repository enforces a critical rule: **no fallbacks are allowed** in token usage. The pattern `var(--token, fallback)` is explicitly forbidden, ensuring that missing tokens surface as build-time errors rather than silently reverting to hard-coded defaults.

Consider the Button component implementation:

```css
/* src/ui/components/Button/Button.module.css */
.root {
  background: var(--bg-surface-2);
  color: var(--text);
  border-radius: var(--radius);
  padding: var(--space-s) var(--space-m);
  border: 1px solid var(--border-subtle);
}

```

This pattern repeats across the component library in files like [`Alert.module.css`](https://github.com/CoreBunch/Instatic/blob/main/Alert.module.css) and [`Tooltip.module.css`](https://github.com/CoreBunch/Instatic/blob/main/Tooltip.module.css). Because the tokens are CSS custom properties rather than Sass variables or static values, **changing a token value in [`globals.css`](https://github.com/CoreBunch/Instatic/blob/main/globals.css) automatically updates every component** that references it without requiring a rebuild of individual module files.

## Component Implementation Pattern

TypeScript components import their corresponding CSS Modules as plain objects. The build system maps the local class names to unique scoped identifiers while preserving the global variable references:

```tsx
// src/ui/components/Button/Button.tsx
import styles from "./Button.module.css";

interface Props {
  children: React.ReactNode;
  onClick?: () => void;
}

export function Button({ children, onClick }: Props) {
  return (
    <button className={styles.root} onClick={onClick}>
      {children}
    </button>
  );
}

```

The resulting DOM element receives a scoped class name (e.g., `Button_root__xyz123`) that references the global custom properties. This approach guarantees that the visual language remains consistent even as the component hierarchy grows complex.

## Key Enforcement Rules

The architecture relies on strict enforcement to maintain integrity:

- **Zero hard-coded values**: As verified in [`src/ui/components/Button/Button.module.css`](https://github.com/CoreBunch/Instatic/blob/main/src/ui/components/Button/Button.module.css), all colors must reference design tokens
- **No fallback values**: As demonstrated in [`src/ui/components/Alert/Alert.module.css`](https://github.com/CoreBunch/Instatic/blob/main/src/ui/components/Alert/Alert.module.css), the codebase forbids `var(--token, fallback)` syntax to prevent silent failures
- **Global availability**: Because tokens live on the `:root` selector, they cascade naturally to every CSS Module without explicit imports

## Summary

- Instatic stores all design tokens as CSS custom properties in [`src/styles/globals.css`](https://github.com/CoreBunch/Instatic/blob/main/src/styles/globals.css) (lines 14–96), creating a single source of truth for colors, spacing, and typography
- CSS Modules provide scoped class names for components while referencing global token values via `var(--token)` syntax
- The build pipeline (Vite + Bun) processes [`.module.css`](https://github.com/CoreBunch/Instatic/blob/main/.module.css) files to ensure local scope for class names but global resolution for variable values
- Strict rules prohibit hard-coded colors and fallback values in `var()` functions, forcing immediate visibility of missing tokens
- Runtime updates to [`globals.css`](https://github.com/CoreBunch/Instatic/blob/main/globals.css) propagate instantly across the entire UI without rebuilding individual components

## Frequently Asked Questions

### Why does Instatic forbid fallback values in CSS variables?

Instatic explicitly disallows `var(--token, fallback)` syntax to ensure design system integrity. When a token is missing or renamed, the build process surfaces the error immediately rather than silently rendering a hard-coded fallback color. This enforcement, visible in files like [`src/ui/components/Alert/Alert.module.css`](https://github.com/CoreBunch/Instatic/blob/main/src/ui/components/Alert/Alert.module.css), prevents visual inconsistencies and forces developers to maintain the centralized token definitions.

### How do CSS Modules access global custom properties without importing them?

CSS custom properties declared on the `:root` selector in [`src/styles/globals.css`](https://github.com/CoreBunch/Instatic/blob/main/src/styles/globals.css) cascade to every element in the document, including those styled by CSS Modules. While the class names generated by CSS Modules (like `.root` in [`Button.module.css`](https://github.com/CoreBunch/Instatic/blob/main/Button.module.css)) are locally scoped to avoid naming collisions, the `var(--token)` references resolve against the global `:root` context where the values are defined.

### What happens when I need to add a new color to the design system?

You must define the new token in [`src/styles/globals.css`](https://github.com/CoreBunch/Instatic/blob/main/src/styles/globals.css) within the `:root` selector, following the existing naming convention (e.g., `--accent-3` or `--state-error`). Once defined, any CSS Module can reference it immediately using `var(--new-token)`. Because tokens are CSS custom properties rather than compiled constants, no rebuild of the CSS Modules is required—the new value becomes available instantly across all components.

### Can I override tokens for specific themes or modes?

Yes. Because Instatic uses standard CSS custom properties, you can redefine token values under specific selectors or media queries in [`globals.css`](https://github.com/CoreBunch/Instatic/blob/main/globals.css). For example, wrapping theme overrides in a `[data-theme="dark"]` selector automatically switches all referenced values across every CSS Module without modifying individual component styles. This cascade behavior ensures that theming remains maintainable at the global level while components remain agnostic to the active theme.