get-shit-pretty 0.7.3 → 0.8.2

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.
Files changed (78) hide show
  1. package/bin/theme-css.js +331 -0
  2. package/gsp/agents/gsp-brand-coherence.md +7 -0
  3. package/gsp/hooks/hooks.json +1 -1
  4. package/gsp/skills/gsp-brand-brief/SKILL.md +50 -5
  5. package/gsp/skills/gsp-brand-guidelines/SKILL.md +51 -31
  6. package/gsp/skills/gsp-brand-guidelines/design-tokens.md +2 -0
  7. package/gsp/skills/gsp-brand-guidelines/guidelines-structure.md +167 -0
  8. package/gsp/skills/gsp-brand-guidelines/methodology/gsp-brand-coherence.md +86 -0
  9. package/gsp/skills/gsp-brand-guidelines/methodology/gsp-brand-engineer.md +13 -5
  10. package/gsp/skills/gsp-brand-guidelines/token-mapping.md +16 -319
  11. package/gsp/skills/gsp-brand-identity/SKILL.md +1 -1
  12. package/gsp/skills/gsp-brand-refine/SKILL.md +5 -6
  13. package/gsp/skills/gsp-brand-research/SKILL.md +1 -1
  14. package/gsp/skills/gsp-brand-strategy/SKILL.md +1 -1
  15. package/gsp/skills/gsp-design-system/SKILL.md +1 -1
  16. package/gsp/skills/gsp-doctor/SKILL.md +51 -3
  17. package/gsp/skills/gsp-progress/SKILL.md +1 -1
  18. package/gsp/skills/gsp-project-brief/SKILL.md +40 -6
  19. package/gsp/skills/gsp-project-build/SKILL.md +27 -31
  20. package/gsp/skills/gsp-project-build/flows/figma.md +50 -0
  21. package/gsp/skills/gsp-project-build/flows/revision.md +64 -0
  22. package/gsp/skills/gsp-project-build/methodology/gsp-project-builder.md +84 -1
  23. package/gsp/skills/gsp-project-build/shadcn-composition.md +217 -0
  24. package/gsp/skills/gsp-project-critique/SKILL.md +3 -1
  25. package/gsp/skills/gsp-project-design/SKILL.md +3 -2
  26. package/gsp/skills/gsp-project-design/methodology/gsp-project-designer.md +28 -21
  27. package/gsp/skills/gsp-project-research/SKILL.md +3 -1
  28. package/gsp/skills/gsp-project-review/SKILL.md +10 -1
  29. package/gsp/skills/gsp-scaffold/SKILL.md +67 -11
  30. package/gsp/skills/gsp-scaffold/shadcn-rules.md +433 -0
  31. package/gsp/skills/gsp-scaffold/shadcn-theming.md +310 -0
  32. package/gsp/skills/gsp-start/SKILL.md +18 -2
  33. package/gsp/skills/gsp-style/SKILL.md +1 -1
  34. package/gsp/skills/gsp-style/style-preset-schema.md +59 -14
  35. package/gsp/skills/gsp-style/styles/academia.yml +58 -8
  36. package/gsp/skills/gsp-style/styles/art-deco.yml +39 -7
  37. package/gsp/skills/gsp-style/styles/bauhaus.yml +39 -8
  38. package/gsp/skills/gsp-style/styles/bold-typography.yml +39 -8
  39. package/gsp/skills/gsp-style/styles/botanical.yml +39 -9
  40. package/gsp/skills/gsp-style/styles/claymorphism.yml +39 -9
  41. package/gsp/skills/gsp-style/styles/cyberpunk.yml +39 -7
  42. package/gsp/skills/gsp-style/styles/enterprise.yml +39 -10
  43. package/gsp/skills/gsp-style/styles/flat-design.yml +39 -9
  44. package/gsp/skills/gsp-style/styles/fluent.yml +39 -10
  45. package/gsp/skills/gsp-style/styles/glassmorphism.yml +39 -8
  46. package/gsp/skills/gsp-style/styles/humanist-literary.yml +39 -9
  47. package/gsp/skills/gsp-style/styles/industrial.yml +59 -9
  48. package/gsp/skills/gsp-style/styles/kinetic.yml +32 -7
  49. package/gsp/skills/gsp-style/styles/liquid-glass.yml +59 -9
  50. package/gsp/skills/gsp-style/styles/luxury.yml +59 -9
  51. package/gsp/skills/gsp-style/styles/material.yml +59 -9
  52. package/gsp/skills/gsp-style/styles/maximalism.yml +32 -6
  53. package/gsp/skills/gsp-style/styles/minimal-dark.yml +32 -7
  54. package/gsp/skills/gsp-style/styles/modern-dark.yml +32 -7
  55. package/gsp/skills/gsp-style/styles/monochrome.yml +59 -10
  56. package/gsp/skills/gsp-style/styles/neubrutalism.yml +59 -9
  57. package/gsp/skills/gsp-style/styles/neumorphism.yml +32 -7
  58. package/gsp/skills/gsp-style/styles/newsprint.yml +32 -7
  59. package/gsp/skills/gsp-style/styles/nothing.yml +44 -13
  60. package/gsp/skills/gsp-style/styles/organic.yml +42 -9
  61. package/gsp/skills/gsp-style/styles/playful-geometric.yml +43 -9
  62. package/gsp/skills/gsp-style/styles/professional.yml +41 -10
  63. package/gsp/skills/gsp-style/styles/retro.yml +42 -8
  64. package/gsp/skills/gsp-style/styles/saas.yml +42 -9
  65. package/gsp/skills/gsp-style/styles/sketch.yml +42 -9
  66. package/gsp/skills/gsp-style/styles/swiss-minimalist.yml +41 -10
  67. package/gsp/skills/gsp-style/styles/terminal.yml +42 -8
  68. package/gsp/skills/gsp-style/styles/vaporwave.yml +42 -7
  69. package/gsp/skills/gsp-style/styles/web3.yml +42 -9
  70. package/gsp/templates/branding/brief.md +9 -0
  71. package/gsp/templates/branding/config.json +1 -1
  72. package/gsp/templates/design-claude.md +6 -0
  73. package/gsp/templates/phases/design.md +0 -8
  74. package/gsp/templates/phases/patterns.md +2 -2
  75. package/gsp/templates/projects/config.json +6 -3
  76. package/gsp/templates/projects/state.md +1 -1
  77. package/gsp/templates/system/STACK.md +1 -0
  78. package/package.json +1 -1
