brandspec 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,389 @@
1
+ # Tokens Specification
2
+
3
+ Machine-readable specification for the `tokens` section of brand.yaml.
4
+
5
+ Follows the [W3C Design Tokens Community Group (DTCG)](https://tr.designtokens.org/format/) format.
6
+
7
+ ## Token Format
8
+
9
+ Every token uses DTCG properties:
10
+
11
+ ```yaml
12
+ token-name:
13
+ $value: "..." # Required. The token value.
14
+ $type: color # Recommended. Token type.
15
+ $description: "..." # Optional. Human-readable description.
16
+ $extensions: # Optional. Extra metadata.
17
+ dark: "..." # Dark mode override value.
18
+ compat: # Legacy format alternatives.
19
+ hex: "..."
20
+ hsl: "..."
21
+ ```
22
+
23
+ ### Supported Types
24
+
25
+ | `$type` | Value format | Example |
26
+ |---------|-------------|---------|
27
+ | `color` | oklch string | `"oklch(0.65 0.18 250)"` |
28
+ | `dimension` | CSS length | `"1rem"`, `"16px"` |
29
+ | `fontFamily` | CSS font stack | `"Inter, system-ui, sans-serif"` |
30
+ | `fontWeight` | CSS weight | `"400"`, `"bold"` |
31
+ | `duration` | CSS duration | `"200ms"` |
32
+ | `cubicBezier` | Array of 4 numbers | `[0.4, 0, 0.2, 1]` |
33
+
34
+ ## Token Categories
35
+
36
+ ```yaml
37
+ tokens:
38
+ colors: # Color tokens (see §Colors below)
39
+ typography: # Font tokens (see §Typography below)
40
+ spacing: # Spacing tokens (see §Spacing below)
41
+ radius: # Border radius tokens (see §Radius below)
42
+ ```
43
+
44
+ ---
45
+
46
+ ## Colors
47
+
48
+ ### Color Format
49
+
50
+ All color values MUST use **oklch** as the canonical format.
51
+
52
+ ```yaml
53
+ $value: "oklch(L C H)"
54
+ # L = lightness (0–1)
55
+ # C = chroma (0–0.4, typical brand colors 0.10–0.20)
56
+ # H = hue angle (0–360)
57
+ ```
58
+
59
+ Why oklch:
60
+ - Perceptually uniform (equal steps look equal)
61
+ - Wide gamut (P3, Rec.2020)
62
+ - Native CSS support
63
+ - Predictable palette generation (rotate H, adjust L/C)
64
+
65
+ ### Variant Naming Convention
66
+
67
+ Every color token uses a flat naming pattern with suffixes:
68
+
69
+ | Suffix | Purpose | When to define |
70
+ |--------|---------|----------------|
71
+ | *(none)* | Base color (used as background) | Always |
72
+ | `-foreground` | Text/icon color on that background | Always |
73
+ | `-muted` | Subtle/toned-down background variant | Optional |
74
+
75
+ CSS output maps directly:
76
+ ```
77
+ primary → --primary
78
+ primary-foreground → --primary-foreground
79
+ primary-muted → --primary-muted
80
+ ```
81
+
82
+ Contrast requirement: base + `-foreground` pair MUST meet WCAG AA (4.5:1 normal text, 3:1 large text).
83
+
84
+ ### Required Color Tokens
85
+
86
+ > "Required" means needed for a complete brandspec, not schema-enforced. `brandspec lint` reports missing required tokens as warnings.
87
+
88
+ These tokens MUST be defined for a complete brandspec:
89
+
90
+ ```yaml
91
+ tokens:
92
+ colors:
93
+ # Brand colors
94
+ primary:
95
+ $value: "oklch(L C H)"
96
+ $type: color
97
+ primary-foreground:
98
+ $value: "oklch(L C H)"
99
+ $type: color
100
+ secondary:
101
+ $value: "oklch(L C H)"
102
+ $type: color
103
+ secondary-foreground:
104
+ $value: "oklch(L C H)"
105
+ $type: color
106
+
107
+ # Surface colors
108
+ background:
109
+ $value: "oklch(L C H)"
110
+ $type: color
111
+ foreground:
112
+ $value: "oklch(L C H)"
113
+ $type: color
114
+ muted:
115
+ $value: "oklch(L C H)"
116
+ $type: color
117
+ muted-foreground:
118
+ $value: "oklch(L C H)"
119
+ $type: color
120
+
121
+ # Status colors
122
+ destructive:
123
+ $value: "oklch(L C H)"
124
+ $type: color
125
+ destructive-foreground:
126
+ $value: "oklch(L C H)"
127
+ $type: color
128
+ ```
129
+
130
+ ### Recommended Color Tokens
131
+
132
+ These tokens SHOULD be defined for UI completeness:
133
+
134
+ ```yaml
135
+ # Semantic status colors
136
+ success:
137
+ $value: "oklch(L C H)" # Green family (H ≈ 145)
138
+ $type: color
139
+ success-foreground:
140
+ $value: "oklch(L C H)"
141
+ $type: color
142
+ success-muted:
143
+ $value: "oklch(L C H)"
144
+ $type: color
145
+ warning:
146
+ $value: "oklch(L C H)" # Amber family (H ≈ 85)
147
+ $type: color
148
+ warning-foreground:
149
+ $value: "oklch(L C H)"
150
+ $type: color
151
+ warning-muted:
152
+ $value: "oklch(L C H)"
153
+ $type: color
154
+ info:
155
+ $value: "oklch(L C H)" # Blue family (H ≈ 230)
156
+ $type: color
157
+ info-foreground:
158
+ $value: "oklch(L C H)"
159
+ $type: color
160
+ info-muted:
161
+ $value: "oklch(L C H)"
162
+ $type: color
163
+
164
+ # Brand color muted variants
165
+ primary-muted:
166
+ $value: "oklch(L C H)"
167
+ $type: color
168
+ secondary-muted:
169
+ $value: "oklch(L C H)"
170
+ $type: color
171
+ ```
172
+
173
+ ### Complete Color Token List
174
+
175
+ ```
176
+ Required:
177
+ background, foreground
178
+ primary, primary-foreground
179
+ secondary, secondary-foreground
180
+ muted, muted-foreground
181
+ destructive, destructive-foreground
182
+
183
+ Recommended:
184
+ primary-muted, secondary-muted
185
+ success, success-foreground, success-muted
186
+ warning, warning-foreground, warning-muted
187
+ info, info-foreground, info-muted
188
+ ```
189
+
190
+ ### Dark Mode
191
+
192
+ Define dark mode values using `$extensions.dark` on each token:
193
+
194
+ ```yaml
195
+ background:
196
+ $value: "oklch(0.99 0.005 250)" # Light mode
197
+ $type: color
198
+ $extensions:
199
+ dark: "oklch(0.15 0.02 250)" # Dark mode
200
+ ```
201
+
202
+ Rules:
203
+ - `$value` is the light mode (default) value
204
+ - `$extensions.dark` is the dark override
205
+ - Dark variants are optional; ask the user explicitly
206
+ - When defined, export produces both `:root` and `.dark` blocks
207
+
208
+ ### Legacy Compatibility
209
+
210
+ When interoperability with tools that don't support oklch is needed, provide `$extensions.compat`:
211
+
212
+ ```yaml
213
+ primary:
214
+ $value: "oklch(0.65 0.18 250)"
215
+ $type: color
216
+ $extensions:
217
+ compat:
218
+ hsl: "hsl(220 70% 50%)"
219
+ hex: "#3b82f6"
220
+ ```
221
+
222
+ Rules:
223
+ - `$value` (oklch) is always the source of truth
224
+ - `compat` values are informational; conversions are approximate (oklch covers wider gamut than sRGB)
225
+ - CSS export uses `$value` directly (browsers support oklch natively)
226
+
227
+ ### Palette Generation Guidelines
228
+
229
+ When generating a harmonious palette from a primary color:
230
+
231
+ | Token | Derivation from primary |
232
+ |-------|------------------------|
233
+ | `primary-foreground` | L ≈ 0.98, C ≈ 0.01, same H |
234
+ | `primary-muted` | L ≈ 0.90, C ≈ 0.04, same H |
235
+ | `secondary` | Different H, similar L/C |
236
+ | `background` | L ≈ 0.99, C ≈ 0.005, primary H |
237
+ | `foreground` | L ≈ 0.15, C ≈ 0.02, primary H |
238
+ | `muted` | L ≈ 0.95, C ≈ 0.01, primary H |
239
+ | `muted-foreground` | L ≈ 0.45, C ≈ 0.02, primary H |
240
+ | `destructive` | L ≈ 0.55, C ≈ 0.20, H ≈ 25 (red) |
241
+ | `success` | L ≈ 0.65, C ≈ 0.18, H ≈ 145 (green) |
242
+ | `warning` | L ≈ 0.75, C ≈ 0.15, H ≈ 85 (amber) |
243
+ | `info` | L ≈ 0.65, C ≈ 0.12, H ≈ 230 (blue) |
244
+
245
+ ---
246
+
247
+ ## Typography
248
+
249
+ ### Required Typography Tokens
250
+
251
+ ```yaml
252
+ tokens:
253
+ typography:
254
+ heading:
255
+ $value: "Inter, system-ui, sans-serif"
256
+ $type: fontFamily
257
+ body:
258
+ $value: "Inter, system-ui, sans-serif"
259
+ $type: fontFamily
260
+ ```
261
+
262
+ ### Optional Typography Tokens
263
+
264
+ ```yaml
265
+ mono:
266
+ $value: "JetBrains Mono, monospace"
267
+ $type: fontFamily
268
+ ```
269
+
270
+ ### Font Pairing Strategies
271
+
272
+ | Strategy | Heading | Body | Effect |
273
+ |----------|---------|------|--------|
274
+ | Same family | Inter | Inter | Simple, consistent |
275
+ | Contrast | Space Grotesk | Inter | Distinctive headlines |
276
+ | Editorial | Fraunces (serif) | Inter (sans) | Editorial, premium |
277
+
278
+ ---
279
+
280
+ ## Spacing
281
+
282
+ ### Recommended Spacing Scale
283
+
284
+ ```yaml
285
+ tokens:
286
+ spacing:
287
+ xs:
288
+ $value: "0.25rem"
289
+ $type: dimension
290
+ sm:
291
+ $value: "0.5rem"
292
+ $type: dimension
293
+ md:
294
+ $value: "1rem"
295
+ $type: dimension
296
+ lg:
297
+ $value: "1.5rem"
298
+ $type: dimension
299
+ xl:
300
+ $value: "2rem"
301
+ $type: dimension
302
+ ```
303
+
304
+ Compatible with shadcn/ui + Tailwind v4 defaults.
305
+
306
+ ---
307
+
308
+ ## Radius
309
+
310
+ ### Recommended Radius Scale
311
+
312
+ ```yaml
313
+ tokens:
314
+ radius:
315
+ sm:
316
+ $value: "0.25rem"
317
+ $type: dimension
318
+ md:
319
+ $value: "0.5rem"
320
+ $type: dimension
321
+ lg:
322
+ $value: "1rem"
323
+ $type: dimension
324
+ ```
325
+
326
+ ---
327
+
328
+ ## Export Mapping
329
+
330
+ ### CSS Custom Properties
331
+
332
+ | brandspec path | CSS output |
333
+ |----------------|------------|
334
+ | `tokens.colors.{name}.$value` | `--{name}: {value};` |
335
+ | `tokens.typography.{name}.$value` | `--font-{name}: {value};` |
336
+ | `tokens.spacing.{name}.$value` | `--spacing-{name}: {value};` |
337
+ | `tokens.radius.{name}.$value` | `--radius-{name}: {value};` |
338
+
339
+ Dark mode: `$extensions.dark` values emit under `.dark {}` selector.
340
+
341
+ ### Tailwind Config
342
+
343
+ Tailwind config references CSS variables (not hardcoded values):
344
+
345
+ ```ts
346
+ colors: {
347
+ primary: "var(--primary)",
348
+ "primary-foreground": "var(--primary-foreground)",
349
+ }
350
+ ```
351
+
352
+ ### Figma Variables
353
+
354
+ - oklch values are converted to sRGB hex for Figma import
355
+ - If `$extensions.compat.hex` exists, use it directly
356
+ - Dark mode creates a "Dark" mode within the Figma variable collection
357
+
358
+ ---
359
+
360
+ ## shadcn/ui Compatibility
361
+
362
+ brandspec tokens map directly to shadcn/ui CSS variables:
363
+
364
+ ```
365
+ --primary → bg-primary
366
+ --primary-foreground → text-primary-foreground
367
+ --muted → bg-muted
368
+ --destructive → bg-destructive
369
+ ```
370
+
371
+ Usage: `<button class="bg-primary text-primary-foreground">Click</button>`
372
+
373
+ ## Brand Extensions
374
+
375
+ For brand-specific color scales (50–900) or custom tokens beyond the standard set, use the top-level `extensions` section:
376
+
377
+ ```yaml
378
+ extensions:
379
+ brand-scale:
380
+ primary-50:
381
+ $value: "oklch(0.97 0.02 250)"
382
+ $type: color
383
+ # ... through primary-900
384
+ ```
385
+
386
+ Rules:
387
+ - Use `extensions` for non-standard tokens
388
+ - Follow the same DTCG format
389
+ - Preserved by schema (`additionalProperties: true`)
@@ -0,0 +1,201 @@
1
+ # brandspec Schema v0.1.0
2
+ # This document defines the structure of a brand.yaml file.
3
+
4
+ $schema: "https://json-schema.org/draft/2020-12/schema"
5
+ $id: "https://brandspec.tools/schema/v0.1.0"
6
+ title: "brandspec"
7
+ description: "Brand Identity specification format"
8
+ type: object
9
+
10
+ required:
11
+ - meta
12
+
13
+ properties:
14
+ meta:
15
+ type: object
16
+ description: "Brand metadata"
17
+ required:
18
+ - name
19
+ properties:
20
+ name:
21
+ type: string
22
+ description: "Brand name"
23
+ version:
24
+ type: string
25
+ description: "Brand spec version (semver)"
26
+ updated:
27
+ type: string
28
+ format: date
29
+ description: "Last updated date"
30
+ description:
31
+ type: string
32
+ description: "Brief brand description"
33
+ url:
34
+ type: string
35
+ format: uri
36
+ description: "Brand website"
37
+ additionalProperties: true
38
+
39
+ core:
40
+ type: object
41
+ description: "Brand essence, personality, and voice"
42
+ properties:
43
+ essence:
44
+ type: string
45
+ description: "One sentence capturing the brand's core"
46
+ tagline:
47
+ type: string
48
+ description: "Public-facing tagline"
49
+ mission:
50
+ type: string
51
+ description: "Brand mission statement"
52
+ vision:
53
+ type: string
54
+ description: "Brand vision statement"
55
+ values:
56
+ type: array
57
+ items:
58
+ type: string
59
+ description: "Core brand values"
60
+ personality:
61
+ type: array
62
+ items:
63
+ type: string
64
+ description: "Brand personality traits"
65
+ voice:
66
+ type: object
67
+ description: "Voice and tone guidelines"
68
+ properties:
69
+ tone:
70
+ type: array
71
+ items:
72
+ type: string
73
+ principles:
74
+ type: array
75
+ items:
76
+ type: string
77
+ additionalProperties: true
78
+ additionalProperties: true
79
+
80
+ tokens:
81
+ type: object
82
+ description: "Design tokens (W3C DTCG compliant)"
83
+ additionalProperties: true
84
+ # Follows W3C Design Tokens Community Group specification
85
+ # https://tr.designtokens.org/format/
86
+ #
87
+ # Example:
88
+ # colors:
89
+ # primary:
90
+ # $value: "oklch(0.7 0.15 250)"
91
+ # $type: color
92
+ # $description: "Primary brand color"
93
+
94
+ assets:
95
+ type: array
96
+ description: "Brand assets (logos, icons, images, etc.)"
97
+ items:
98
+ type: object
99
+ required:
100
+ - file
101
+ properties:
102
+ file:
103
+ type: string
104
+ description: "File path (required)"
105
+ id:
106
+ type: string
107
+ description: "Semantic identifier (recommended)"
108
+ role:
109
+ type: string
110
+ description: "Asset role"
111
+ # Recommended values:
112
+ # logo, wordmark, symbol, icon, favicon,
113
+ # graphic, pattern, photo, illustration,
114
+ # video, audio, document, font
115
+ variant:
116
+ type: string
117
+ description: "Asset variant"
118
+ # Recommended values:
119
+ # primary, secondary, monochrome, inverse,
120
+ # simplified, vertical, horizontal
121
+ context:
122
+ type: string
123
+ description: "Usage context"
124
+ # Recommended values:
125
+ # light-bg, dark-bg, any, print, digital, social
126
+ description:
127
+ type: string
128
+ description: "Human-readable description"
129
+ formats:
130
+ type: array
131
+ description: "Derived formats"
132
+ items:
133
+ type: object
134
+ properties:
135
+ path:
136
+ type: string
137
+ width:
138
+ type: integer
139
+ height:
140
+ type: integer
141
+ additionalProperties: true
142
+ tags:
143
+ type: array
144
+ items:
145
+ type: string
146
+ description: "Free-form tags"
147
+ additionalProperties: true
148
+
149
+ guidelines:
150
+ type: object
151
+ description: "Usage guidelines — each key is a guideline section (e.g. logo-usage, color-usage)"
152
+ additionalProperties:
153
+ type: object
154
+ properties:
155
+ content:
156
+ type: string
157
+ description: "Free-form Markdown content (human-readable guidelines)"
158
+ rules:
159
+ type: array
160
+ description: "Structured, machine-readable rules for AI-driven brand linting"
161
+ items:
162
+ $ref: "#/$defs/guidelineRule"
163
+ additionalProperties: true
164
+
165
+ extensions:
166
+ type: object
167
+ description: "Custom extensions (fully open)"
168
+ additionalProperties: true
169
+
170
+ additionalProperties: true
171
+
172
+ $defs:
173
+ guidelineRule:
174
+ type: object
175
+ description: "A single checkable brand guideline rule"
176
+ required:
177
+ - description
178
+ - severity
179
+ properties:
180
+ id:
181
+ type: string
182
+ description: "Unique rule identifier (e.g. logo-min-size, color-contrast)"
183
+ description:
184
+ type: string
185
+ description: "Human-readable explanation of what this rule enforces"
186
+ severity:
187
+ type: string
188
+ enum:
189
+ - info
190
+ - warning
191
+ - error
192
+ description: "Severity level — info (advisory), warning (should fix), error (must fix)"
193
+ criteria:
194
+ type: array
195
+ items:
196
+ type: string
197
+ description: "List of specific, checkable conditions that satisfy this rule"
198
+ applies_to:
199
+ type: string
200
+ description: "What this rule targets (e.g. logo, color, typography, voice)"
201
+ additionalProperties: true