Core Framework Integration for Generating CSS Tokens in Instatic

Instatic's Core Framework module centralizes design-system definitions and transforms them into CSS custom properties and utility classes through a validated, multi-stage pipeline.

The Core Framework integration is the engine behind Instatic's token-driven CSS generation. It bridges the visual editor's design panels with the static publishing pipeline, ensuring every site emits consistent, namespaced CSS tokens that can be safely overridden by user styles.

This article walks through the complete workflow—from framework settings in the admin UI to the final framework.css bundle—using actual source paths and function signatures from the CoreBunch/Instatic repository.

How Framework Settings Become CSS Tokens

The pipeline begins when site owners configure design tokens through the admin interface. These settings flow through validation, planning, and rendering stages before reaching the published page.

Step 1: Framework Settings Validation

Site configurations are stored in site.settings.framework and validated against FrameworkSettingsSchema in src/core/framework-schema/schemas.ts. This TypeBox schema enforces type safety for colors, typography, spacing scales, and other design primitives.

Admin panels for Colors, Typography, and Spacing write to this validated structure. Invalid or incomplete settings fail fast at the schema level, preventing downstream errors in CSS generation.

Step 2: Building the Framework Plan

The buildFrameworkPlan function in src/core/framework/index.ts transforms validated settings into an executable plan. This plan contains:

  • Root custom-property definitions for color, font-family, and spacing tokens
  • Generated utility classes for each scale step (e.g., .font-size-lg, .gap-2)

The plan acts as an intermediate representation—decoupled from both the admin UI and the final CSS output. This separation allows the publisher to optimize without affecting the authoring experience.

Step 3: CSS Generation and Bundling

The publisher consumes the framework plan in src/core/publisher/frameworkCss.ts. Two key functions orchestrate this stage:

Function Location Purpose
buildSiteFrameworkCss(site) src/core/publisher/frameworkCss.ts Orchestrates the full generation workflow
generateFrameworkCss(site) src/core/publisher/frameworkCss.ts Renders the final framework.css bundle

The generated CSS includes:

/* Example output: root custom properties */
:root {
  --color-primary: #007bff;
  --font-primary: 'Inter', sans-serif;
  --space-4: 1rem;
}

/* Example output: utility classes */
.font-size-lg { font-size: var(--font-size-lg); }
.gap-2 { gap: var(--space-2); }

Step 4: Token Emission and Cascade Order

In src/core/publisher/render.ts, the final page CSS is assembled by concatenating four bundles in strict order:

  1. reset — browser normalization
  2. framework — the generated design tokens
  3. style — component-level styles
  4. userStyles — custom user CSS

This ordering guarantees framework tokens appear before user-defined CSS, enabling predictable overrides without specificity battles.

Token Scale Generation Internals

The framework doesn't hand-write every token. Shared engines in src/core/framework/ compute systematic scales.

Spacing and Typography Scales

Both modules leverage src/core/framework/scaleModule.ts, the shared engine that creates the token-to-utility-class mapping. This abstraction ensures consistent naming conventions and calculation logic across different token categories.

Runtime Token Consumption

Framework tokens aren't just for published output. The admin UI itself consumes them through design-token primitives.

UI Primitive: pillAccent

Located at src/ui/pillAccent.ts, this primitive selects deterministic accent tokens from the framework palette:

import { pillAccent } from '@/ui/pillAccent';

const accent = pillAccent('primary'); // → '--pill-primary' custom property

Components like pills, badges, and buttons use these primitives to maintain visual consistency with the site's configured theme without hardcoding values.

Import and Conflict Resolution

When external CSS is imported, the framework handles token extraction and merging through src/core/siteImport/*.

Token Extraction Pipeline

Module Function
src/core/siteImport/colorTokens.ts Extracts :root color properties, rewrites as framework tokens
src/core/siteImport/fontTokens.ts Extracts font-family declarations, registers as framework tokens
src/core/siteImport/conflicts.ts Detects and resolves token name collisions

Imported custom properties are namespace-migrated into the framework registry, preserving their values while ensuring they follow Instatic's token conventions.

Complete Workflow Example

Here's the full chain from settings to published CSS:

// 1️⃣ Resolve framework preferences (with sensible defaults)
import { resolveFrameworkPreferences } from '@core/framework';

const prefs = resolveFrameworkPreferences(site.settings.framework?.preferences);

// 2️⃣ Build the framework plan (scales, colors, utilities)
import { buildFrameworkPlan } from '@core/framework';

const { rootCss, utilityClasses } = buildFrameworkPlan(site.settings.framework);

// 3️⃣ Generate the final CSS bundle for publishing
import { generateFrameworkCss } from '@core/publisher';

const frameworkCss = generateFrameworkCss(site);

// 4️⃣ Use a token in a component (e.g., a Pill)
import { pillAccent } from '@/ui/pillAccent';

const accent = pillAccent('primary'); // → '--pill-primary' custom property

Each stage is pure and testable: preferences resolve against defaults, plans build deterministically from settings, and CSS generates without side effects.

Key Architectural Guarantees

The Core Framework integration provides three invariant properties:

  • Namespace safety — all tokens use the -- prefix, preventing collisions with third-party CSS
  • Tree-shaking — only utility classes actually referenced by site content appear in framework.css
  • Zero runtime — the published framework.css contains no editor code or JavaScript dependencies, ensuring fully static output

Summary

Frequently Asked Questions

What file generates the actual framework.css output?

The generateFrameworkCss function in src/core/publisher/frameworkCss.ts renders the final bundle. It consumes the framework plan built by buildFrameworkPlan and outputs CSS containing root custom properties and utility classes.

How does Instatic handle conflicts between imported CSS tokens and existing framework tokens?

Conflicts are detected and resolved in src/core/siteImport/conflicts.ts. The pipeline extracts :root custom properties from imported CSS via src/core/siteImport/colorTokens.ts and src/core/siteImport/fontTokens.ts, rewrites them as framework tokens, and merges them with the existing registry according to conflict resolution rules.

Can users override framework tokens in their custom CSS?

Yes. The render pipeline in src/core/publisher/render.ts concatenates bundles with framework preceding userStyles. This cascade order allows user-defined CSS to override any framework token using standard CSS custom property semantics.

What ensures that only used utility classes are included in the output?

The framework plan tracks which utility classes are referenced by site content. The publisher performs tree-shaking during generateFrameworkCss, emitting only classes that appear in the site's component graph—keeping framework.css lean for performance.

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 →