The Pipeline
Overview
Section titled “Overview”Dispersa processes design tokens through a pipeline from resolution to rendered output. Tokens flow from a resolver document through shared stages (run once) and per-output stages (run for each output), being resolved, filtered, transformed, and formatted along the way.
Click any stage below to see what it does:
Loads the DTCG resolver document and validates it against the official DTCG 2025.10 JSON schema, catching structural errors like missing versions, invalid set references, or malformed modifiers. After validation, sets are merged in order and modifier contexts (themes, platforms, densities) are applied to produce the raw token tree for each permutation.
Stages
Section titled “Stages”| Stage | Scope | Description |
|---|---|---|
| 1. Resolve | Shared | Load and validate the resolver document, merge sets, apply modifier contexts |
| 2. Preprocess | Shared | Run optional preprocessors on the raw token tree |
| 3. Parse | Shared | Validate and flatten token documents, resolve references and aliases |
| 4. Lint | Shared | Run lint rules on resolved tokens (optional, configured via lint option) |
| 5. Global Filter | Shared | Remove tokens globally before per-output processing |
| 6. Global Transform | Shared | Transform all tokens before per-output processing |
| 7. Filter | Per-output | Further narrow tokens for each specific output |
| 8. Transform | Per-output | Convert token values and names for the target platform |
| 9. Render | Per-output | Format tokens into CSS, JSON, JS, Tailwind, Swift, Kotlin, etc. |
Global vs. Per-Output
Section titled “Global vs. Per-Output”Stages 1-6 run once for the entire build and produce a resolved, flat token set. Stages 7-9 run per output, so each output can have its own filters, transforms, and renderer.
Stages 1-6: Shared (run once)
Section titled “Stages 1-6: Shared (run once)”-
Resolve — Loads and parses the resolver document. The resolver is validated against the official DTCG 2025.10 JSON schema, catching structural errors like missing versions, invalid set references, or malformed modifiers. After validation, sets are merged in order and modifier contexts (themes, platforms, densities) are applied to produce the raw token tree for each permutation.
-
Preprocess — Runs optional preprocessors on the raw token tree. Use this to strip vendor metadata, inject computed tokens, or normalize legacy formats before parsing.
-
Parse — Resolves JSON Pointer
$refreferences (including external files), flattens nested groups to dot-path keys (e.g.color.action.brand), inherits group-level$type, and resolves{token.name}alias references with circular dependency detection. During parsing, each token document is validated against the DTCG format schema, and individual tokens are checked against their type-specific schemas (color, dimension, etc.). Token names and group structures are also validated per the DTCG specification. -
Lint — Runs lint rules on resolved tokens to check for issues like naming conventions, missing descriptions, deprecated usage, or custom rules from plugins. Linting is optional and configured via the
lintoption inBuildConfig. Results are included in build output when linting is enabled. -
Global Filter — Global filters from
BuildConfigreduce the token set for all outputs. Tokens excluded here never reach any output. -
Global Transform — Global transforms from
BuildConfigrun on all tokens (e.g.nameKebabCase()). These apply before any per-output transforms.
Stages 7-9: Per-output
Section titled “Stages 7-9: Per-output”-
Filter — Per-output filters from each
OutputConfigfurther narrow the globally transformed set for that specific output. -
Transform — Per-output transforms run after global transforms (e.g.
colorToHex()for CSS). They convert token values and names for the target format. -
Render — The renderer formats the final tokens into the target output: CSS custom properties, JSON, JS/TS modules, Tailwind
@themeblocks, Swift/SwiftUI, Kotlin/Compose, or any custom format viadefineRenderer.
Processing Order
Section titled “Processing Order”import { build, css, json } from 'dispersa'import { byType, nameKebabCase } from 'dispersa/transforms'
await build({ // Global: applied to ALL outputs (stages 5-6) filters: [byType('color')], transforms: [nameKebabCase()],
outputs: [ css({ name: 'css', // Per-output: applied AFTER global (stages 7-8) transforms: [ /* color transforms */ ], }), json({ name: 'json', // Per-output: different transforms for this output transforms: [ /* other transforms */ ], }), ],})