@@ -0,0 +1,331 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * theme-css.js — GSP deterministic token-to-CSS generator
4
+ *
5
+ * Reads a GSP style preset `.yml` file and outputs a shadcn/ui-compatible
6
+ * CSS variables block for `:root` and `.dark`.
7
+ *
8
+ * Usage:
9
+ * node bin/theme-css.js <path-to-preset.yml>
10
+ * node bin/theme-css.js <path-to-preset.yml> --output globals.css
11
+ * node bin/theme-css.js <path-to-preset.yml> --stdout
12
+ *
13
+ * Token → CSS var mapping is 1:1. No derivation, no LLM guesswork.
14
+ * Hex values are converted to OKLCH. Alpha values (oklch with /) pass through.
15
+ * Sidebar vars are output verbatim. Extras (success/warning/info) become custom props.
16
+ */
17
+
18
+ 'use strict';
19
+
20
+ const fs = require('fs');
21
+ const path = require('path');
22
+
23
+ // ---------------------------------------------------------------------------
24
+ // YAML parser (zero-dependency, handles the subset GSP uses)
25
+ // ---------------------------------------------------------------------------
26
+
27
+ function parseYaml(text) {
28
+ const lines = text.split('\n');
29
+ const root = {};
30
+ const stack = [{ indent: -1, obj: root }];
31
+
32
+ for (let i = 0; i < lines.length; i++) {
33
+ const raw = lines[i];
34
+ const trimmed = raw.trimEnd();
35
+ if (!trimmed || trimmed.trimStart().startsWith('#')) continue;
36
+
37
+ const indent = raw.length - raw.trimStart().length;
38
+ const content = trimmed.trimStart();
39
+
40
+ // Handle inline arrays: key: [a, b, c]
41
+ const colonIdx = content.indexOf(':');
42
+ if (colonIdx === -1) continue;
43
+
44
+ const key = content.slice(0, colonIdx).trim();
45
+ const rest = content.slice(colonIdx + 1).trim();
46
+
47
+ // Pop stack to correct parent
48
+ while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
49
+ stack.pop();
50
+ }
51
+ const parent = stack[stack.length - 1].obj;
52
+
53
+ if (rest === '' || rest.startsWith('#')) {
54
+ // Nested object
55
+ parent[key] = {};
56
+ stack.push({ indent, obj: parent[key] });
57
+ } else if (rest.startsWith('[')) {
58
+ // Inline array — parse as string, not needed for color extraction
59
+ parent[key] = rest;
60
+ } else {
61
+ // Scalar — strip inline comments and quotes
62
+ let val = rest.split(' #')[0].trim();
63
+ if ((val.startsWith('"') && val.endsWith('"')) ||
64
+ (val.startsWith("'") && val.endsWith("'"))) {
65
+ val = val.slice(1, -1);
66
+ }
67
+ // Numbers
68
+ if (/^-?\d+(\.\d+)?$/.test(val)) {
69
+ parent[key] = parseFloat(val);
70
+ } else if (val === 'true') {
71
+ parent[key] = true;
72
+ } else if (val === 'false') {
73
+ parent[key] = false;
74
+ } else {
75
+ parent[key] = val;
76
+ }
77
+ }
78
+ }
79
+
80
+ return root;
81
+ }
82
+
83
+ // ---------------------------------------------------------------------------
84
+ // Color conversion: hex → OKLCH
85
+ // ---------------------------------------------------------------------------
86
+
87
+ function hexToRgb(hex) {
88
+ const h = hex.replace('#', '');
89
+ const len = h.length;
90
+ if (len === 3) {
91
+ return [
92
+ parseInt(h[0] + h[0], 16),
93
+ parseInt(h[1] + h[1], 16),
94
+ parseInt(h[2] + h[2], 16),
95
+ ];
96
+ }
97
+ return [
98
+ parseInt(h.slice(0, 2), 16),
99
+ parseInt(h.slice(2, 4), 16),
100
+ parseInt(h.slice(4, 6), 16),
101
+ ];
102
+ }
103
+
104
+ // sRGB → linear
105
+ function toLinear(c) {
106
+ c = c / 255;
107
+ return c <= 0.04045 ? c / 12.92 : Math.pow((c + 0.055) / 1.055, 2.4);
108
+ }
109
+
110
+ // Linear RGB → XYZ (D65)
111
+ function linearToXyz(r, g, b) {
112
+ return [
113
+ r * 0.4124564 + g * 0.3575761 + b * 0.1804375,
114
+ r * 0.2126729 + g * 0.7151522 + b * 0.0721750,
115
+ r * 0.0193339 + g * 0.1191920 + b * 0.9503041,
116
+ ];
117
+ }
118
+
119
+ // XYZ → OKLab
120
+ function xyzToOklab(x, y, z) {
121
+ const l_ = Math.cbrt(0.8189330101 * x + 0.3618667424 * y - 0.1288597137 * z);
122
+ const m_ = Math.cbrt(0.0329845436 * x + 0.9293118715 * y + 0.0361456387 * z);
123
+ const s_ = Math.cbrt(0.0482003018 * x + 0.2643662691 * y + 0.6338517070 * z);
124
+ return [
125
+ 0.2104542553 * l_ + 0.7936177850 * m_ - 0.0040720468 * s_,
126
+ 1.9779984951 * l_ - 2.4285922050 * m_ + 0.4505937099 * s_,
127
+ 0.0259040371 * l_ + 0.7827717662 * m_ - 0.8086757660 * s_,
128
+ ];
129
+ }
130
+
131
+ // OKLab → OKLCH
132
+ function oklabToOklch(L, a, b) {
133
+ const C = Math.sqrt(a * a + b * b);
134
+ let H = Math.atan2(b, a) * (180 / Math.PI);
135
+ if (H < 0) H += 360;
136
+ return [L, C, H];
137
+ }
138
+
139
+ function hexToOklch(hex) {
140
+ const [r, g, b] = hexToRgb(hex);
141
+ const lr = toLinear(r);
142
+ const lg = toLinear(g);
143
+ const lb = toLinear(b);
144
+ const [x, y, z] = linearToXyz(lr, lg, lb);
145
+ const [L, a, bk] = xyzToOklab(x, y, z);
146
+ const [Lch, C, H] = oklabToOklch(L, a, bk);
147
+ // Format: oklch(L% C H)
148
+ const Lpct = (Lch * 100).toFixed(2);
149
+ const Cfmt = C.toFixed(4);
150
+ const Hfmt = H.toFixed(2);
151
+ return `oklch(${Lpct}% ${Cfmt} ${Hfmt})`;
152
+ }
153
+
154
+ // ---------------------------------------------------------------------------
155
+ // Value formatter: hex → oklch, alpha values pass through
156
+ // ---------------------------------------------------------------------------
157
+
158
+ function formatValue(val) {
159
+ if (typeof val !== 'string') return String(val);
160
+ const v = val.trim();
161
+
162
+ // Already oklch (alpha or not) — pass through
163
+ if (v.startsWith('oklch(')) return v;
164
+
165
+ // Hex color
166
+ if (/^#[0-9a-fA-F]{3,6}$/.test(v)) {
167
+ return hexToOklch(v);
168
+ }
169
+
170
+ // Everything else (rgba, named colors, etc.) — pass through
171
+ return v;
172
+ }
173
+
174
+ // ---------------------------------------------------------------------------
175
+ // CSS var name mapping (1:1 to shadcn/ui)
176
+ // ---------------------------------------------------------------------------
177
+
178
+ // Core color tokens → CSS var names
179
+ const CORE_VARS = [
180
+ 'background', 'foreground',
181
+ 'card', 'card-foreground',
182
+ 'popover', 'popover-foreground',
183
+ 'primary', 'primary-foreground',
184
+ 'secondary', 'secondary-foreground',
185
+ 'accent', 'accent-foreground',
186
+ 'muted', 'muted-foreground',
187
+ 'destructive',
188
+ 'border', 'input', 'ring',
189
+ ];
190
+
191
+ // NOTE: 'sidebar' (not 'sidebar-background') matches shadcn's CSS var --sidebar
192
+ const SIDEBAR_VARS = [
193
+ 'sidebar', 'sidebar-foreground',
194
+ 'sidebar-primary', 'sidebar-primary-foreground',
195
+ 'sidebar-accent', 'sidebar-accent-foreground',
196
+ 'sidebar-border', 'sidebar-ring',
197
+ ];
198
+
199
+ const EXTRA_VARS = ['success', 'warning', 'info'];
200
+
201
+ // Shape tokens → CSS vars
202
+ const SHAPE_VARS = {
203
+ 'border-radius-lg': '--radius',
204
+ };
205
+
206
+ // ---------------------------------------------------------------------------
207
+ // CSS block generator
208
+ // ---------------------------------------------------------------------------
209
+
210
+ function generateBlock(colorObj, shapeObj, typographyObj, selector) {
211
+ if (!colorObj) return '';
212
+ const lines = [];
213
+
214
+ // Core vars
215
+ for (const key of CORE_VARS) {
216
+ if (colorObj[key] !== undefined) {
217
+ lines.push(` --${key}: ${formatValue(colorObj[key])};`);
218
+ }
219
+ }
220
+
221
+ // Sidebar vars
222
+ for (const key of SIDEBAR_VARS) {
223
+ if (colorObj[key] !== undefined) {
224
+ lines.push(` --${key}: ${formatValue(colorObj[key])};`);
225
+ }
226
+ }
227
+
228
+ // Chart vars — emit in both :root and .dark (dark falls back to light values if not set)
229
+ {
230
+ // For :root use light palette; for .dark use dark overrides falling back to light
231
+ const chartColors = [
232
+ colorObj['chart-1'] || colorObj.primary,
233
+ colorObj['chart-2'] || colorObj.secondary,
234
+ colorObj['chart-3'] || colorObj.accent,
235
+ colorObj['chart-4'] || colorObj.info || colorObj.primary,
236
+ colorObj['chart-5'] || colorObj.success || colorObj.secondary || colorObj.primary,
237
+ ];
238
+ chartColors.forEach((c, i) => {
239
+ if (c) lines.push(` --chart-${i + 1}: ${formatValue(c)};`);
240
+ });
241
+ }
242
+
243
+ // Shape → radius (only in :root)
244
+ if (selector === ':root' && shapeObj) {
245
+ const lg = shapeObj['border-radius-lg'];
246
+ if (lg !== undefined) {
247
+ lines.push(` --radius: ${lg};`);
248
+ }
249
+ }
250
+
251
+ // Typography → font CSS vars (only in :root)
252
+ if (selector === ':root' && typographyObj) {
253
+ const fontMappings = [
254
+ ['font-family-primary', '--font-sans'],
255
+ ['font-family-mono', '--font-mono'],
256
+ ['font-family-display', '--font-display'],
257
+ ['font-family-secondary', '--font-secondary'],
258
+ ];
259
+ for (const [ymlKey, cssVar] of fontMappings) {
260
+ if (typographyObj[ymlKey] !== undefined) {
261
+ lines.push(` ${cssVar}: ${typographyObj[ymlKey]};`);
262
+ }
263
+ }
264
+ }
265
+
266
+ // Extras as custom properties
267
+ for (const key of EXTRA_VARS) {
268
+ if (colorObj[key] !== undefined) {
269
+ lines.push(` --${key}: ${formatValue(colorObj[key])};`);
270
+ }
271
+ }
272
+
273
+ if (!lines.length) return '';
274
+ return `${selector} {\n${lines.join('\n')}\n}`;
275
+ }
276
+
277
+ // ---------------------------------------------------------------------------
278
+ // Main
279
+ // ---------------------------------------------------------------------------
280
+
281
+ function main() {
282
+ const args = process.argv.slice(2);
283
+ if (!args.length || args.includes('--help') || args.includes('-h')) {
284
+ console.log(`Usage: node bin/theme-css.js <preset.yml> [--output <file>] [--stdout]`);
285
+ console.log(` node bin/theme-css.js gsp/skills/gsp-style/styles/saas.yml`);
286
+ process.exit(0);
287
+ }
288
+
289
+ const inputPath = path.resolve(args[0]);
290
+ if (!fs.existsSync(inputPath)) {
291
+ console.error(`Error: File not found: ${inputPath}`);
292
+ process.exit(1);
293
+ }
294
+
295
+ const outputIdx = args.indexOf('--output');
296
+ const outputPath = outputIdx !== -1 ? path.resolve(args[outputIdx + 1]) : null;
297
+ const toStdout = args.includes('--stdout') || !outputPath;
298
+
299
+ const raw = fs.readFileSync(inputPath, 'utf8');
300
+ const preset = parseYaml(raw);
301
+
302
+ const colorLight = (preset.tokens && preset.tokens.color) || {};
303
+ const colorDark = (preset.dark_mode && preset.dark_mode.color) || {};
304
+ const shape = (preset.tokens && preset.tokens.shape) || {};
305
+ const typography = (preset.tokens && preset.tokens.typography) || null;
306
+
307
+ const rootBlock = generateBlock(colorLight, shape, typography, ':root');
308
+ const darkBlock = generateBlock(colorDark, null, null, '.dark');
309
+
310
+ const presetName = preset.name || path.basename(inputPath, '.yml');
311
+ const presetDesc = preset.description || '';
312
+
313
+ const header = [
314
+ `/* GSP theme: ${presetName} */`,
315
+ presetDesc ? `/* ${presetDesc} */` : null,
316
+ `/* Generated by bin/theme-css.js from ${path.basename(inputPath)} */`,
317
+ `/* Edit the .yml file, not this output */`,
318
+ '',
319
+ ].filter(Boolean).join('\n');
320
+
321
+ const output = [header, rootBlock, darkBlock ? '' : null, darkBlock].filter(s => s !== null).join('\n');
322
+
323
+ if (toStdout) {
324
+ process.stdout.write(output + '\n');
325
+ } else {
326
+ fs.writeFileSync(outputPath, output + '\n', 'utf8');
327
+ console.log(`Written to ${outputPath}`);
328
+ }
329
+ }
330
+
331
+ main();
@@ -0,0 +1,7 @@
1
+ ---
2
+ name: gsp-brand-coherence
3
+ description: Brand coherence auditor — scores intensity dials against archetype and surfaces tensions between declared values and expressed output
4
+ tools:
5
+ - Read
6
+ ---
7
+ Coherence auditor for gsp-brand-guidelines. Spawned by the skill after Pass 1 to evaluate the generated artifacts before user review.
@@ -17,7 +17,7 @@
17
17
  "hooks": [
18
18
  {
19
19
  "type": "prompt",
20
- "prompt": "The gsp-project-designer agent just finished. Verify: (1) at least one design/screen-*.md chunk was written, (2) design/INDEX.md was written, (3) design/preview.html was written. Report any missing deliverables to the user."
20
+ "prompt": "The gsp-project-designer agent just finished. Verify: (1) at least one design/screen-*.md chunk was written, (2) design/INDEX.md was written. Report any missing deliverables to the user."
21
21
  }
22
22
  ]
23
23
  },
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gsp-brand-brief
3
- description: Define your brand — who, why, and what it should feel like
3
+ description: Define your brand — who, why, and what it should feel like — use when: create a brand, define our brand identity, who are we, what's our brand
4
4
  user-invocable: true
5
5
  allowed-tools:
6
6
  - Read
@@ -86,23 +86,35 @@ Before presenting personality options, **internally synthesize** promise (what s
86
86
  - Note: this is a high-level direction only. Brand strategy phase will deepen this into archetype + voice — don't over-refine here.
87
87
  8. What should the brand NEVER feel like? (use `AskUserQuestion` with 2-3 anti-directions inferred from their personality pick, plus open-ended option)
88
88
  9. Brands admired or styles to avoid? (open-ended `AskUserQuestion`)
89
+ 10. Visual direction — raw aesthetic feeling. Use `AskUserQuestion` (open-ended):
90
+ > "What should it look and feel like visually? You can share image or website links, describe a mood ('editorial and dark', 'warm brutalist', 'cinematographic with beautiful stills'), drop adjective clusters ('rounded, clean, airy'), or even describe a scene or texture. The weirder and more specific the better — this is what prevents a bland brand."
91
+ - Synthesize the answer into a `visual_direction` block in the brief: mood words, reference aesthetics, texture/atmosphere descriptors, any specific anti-patterns (e.g., "never stock-photo corporate"). This block directly informs color, typography, and imagery choices downstream.
89
92
 
90
93
  ## Step 4: Constraints & confirmation
91
94
 
92
- 10. Any non-negotiables or constraints? (timeline, budget, must-haves) — open-ended `AskUserQuestion`
93
- 11. State your understanding back: "Here's what I'm hearing: [summary]." Use `AskUserQuestion`:
95
+ 11. Any non-negotiables or constraints? (timeline, budget, must-haves) — open-ended `AskUserQuestion`
96
+ 12. State your understanding back but lead with *feeling*, not facts. Format:
97
+
98
+ > "Here's what I'm hearing: [2-sentence factual summary].
99
+ > The feeling this brand should leave: **[emotional compass — one evocative sentence capturing the brand's energy, not its category]**."
100
+
101
+ The emotional compass is the hardest line to write and the most important. It should make the user feel something when they read it. Not "a fintech tool that simplifies investing" but "the brand that makes financial confidence feel earned, not given." Synthesize it from the personality direction, the persona aspiration, the brand POV, and the visual direction. It should be specific enough to be wrong — vague sentences aren't compasses.
102
+
103
+ Use `AskUserQuestion`:
94
104
  - **Looks good** — "That's accurate, let's go"
95
- - **Adjust something** — "I want to change or add something"
105
+ - **Adjust the feeling** — "The compass is off let me reframe it"
106
+ - **Adjust something else** — "Facts are right but I want to change something"
96
107
 
97
108
  If "Adjust" — ask what to change, update your understanding, re-confirm. Don't re-ask everything.
98
109
 
99
- ## Step 5: Write artifacts
110
+ ## Step 5: Write artifacts and register brand
100
111
 
101
112
  Read templates at write time from `${CLAUDE_SKILL_DIR}/../../templates/branding/` and write:
102
113
 
103
114
  1. `.design/branding/{name}/BRIEF.md` from `brief.md` template
104
115
  - Populate all sections from conversation answers
105
116
  - Synthesize brand promise, POV, and personality (these are inferred, not asked directly)
117
+ - Write the confirmed emotional compass as `brand_heartbeat` in the Emotional Compass section
106
118
  - Set `brand_mode` to `new`
107
119
  - Set evolve-only sections (Existing Brand State, Evolution Scope) to "N/A — new brand"
108
120
 
@@ -117,6 +129,14 @@ Read templates at write time from `${CLAUDE_SKILL_DIR}/../../templates/branding/
117
129
 
118
130
  4. `.design/branding/{name}/ROADMAP.md` from `roadmap.md` template
119
131
 
132
+ 5. Write/update `.design/CLAUDE.md` — register the brand as started. If the file doesn't exist, read `${CLAUDE_SKILL_DIR}/../../templates/design-claude.md` first. Append under `## Brands`:
133
+
134
+ ```markdown
135
+ ### {brand-name} · in progress · {DATE}
136
+ "{brand_heartbeat}"
137
+ next: gsp-brand-research · .design/branding/{brand-name}/
138
+ ```
139
+
120
140
  ## Step 6: Route
121
141
 
122
142
  Use `AskUserQuestion` — always offer Continue / Stop here / What happens next:
@@ -126,4 +146,29 @@ Use `AskUserQuestion` — always offer Continue / Stop here / What happens next:
126
146
  - **What happens next?** — "Explain the research phase" → explain what brand-research does (market landscape, competitive audit, trend analysis, mood board direction) and how it uses the brief
127
147
 
128
148
  If `e2e: true`, mention that after the full branding diamond completes, it will auto-transition to project setup.
149
+
150
+ ## Step 7: e2e transition (only when `e2e: true` and branding diamond is complete)
151
+
152
+ After all four brand phases complete (brand-research → brand-strategy → brand-identity → brand-guidelines), scaffold the project directory before invoking `/gsp-project-brief`:
153
+
154
+ 1. Derive `{project-slug}` from the brand name: lowercase, spaces and underscores replaced with hyphens.
155
+
156
+ 2. Create the project directory:
157
+ ```bash
158
+ mkdir -p .design/projects/{project-slug}/
159
+ ```
160
+
161
+ 3. Read templates at write time from `${CLAUDE_SKILL_DIR}/../../templates/projects/` and write:
162
+ - `.design/projects/{project-slug}/config.json` from `config.json` template — set `project.name` (title-cased from project-slug) and `project.created` (ISO date)
163
+ - `.design/projects/{project-slug}/STATE.md` from `state.md` template — fill in project name and brand name
164
+
165
+ 4. Write `.design/projects/{project-slug}/brand.ref` containing the brand directory name (e.g. `{brand-name}`), so the project knows which brand it belongs to.
166
+
167
+ 5. Display:
168
+ ```
169
+ brand complete — {brand-name}
170
+ now let's scope your project.
171
+ ```
172
+
173
+ 6. Invoke `/gsp-project-brief` via Skill tool, passing `{project-slug}` so Step 0 resolves the existing directory rather than prompting for one.
129
174
  </process>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gsp-brand-guidelines
3
- description: Operationalize your brand assemble tokens, STYLE.md, component mapping, and guidelines (technical phase — benefits from capable models)
3
+ description: Build design system tokens and STYLE.md (technical phase — benefits from capable models) — use when: create the design system, generate tokens, finalize brand guidelines, build the component system
4
4
  user-invocable: true
5
5
  allowed-tools:
6
6
  - Read
@@ -113,6 +113,7 @@ Redesign the system from the ground up, informed by what exists.
113
113
  Read these files and hold their content for inlining into the agent prompt:
114
114
  - `${CLAUDE_SKILL_DIR}/../../templates/phases/patterns.md` — patterns output template
115
115
  - `${CLAUDE_SKILL_DIR}/design-tokens.md` — design tokens reference
116
+ - `${CLAUDE_SKILL_DIR}/guidelines-structure.md` — guidelines.html structure spec (shadcn tokens, sections, primitive classes)
116
117
  - `${CLAUDE_SKILL_DIR}/methodology/gsp-brand-engineer.md` — agent methodology
117
118
 
118
119
  Spawn the `gsp-brand-engineer` agent. **Inline all content** — the agent should not need to read input files.
@@ -120,11 +121,12 @@ Spawn the `gsp-brand-engineer` agent. **Inline all content** — the agent shoul
120
121
  Pass in the agent prompt:
121
122
  - **Content of** all identity chunks + palettes.json (loaded in Step 1)
122
123
  - **Content of** strategy chunks: voice-and-tone.md, archetype.md, positioning.md (loaded in Step 1)
123
- - **Content of** BRIEF.md (loaded in Step 1)
124
+ - **Content of** BRIEF.md (loaded in Step 1) — explicitly pass the `brand_heartbeat` field as a named input so the agent uses it in the hero headline if no manifesto line exists yet
124
125
  - **Content of** style base preset `.yml` + `.md` (loaded in Step 1) — `.yml` as structural scaffold, `.md` as philosophy + implementation content for STYLE.md
125
126
  - **Agent methodology** (loaded above)
126
127
  - **Content of** patterns output template (loaded above)
127
128
  - **Content of** design tokens reference (loaded above)
129
+ - **Content of** guidelines structure spec (loaded above) — follow this exactly for `guidelines.html`
128
130
  - The `system_strategy` and `tech_stack` values
129
131
  - **Output path:** `{BRAND_PATH}/patterns/`
130
132
 
@@ -136,55 +138,64 @@ Pass in the agent prompt:
136
138
  >
137
139
  > Do NOT produce component artifacts yet (token-mapping, overrides, custom specs). Those come after the user reviews the visual output.
138
140
 
139
- ## Step 3.5: Visual review
141
+ ## Step 3.5: Coherence check
140
142
 
141
- Tell the user: "Open `{BRAND_PATH}/patterns/guidelines.html` in your browserthis is your brand in one page."
143
+ Spawn the `gsp-brand-coherence` agent with a fresh context. Load the methodology and inline all inputs the agent should not need to read files.
142
144
 
143
- Present a compact summary:
145
+ ### Load
146
+ Read these and hold for inlining:
147
+ - `${CLAUDE_SKILL_DIR}/methodology/gsp-brand-coherence.md` — agent methodology
148
+ - `{BRAND_PATH}/patterns/{brand-name}.yml` — generated preset
149
+ - `{BRAND_PATH}/patterns/guidelines.html` — generated visual guide
144
150
 
145
- ```
146
- {brand-name} guidelines
147
- ═══════════════════════════════════════
151
+ Extract from Step 1 context:
152
+ - `archetype` — from archetype.md
153
+ - `brand_heartbeat` — from BRIEF.md
154
+
155
+ ### Spawn `gsp-brand-coherence`
148
156
 
149
- .yml preset
150
- colors: {primary}, {secondary}, {accent}
151
- typography: {primary font}, {secondary font}
152
- intensity: variance {N}/10, motion {N}/10, density {N}/10
157
+ Pass inline:
158
+ - **Agent methodology** (loaded above)
159
+ - **Content of** `{brand-name}.yml`
160
+ - **Content of** `guidelines.html`
161
+ - `archetype` and `brand_heartbeat`
153
162
 
154
- STYLE.md
155
- patterns: {N} components defined
156
- constraints: {N} never, {N} always rules
157
- effects: {interaction vocabulary list}
158
- bold bets: {1-line summary of boldest bet}
163
+ The agent returns a structured coherence report. No back-and-forth — one response.
159
164
 
160
- open guidelines.html in your browser to preview
165
+ ### Present the report
161
166
 
167
+ Display the agent's report, then add:
168
+
169
+ ```
170
+ → open guidelines.html in your browser
162
171
  ─────────────────────────────────────
163
172
  ```
164
173
 
165
174
  Use `AskUserQuestion`:
166
- - **Looks good** — "The brand looks right, build components"
167
- - **Adjust tokens** — "I want to tweak colors, typography, or spacing"
168
- - **Adjust patterns** — "I want to change component rules or constraints"
169
- - **Adjust intensity** — "More/less creative, more/less motion, more/less density"
175
+ - **Looks right** — "Coherent build components"
176
+ - **Push [tension 1]** — pre-fill with the specific gap from the report
177
+ - **Push [tension 2]** — same
178
+ - **Adjust something else** — "I want to change colors / type / patterns"
170
179
 
171
- If adjustments needed, use `/gsp-brand-refine` with the feedback to surgically update the `.yml`, regenerate `STYLE.md`, and regenerate `guidelines.html`. Then re-present.
180
+ If refinement needed invoke `/gsp-brand-refine` with the specific tension. After it completes, re-spawn `gsp-brand-coherence` with the updated `.yml` and `guidelines.html`. Only proceed to Step 3.75 when the archetype tension is present and dials are coherent.
172
181
 
173
182
  ## Step 3.75: Perspective check
174
183
 
175
- Load persona profiles from `{BRAND_PATH}/BRIEF.md` and present stakeholder reactions:
184
+ Load persona profiles and the `brand_heartbeat` from `{BRAND_PATH}/BRIEF.md`. Present stakeholder reactions framed around the compass:
176
185
 
177
- "Stress-testing the brand visuals:
186
+ ```
187
+ stress-testing against: "{brand_heartbeat}"
178
188
 
179
- {primary persona name}: {would this visual language feel trustworthy and appropriate?}
180
- Skeptic: {are the constraints too restrictive or too loose? Is the intensity calibrated right?}
181
- {top competitor}: {is the brand visually differentiated?}"
189
+ {primary persona name}: {does this visual language make them feel that sentence?}
190
+ Skeptic: {does the intensity feel calibrated or is it playing it safe?}
191
+ {top competitor}: {is the brand visually distinct enough to own this feeling?}
192
+ ```
182
193
 
183
194
  Use `AskUserQuestion`:
184
- - **Lock it in** — "The brand is solid, build components"
185
- - **Adjust** — "One of these concerns resonates — I want to change something"
195
+ - **Lock it in** — "The brand earns that feeling — build components"
196
+ - **Adjust** — "One of these concerns resonates"
186
197
 
187
- If adjust → use `/gsp-brand-refine` with the concern, then re-present. If confirmed → proceed to components.
198
+ If adjust → invoke `/gsp-brand-refine` with the concern, re-present. If confirmed → proceed to components.
188
199
 
189
200
  ## Step 4: Spawn brand engineer — Pass 2: Components
190
201
 
@@ -212,6 +223,14 @@ Update `{BRAND_PATH}/STATE.md`:
212
223
  - Record completion date
213
224
  - Set Prettiness Level to 100%
214
225
 
226
+ Update `.design/CLAUDE.md` — replace the existing `### {brand-name}` entry (written by gsp-brand-brief when started) with the completed entry:
227
+
228
+ ```markdown
229
+ ### {brand-name} · complete · {DATE}
230
+ "{brand_heartbeat}"
231
+ .design/branding/{brand-name}/patterns/ — guidelines.html · STYLE.md · {brand-name}.yml
232
+ ```
233
+
215
234
  ## Step 5: Phase transition output
216
235
 
217
236
  Invoke `/gsp-phase-transition` with phase `guidelines` and output directory `{BRAND_PATH}/patterns/`.
@@ -224,6 +243,7 @@ Also display a brand summary after the standard transition — this is the final
224
243
 
225
244
  ```
226
245
  brand complete — {brand-name}
246
+ "{brand_heartbeat}"
227
247
 
228
248
  discover {key finding}
229
249
  strategy {archetype}, {positioning}, {top voice attributes}
@@ -1,5 +1,7 @@
1
1
  # Design Token Standards
2
2
 
3
+ > **GSP approach (v0.8.0+):** GSP presets use **shadcn/ui-native token names** directly — keys in `.yml` files map 1:1 to shadcn CSS variables (`background`, `foreground`, `primary`, `accent`, etc.). The W3C format below is background context on token standards in general; it does not reflect GSP's flat, shadcn-native schema. See `bin/theme-css.js` for how GSP converts `.yml` tokens to CSS.
4
+
3
5
  **Format:** W3C Design Tokens Community Group specification
4
6
 
5
7
  ---