Sigil Preset
Create and modify complete token presets that define the visual identity of a Sigil-powered project.
The #1 Rule: Full Token Coverage
Every custom preset MUST populate ALL 33 token categories and ALL fields.
The canonical template is packages/presets/src/_template.ts. It contains every
field from SigilTokens with sensible defaults. When creating a custom preset:
- Start from the template — copy
_template.ts, rename, change values.
- Never delete fields — change values, don't remove keys.
- No partial presets — if a field exists in
_template.ts, it must exist in your preset.
The 33 required categories (all must be present):
| # |
Category |
Fields |
Required |
| 1 |
colors |
36 |
yes (type-required) |
| 2 |
typography |
31 |
yes (type-required) |
| 3 |
spacing |
25 |
yes (type-required) |
| 4 |
layout |
22 |
yes (template-required) |
| 5 |
sigil |
10 |
yes (type-required) |
| 6 |
radius |
16 |
yes (type-required) |
| 7 |
shadows |
14 |
yes (type-required) |
| 8 |
motion |
19 |
yes (type-required) |
| 9 |
borders |
11 |
yes (type-required) |
| 10 |
buttons |
9 |
yes (template-required) |
| 11 |
cards |
18 |
yes (template-required) |
| 12 |
headings |
15 |
yes (template-required) |
| 13 |
navigation |
24 |
yes (template-required) |
| 14 |
backgrounds |
9 |
yes (template-required) |
| 15 |
code |
14 |
yes (template-required) |
| 16 |
inputs |
13 |
yes (template-required) |
| 17 |
cursor |
15 |
yes (template-required) |
| 18 |
scrollbar |
13 |
yes (template-required) |
| 19 |
alignment |
13 |
yes (template-required) |
| 20 |
sections |
25 |
yes (template-required) |
| 21 |
dividers |
15 |
yes (template-required) |
| 22 |
gridVisuals |
10 |
yes (template-required) |
| 23 |
focus |
5 |
yes (template-required) |
| 24 |
overlays |
8 |
yes (template-required) |
| 25 |
dataViz |
13 |
yes (template-required) |
| 26 |
media |
6 |
yes (template-required) |
| 27 |
controls |
11 |
yes (template-required) |
| 28 |
componentSurfaces |
12 |
yes (template-required) |
| 29 |
hero |
25 |
yes (template-required) |
| 30 |
cta |
15 |
yes (template-required) |
| 31 |
footer |
15 |
yes (template-required) |
| 32 |
banner |
12 |
yes (template-required) |
| 33 |
pageRhythm |
14 |
yes (template-required) |
When to Use
- User asks to create a custom preset
- User asks to modify an existing preset in
packages/presets/
- User says "create a preset", "new theme", "custom preset"
- User wants to adjust colors, typography, or spacing for a preset
- User asks which preset to use for a specific aesthetic
How to Use
1. Start from the template
Always start from packages/presets/src/_template.ts. Read it first:
cat packages/presets/src/_template.ts
Then copy and customize:
import type { SigilPreset } from "@sigil-ui/tokens";
export const myPreset: SigilPreset = {
name: "my-preset",
metadata: {
description: "Short description of this preset's aesthetic",
author: "author-name",
version: "0.1.0",
tags: ["category", "mood"],
mood: "the vibe in 2-3 words",
},
tokens: {
// ALL 33 categories from _template.ts — change values, never delete fields
colors: { /* all 35 fields */ },
typography: { /* all 31 fields */ },
spacing: { /* all 25 fields */ },
layout: { /* all 22 fields */ },
sigil: { /* all 10 fields */ },
radius: { /* all 16 fields */ },
shadows: { /* all 14 fields */ },
motion: { /* all 18 fields */ },
borders: { /* all 11 fields */ },
buttons: { /* all 9 fields */ },
cards: { /* all 18 fields */ },
headings: { /* all 15 fields */ },
navigation: { /* all 24 fields */ },
backgrounds: { /* all 9 fields */ },
code: { /* all 14 fields */ },
inputs: { /* all 13 fields */ },
cursor: { /* all 15 fields */ },
scrollbar: { /* all 13 fields */ },
alignment: { /* all 13 fields */ },
sections: { /* all 25 fields */ },
dividers: { /* all 15 fields */ },
gridVisuals: { /* all 10 fields */ },
focus: { /* all 5 fields */ },
overlays: { /* all 8 fields */ },
dataViz: { /* all 13 fields */ },
media: { /* all 6 fields */ },
controls: { /* all 11 fields */ },
componentSurfaces: { /* all 12 fields */ },
hero: { /* all 25 fields */ },
cta: { /* all 15 fields */ },
footer: { /* all 15 fields */ },
banner: { /* all 12 fields */ },
pageRhythm: { /* all 14 fields */ },
},
};
2. Built-in presets
| Preset |
Aesthetic |
Display Font |
Body Font |
Mono Font |
Primary Hue |
Radius |
sigil |
Structural-visibility |
Nacelle |
system-ui |
Roboto Mono |
280 (indigo) |
6–12px |
midnight |
Dark premium SaaS |
GT America |
system-ui |
JetBrains Mono |
250 (blue) |
4–12px |
editorial |
Paper-like docs |
Söhne |
Charter |
IBM Plex Mono |
260 (cobalt) |
3–8px |
brutalist |
Neo-brutalist |
Space Grotesk |
Space Grotesk |
Space Mono |
105 (yellow) |
0px |
soft |
Warm consumer-friendly |
Satoshi |
Inter |
Fira Code |
310 (pink) |
8–20px |
3. Creating a new preset (in-repo)
- Copy
packages/presets/src/_template.ts → packages/presets/src/<name>.ts.
- Rename the export and
name field.
- Change token values — never delete fields.
- Add to barrel:
packages/presets/src/index.ts.
- Add entry to
packages/presets/tsup.config.ts.
- Add export map entry to
packages/presets/package.json.
- Register in
packages/cli/src/commands/init.ts and packages/cli/src/commands/preset.ts.
4. User-created presets (via CLI)
Users can run sigil preset create to scaffold a sigil.preset.<name>.ts file in
their project root. The CLI generates from the template with all 33 categories.
Rules
- All 33 token categories required — a preset must define every field from
_template.ts. No partial presets. No missing categories. This is the most important rule.
- All colors in OKLCH — use
oklch(L C H) format exclusively. No hex, rgb, or hsl.
- Themed colors —
background, surface, surface-elevated, all text-*, and all border-* tokens must provide both light and dark values.
- Unthemed colors —
primary, secondary, success, warning, error, info are single values shared across themes.
- Font stacks — always include system fallbacks (e.g.,
"Satoshi", system-ui, sans-serif).
- Spacing scale — must be a 10-element array of ascending numbers, unit is always
"px".
- Radius consistency — values should form a smooth progression (sm < md < lg < xl < 2xl). Exception: brutalist may use 0px for all.
- Shadow layering — use multi-layer shadows for md/lg/xl to create realistic depth. sm can be a single layer.
- Motion coherence — faster presets (brutalist) should have shorter durations, softer presets should be slower.
- Metadata required —
description, author, and version must be set.
Validation Checklist
Before considering a custom preset complete, verify:
Examples
Deriving a preset from the template
Copy the template, then change the values that define your aesthetic:
import { _templatePreset } from "./_template.js";
import type { SigilPreset } from "@sigil-ui/tokens";
export const warmPreset: SigilPreset = {
name: "warm",
tokens: {
..._templatePreset.tokens,
colors: {
..._templatePreset.tokens.colors,
primary: "oklch(0.65 0.16 35)",
"primary-hover": "oklch(0.60 0.19 35)",
secondary: "oklch(0.70 0.14 150)",
},
typography: {
..._templatePreset.tokens.typography,
"font-display": '"Fraunces", Georgia, serif',
"font-body": '"Source Serif 4", Georgia, serif',
"font-mono": '"Fira Code", ui-monospace, monospace',
},
// All other categories inherited from _templatePreset.tokens
},
metadata: {
description: "Warm variant — terracotta primary, serif typography",
author: "you",
version: "0.1.0",
},
};
Choosing OKLCH values
Use this mental model:
- L (lightness): 0 = black, 1 = white. Primary colors: 0.50–0.70. Backgrounds: 0.95–0.99 (light), 0.05–0.12 (dark).
- C (chroma): 0 = gray, 0.20+ = vivid. Body text: 0. Accent colors: 0.12–0.20.
- H (hue): 0 = red, 60 = yellow, 150 = green, 250 = blue, 310 = pink.
1---2name: sigil-preset3description: Sigil Preset4---56# Sigil Preset78> Create and modify complete token presets that define the visual identity of a Sigil-powered project.910## The #1 Rule: Full Token Coverage1112**Every custom preset MUST populate ALL 33 token categories and ALL fields.**1314The canonical template is `packages/presets/src/_template.ts`. It contains every15field from `SigilTokens` with sensible defaults. When creating a custom preset:16171. **Start from the template** — copy `_template.ts`, rename, change values.182. **Never delete fields** — change values, don't remove keys.193. **No partial presets** — if a field exists in `_template.ts`, it must exist in your preset.2021The 33 required categories (all must be present):2223| # | Category | Fields | Required |24|---|----------|--------|----------|25| 1 | `colors` | 36 | yes (type-required) |26| 2 | `typography` | 31 | yes (type-required) |27| 3 | `spacing` | 25 | yes (type-required) |28| 4 | `layout` | 22 | **yes (template-required)** |29| 5 | `sigil` | 10 | yes (type-required) |30| 6 | `radius` | 16 | yes (type-required) |31| 7 | `shadows` | 14 | yes (type-required) |32| 8 | `motion` | 19 | yes (type-required) |33| 9 | `borders` | 11 | yes (type-required) |34| 10 | `buttons` | 9 | **yes (template-required)** |35| 11 | `cards` | 18 | **yes (template-required)** |36| 12 | `headings` | 15 | **yes (template-required)** |37| 13 | `navigation` | 24 | **yes (template-required)** |38| 14 | `backgrounds` | 9 | **yes (template-required)** |39| 15 | `code` | 14 | **yes (template-required)** |40| 16 | `inputs` | 13 | **yes (template-required)** |41| 17 | `cursor` | 15 | **yes (template-required)** |42| 18 | `scrollbar` | 13 | **yes (template-required)** |43| 19 | `alignment` | 13 | **yes (template-required)** |44| 20 | `sections` | 25 | **yes (template-required)** |45| 21 | `dividers` | 15 | **yes (template-required)** |46| 22 | `gridVisuals` | 10 | **yes (template-required)** |47| 23 | `focus` | 5 | **yes (template-required)** |48| 24 | `overlays` | 8 | **yes (template-required)** |49| 25 | `dataViz` | 13 | **yes (template-required)** |50| 26 | `media` | 6 | **yes (template-required)** |51| 27 | `controls` | 11 | **yes (template-required)** |52| 28 | `componentSurfaces` | 12 | **yes (template-required)** |53| 29 | `hero` | 25 | **yes (template-required)** |54| 30 | `cta` | 15 | **yes (template-required)** |55| 31 | `footer` | 15 | **yes (template-required)** |56| 32 | `banner` | 12 | **yes (template-required)** |57| 33 | `pageRhythm` | 14 | **yes (template-required)** |5859## When to Use6061- User asks to create a custom preset62- User asks to modify an existing preset in `packages/presets/`63- User says "create a preset", "new theme", "custom preset"64- User wants to adjust colors, typography, or spacing for a preset65- User asks which preset to use for a specific aesthetic6667## How to Use6869### 1. Start from the template7071**Always** start from `packages/presets/src/_template.ts`. Read it first:7273```bash74cat packages/presets/src/_template.ts75```7677Then copy and customize:7879```ts80import type { SigilPreset } from "@sigil-ui/tokens";8182export const myPreset: SigilPreset = {83 name: "my-preset",84 metadata: {85 description: "Short description of this preset's aesthetic",86 author: "author-name",87 version: "0.1.0",88 tags: ["category", "mood"],89 mood: "the vibe in 2-3 words",90 },91 tokens: {92 // ALL 33 categories from _template.ts — change values, never delete fields93 colors: { /* all 35 fields */ },94 typography: { /* all 31 fields */ },95 spacing: { /* all 25 fields */ },96 layout: { /* all 22 fields */ },97 sigil: { /* all 10 fields */ },98 radius: { /* all 16 fields */ },99 shadows: { /* all 14 fields */ },100 motion: { /* all 18 fields */ },101 borders: { /* all 11 fields */ },102 buttons: { /* all 9 fields */ },103 cards: { /* all 18 fields */ },104 headings: { /* all 15 fields */ },105 navigation: { /* all 24 fields */ },106 backgrounds: { /* all 9 fields */ },107 code: { /* all 14 fields */ },108 inputs: { /* all 13 fields */ },109 cursor: { /* all 15 fields */ },110 scrollbar: { /* all 13 fields */ },111 alignment: { /* all 13 fields */ },112 sections: { /* all 25 fields */ },113 dividers: { /* all 15 fields */ },114 gridVisuals: { /* all 10 fields */ },115 focus: { /* all 5 fields */ },116 overlays: { /* all 8 fields */ },117 dataViz: { /* all 13 fields */ },118 media: { /* all 6 fields */ },119 controls: { /* all 11 fields */ },120 componentSurfaces: { /* all 12 fields */ },121 hero: { /* all 25 fields */ },122 cta: { /* all 15 fields */ },123 footer: { /* all 15 fields */ },124 banner: { /* all 12 fields */ },125 pageRhythm: { /* all 14 fields */ },126 },127};128```129130### 2. Built-in presets131132| Preset | Aesthetic | Display Font | Body Font | Mono Font | Primary Hue | Radius |133|-------------|--------------------------|-----------------|--------------|-----------------|-------------|---------|134| `sigil` | Structural-visibility | Nacelle | system-ui | Roboto Mono | 280 (indigo)| 6–12px |135| `midnight` | Dark premium SaaS | GT America | system-ui | JetBrains Mono | 250 (blue) | 4–12px |136| `editorial` | Paper-like docs | Söhne | Charter | IBM Plex Mono | 260 (cobalt)| 3–8px |137| `brutalist` | Neo-brutalist | Space Grotesk | Space Grotesk| Space Mono | 105 (yellow)| 0px |138| `soft` | Warm consumer-friendly | Satoshi | Inter | Fira Code | 310 (pink) | 8–20px |139140### 3. Creating a new preset (in-repo)1411421. Copy `packages/presets/src/_template.ts` → `packages/presets/src/<name>.ts`.1432. Rename the export and `name` field.1443. Change token values — **never delete fields**.1454. Add to barrel: `packages/presets/src/index.ts`.1465. Add entry to `packages/presets/tsup.config.ts`.1476. Add export map entry to `packages/presets/package.json`.1487. Register in `packages/cli/src/commands/init.ts` and `packages/cli/src/commands/preset.ts`.149150### 4. User-created presets (via CLI)151152Users can run `sigil preset create` to scaffold a `sigil.preset.<name>.ts` file in153their project root. The CLI generates from the template with all 33 categories.154155## Rules1561571. **All 33 token categories required** — a preset must define every field from `_template.ts`. No partial presets. No missing categories. This is the most important rule.1582. **All colors in OKLCH** — use `oklch(L C H)` format exclusively. No hex, rgb, or hsl.1593. **Themed colors** — `background`, `surface`, `surface-elevated`, all `text-*`, and all `border-*` tokens must provide both `light` and `dark` values.1604. **Unthemed colors** — `primary`, `secondary`, `success`, `warning`, `error`, `info` are single values shared across themes.1615. **Font stacks** — always include system fallbacks (e.g., `"Satoshi", system-ui, sans-serif`).1626. **Spacing scale** — must be a 10-element array of ascending numbers, unit is always `"px"`.1637. **Radius consistency** — values should form a smooth progression (sm < md < lg < xl < 2xl). Exception: brutalist may use 0px for all.1648. **Shadow layering** — use multi-layer shadows for md/lg/xl to create realistic depth. sm can be a single layer.1659. **Motion coherence** — faster presets (brutalist) should have shorter durations, softer presets should be slower.16610. **Metadata required** — `description`, `author`, and `version` must be set.167168## Validation Checklist169170Before considering a custom preset complete, verify:171172- [ ] All 33 token categories present173- [ ] No fields from `_template.ts` are missing174- [ ] All authored colors use OKLCH175- [ ] Themed colors have both `light` and `dark`176- [ ] Spacing scale has exactly 10 ascending values177- [ ] Radius values form a smooth progression178- [ ] Font stacks include system fallbacks179- [ ] Metadata has description, author, version180181## Examples182183### Deriving a preset from the template184185Copy the template, then change the values that define your aesthetic:186187```ts188import { _templatePreset } from "./_template.js";189import type { SigilPreset } from "@sigil-ui/tokens";190191export const warmPreset: SigilPreset = {192 name: "warm",193 tokens: {194 ..._templatePreset.tokens,195 colors: {196 ..._templatePreset.tokens.colors,197 primary: "oklch(0.65 0.16 35)",198 "primary-hover": "oklch(0.60 0.19 35)",199 secondary: "oklch(0.70 0.14 150)",200 },201 typography: {202 ..._templatePreset.tokens.typography,203 "font-display": '"Fraunces", Georgia, serif',204 "font-body": '"Source Serif 4", Georgia, serif',205 "font-mono": '"Fira Code", ui-monospace, monospace',206 },207 // All other categories inherited from _templatePreset.tokens208 },209 metadata: {210 description: "Warm variant — terracotta primary, serif typography",211 author: "you",212 version: "0.1.0",213 },214};215```216217### Choosing OKLCH values218219Use this mental model:220- **L** (lightness): 0 = black, 1 = white. Primary colors: 0.50–0.70. Backgrounds: 0.95–0.99 (light), 0.05–0.12 (dark).221- **C** (chroma): 0 = gray, 0.20+ = vivid. Body text: 0. Accent colors: 0.12–0.20.222- **H** (hue): 0 = red, 60 = yellow, 150 = green, 250 = blue, 310 = pink.