Instatic Design Tokens and CSS Modules Conventions: A Complete Developer Guide

Instatic enforces a strict, token-driven styling system where every visual property is defined as a CSS custom property in src/styles/globals.css and referenced exclusively via CSS Modules, with automated tests blocking hard-coded values and Tailwind usage.

The CoreBunch/Instatic repository implements a rigorous design tokens and CSS modules conventions architecture to ensure visual consistency across its admin interface. Every color, spacing value, and typographic scale is abstracted into reusable CSS custom properties, while component styles are isolated through adjacent CSS Modules. This approach guarantees a themable, maintainable UI that prevents accidental style drift through automated enforcement.

Design Token Architecture in Instatic

Centralized Token Definitions in globals.css

All design tokens reside in src/styles/globals.css, serving as the single source of truth for the entire application. Adding a new token requires appending a --your-token definition to this file, which can then be accessed via var(--your-token) throughout the codebase. This centralization ensures that brand colors, spacing scales, and radius values remain synchronized across all admin components.

Token Categories and Naming Patterns

Instatic organizes tokens by functional purpose rather than arbitrary values. Color tokens follow semantic grouping—--bg-surface, --border-default, --text-bright, and --overlay-10—with opacity variants using numeric suffixes (e.g., --accent-1 and --accent-1-10 for 10% opacity). Radius tokens differentiate contexts explicitly: --editor-radius-sm, --editor-radius, --panel-radius, and --input-radius each serve specific UI regions. Spacing tokens range from --space-4xs to --space-12xl, while typography tokens span --text-xs through --text-xl.

Fluid Spacing and Typography Scales

Unlike static pixel values, Instatic's spacing and typography tokens use clamp() functions to create fluid, viewport-adaptive scales. This eliminates the need for media query breakpoints while maintaining readable proportions across device sizes. The fluid system applies consistently from --space-4xs (minimal gaps) to --space-12xl (major layout sections).

CSS Modules Conventions and File Organization

Adjacent Module Pattern

Components located in src/admin/, src/admin/pages/site/, and src/ui/ directories must co-locate styles using the [ComponentName].module.css naming convention. For example, src/ui/components/Button/Button.module.css contains all Button-specific styles, while src/ui/components/Card/Card.module.css houses card layouts. This adjacency pattern keeps styles discoverable and scoped to their respective components.

camelCase Class Naming

Class selectors within modules use camelCase (e.g., .primaryButton, .cardContainer) rather than kebab-case or BEM methodology. This convention aligns with JavaScript object property access patterns when importing style objects into React components. The CSS Modules build step automatically scopes these classes to prevent global namespace pollution.

Strict Enforcement: No Raw Values or Tailwind

Automated Token Policy Testing

The repository includes src/__tests__/architecture/css-token-policy.test.ts, which fails any build containing raw hex codes, rgb/hsl values, or pixel literals in CSS Modules. This architectural test enforces 100% token adoption—every visual value must reference a custom property via var(--*). Direct literals such as color: #ff0000 or margin: 16px trigger immediate test failures.

Tailwind Prohibition

Instatic explicitly forbids Tailwind CSS utilities and dependencies. The test suite includes noTailwindUtilities.test.ts and no-tailwind-deps.test.ts to prevent utility-class imports or Tailwind-related package dependencies. All styling must occur through CSS Modules referencing design tokens, ensuring the admin UI remains free from utility-class sprawl and specificity conflicts.

Specificity and !important Rules

The codebase bans !important declarations except in two designated exceptions: globals.css for reduced-motion accessibility handling and Button.module.css for specificity reset requirements. This restriction prevents brittle style overrides and maintains the cascade's predictability.

Implementation Examples

Adding a Color Token and Using It in a Component

First, define the token in the global stylesheet:

/* src/styles/globals.css – add the token */
:root {
  --brand-primary: #4a90e2;
  --brand-primary-10: rgba(74,144,226,0.1);
}

Then reference it in a CSS Module:

/* src/ui/components/Alert/Alert.module.css – reference the token */
.alert {
  background-color: var(--brand-primary-10);
  border: 1px solid var(--brand-primary);
  color: var(--text-bright);
  border-radius: var(--editor-radius);
  padding: var(--space-m);
}

Using Fluid Spacing in Layout Components

/* src/ui/components/Stack/Stack.module.css */
.stack {
  display: flex;
  flex-direction: column;
  gap: var(--space-s);   /* fluid spacing – no hard-coded pixels */
}

Referencing Radius Tokens in Cards

/* src/ui/components/Card/Card.module.css */
.card {
  background: var(--bg-surface);
  border-radius: var(--panel-radius);   /* 12 px radius – shared token */
  box-shadow: 0 2px 4px var(--overlay-10);
}

Summary

  • All design tokens are centralized in src/styles/globals.css as CSS custom properties, categorized by semantic purpose (surface, border, text, accent)
  • CSS Modules must use adjacent file naming (Component.module.css) and reside in approved directories (src/admin/, src/ui/)
  • Automated tests in src/__tests__/architecture/ block hard-coded values (css-token-policy.test.ts) and Tailwind usage (noTailwindUtilities.test.ts)
  • Token references must use var(--*) syntax exclusively; no raw hex, rgb, or pixel values are permitted
  • Class names follow camelCase conventions within modules, and !important is banned except in globals.css and Button.module.css

Frequently Asked Questions

Where are design tokens defined in Instatic?

All design tokens are defined as CSS custom properties in src/styles/globals.css. This centralized approach ensures that colors, spacing, typography, and radius values remain consistent across the admin interface and can be updated from a single location, as documented in docs/reference/design-tokens.md.

How does Instatic prevent hard-coded CSS values?

The repository uses src/__tests__/architecture/css-token-policy.test.ts to scan CSS Modules for raw hex codes, rgb values, and pixel literals. Any module containing hard-coded values fails the test suite, enforcing the requirement that all visual properties reference tokens via var() notation.

Why does Instatic ban Tailwind CSS?

Instatic prohibits Tailwind utilities and dependencies through noTailwindUtilities.test.ts and no-tailwind-deps.test.ts to maintain strict visual consistency and prevent utility-class sprawl. The architecture requires explicit token references through CSS Modules instead of utility composition, ensuring design system adherence.

What naming convention should CSS Module class names follow?

Class names within CSS Modules use camelCase (e.g., .buttonPrimary, .cardHeader) rather than kebab-case or BEM. This convention aligns with JavaScript object property access patterns when importing styles into React components, and is enforced by the project's style guide in docs/design.md.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →