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,167 @@
1
+ # guidelines.html — Structure Spec
2
+
3
+ The `guidelines.html` is the visual conference of the entire brand pipeline — every phase of the branding diamond distilled into one self-rendering document:
4
+
5
+ - **Discover** → personas
6
+ - **Strategy** → positioning, voice
7
+ - **Identity** → color, typography, visual elements, logo
8
+ - **Patterns** → components, tokens
9
+
10
+ It uses the brand's own tokens, type, and primitives to render itself. One file, no build step, open in a browser. When someone opens this file, they should understand the brand completely — who it's for, what it stands for, and how it looks and speaks.
11
+
12
+ **Every element in this document must be derived from the brand pipeline outputs.** There are no defaults, no fallbacks, no generic treatments. If the brand is dark and editorial, the doc is dark and editorial. If the brand is warm and rounded, the doc is warm and rounded. The guidelines file is not a template being filled in — it is a brand artifact being built from the ground up using everything the pipeline produced.
13
+
14
+ ## `:root` — shadcn-native token names
15
+
16
+ Use these exact CSS variable names so the file maps 1:1 with the shadcn token system. All values come from the brand's `.yml` tokens — use OKLCH values from palettes.json where available.
17
+
18
+ ```css
19
+ :root {
20
+ /* shadcn core */
21
+ --background: ...; /* page background */
22
+ --foreground: ...; /* primary text */
23
+ --primary: ...; /* brand primary color */
24
+ --primary-foreground: ...; /* text on primary */
25
+ --secondary: ...; /* secondary surface */
26
+ --secondary-foreground: ...;
27
+ --muted: ...; /* muted surface */
28
+ --muted-foreground: ...; /* secondary text */
29
+ --accent: ...; /* accent color (the memorable one) */
30
+ --accent-foreground: ...;
31
+ --destructive: ...; /* error state */
32
+ --border: ...; /* border color */
33
+ --ring: ...; /* focus ring */
34
+ --radius: ...; /* base radius */
35
+
36
+ /* Brand-specific extensions */
37
+ --font-display: ...; /* heading/editorial font */
38
+ --font-body: ...; /* body/UI font */
39
+ --font-mono: ...; /* data/code font */
40
+ --ease: ...; /* brand easing curve */
41
+ }
42
+ ```
43
+
44
+ ## Primitive classes
45
+
46
+ Define only the primitives the brand actually uses. Their implementation is derived from the brand's identity — intensity.variance, visual_direction, effects vocabulary. Don't define a class that doesn't serve this brand.
47
+
48
+ ```css
49
+ /* examples — implement only what fits the brand */
50
+ .frosted-glass /* glass surface — opacity/blur derived from brand intensity */
51
+ .frosted-glass-strong /* heavier glass — for hero overlays */
52
+ .grain /* noise texture — only if brand uses texture */
53
+ .glow /* ambient radial glow — only if brand uses glow */
54
+ .atmosphere /* full-bleed animated gradient — derived from brand palette */
55
+ ```
56
+
57
+ ## Layout primitives
58
+
59
+ ```css
60
+ .container /* max-width wrapper, responsive padding */
61
+ section /* section spacing — density derived from brand intensity */
62
+ .section-label /* eyebrow label */
63
+ .section-heading /* large section heading */
64
+ ```
65
+
66
+ ## Sections
67
+
68
+ The template defines a baseline section order. Follow it. If the brand warrants additional sections beyond this list — imagery style, motion principles, iconography, spatial system, co-branding rules, etc. — add them where they fit. Number sections sequentially. Each section gets an `id` for sidebar navigation.
69
+
70
+ ### Navigation — always
71
+ Fixed left sidebar. Table of contents linking to every section. Brand-derived styling — font, color, spacing, all from the pipeline. Hidden on mobile.
72
+
73
+ **Section ID convention:** every section in the doc must have an `id` attribute that the nav links to:
74
+
75
+ ```html
76
+ <!-- nav -->
77
+ <nav id="toc" style="position: fixed; left: 0; top: 0; height: 100vh; width: 180px; z-index: 50;
78
+ overflow-y: auto; display: flex; flex-direction: column;
79
+ justify-content: center; padding: 0 28px; gap: 8px;
80
+ border-right: 1px solid var(--border); background: var(--background);">
81
+ <a href="#hero" class="toc-link">Brand</a>
82
+ <a href="#logo" class="toc-link">Logo</a>
83
+ <a href="#positioning" class="toc-link">Positioning</a>
84
+ <a href="#color" class="toc-link">Color</a>
85
+ <a href="#typography" class="toc-link">Typography</a>
86
+ <a href="#visuals" class="toc-link">Visual Elements</a>
87
+ <a href="#components" class="toc-link">Components</a>
88
+ <a href="#personas" class="toc-link">Personas</a>
89
+ <a href="#voice" class="toc-link">Voice</a>
90
+ <!-- add entries for any brand-specific sections -->
91
+ </nav>
92
+
93
+ <!-- main content offset -->
94
+ <main style="margin-left: 180px;">
95
+
96
+ <section id="hero">...</section>
97
+ <section id="logo">...</section>
98
+ <!-- each section id matches its toc-link href -->
99
+
100
+ </main>
101
+ ```
102
+
103
+ `.toc-link` styling: use the brand's body font, `--muted-foreground` at rest, `--foreground` on hover, no underline. Active state via a 10-line scroll listener that adds `.active` (accent color) to the link whose section is in view — include this JS inline at the bottom of `<body>`. Keep it small.
104
+
105
+ ### Hero — always
106
+ Defined entirely by the brand. Visual direction, archetype, and identity outputs determine the background, typography scale, layout density, and supporting content. No default treatment.
107
+
108
+ **The headline must be the manifesto line from `positioning.md`.** If strategy phase is not complete, fall back to `brand_heartbeat` from `BRIEF.md`. Never generate a generic headline — this line was earned through the pipeline and must appear here.
109
+
110
+ The hero should feel like opening a brand book. Someone who sees it should understand the brand's energy before reading a single label.
111
+
112
+ ### Logo
113
+ Logo marks (icon, wordmark, lockup) on the brand's background. Composition rules, clear space, forbidden uses. Skip if no logo was defined in identity.
114
+
115
+ ### Positioning
116
+ Brand promise, point of view, manifesto line. Rendered as editorial content using the brand's type hierarchy and visual language.
117
+
118
+ ### Color
119
+ Swatch grid: name, hex, OKLCH per color. Grouped by role. Contrast pairs. Layout derived from the brand.
120
+
121
+ ### Typography
122
+ Show the full type scale rendered live in the actual fonts — not a table, not a screenshot. Each step is a real HTML element styled with the brand's CSS vars.
123
+
124
+ For each scale step show:
125
+ - The text rendered at its actual size
126
+ - Label: step name + font family + weight + size + line-height
127
+ - A sample sentence or phrase that fits the brand voice (not "The quick brown fox")
128
+
129
+ Render all steps in sequence from largest to smallest so the scale relationship is visible at a glance. Show each typeface family in its own block — display font, body font, mono font — with the scale steps that use it.
130
+
131
+ ```html
132
+ <!-- example step -->
133
+ <div style="margin-bottom: 48px;">
134
+ <div class="scale-step" style="font-family: var(--font-display); font-size: 4rem; line-height: 1.05; letter-spacing: -0.03em;">
135
+ We ship what others pitch.
136
+ </div>
137
+ <div class="scale-meta">Display · Instrument Serif · 400 · 64px / 1.05</div>
138
+ </div>
139
+ ```
140
+
141
+ Include pairing notes when the brand uses multiple typefaces: which font handles which role, and what the contrast between them communicates.
142
+
143
+ ### Visual Elements
144
+ The brand's signature motifs: textures, dividers, shapes, glows, atmospheric effects, SVG elements. Each shown with its composition rule — when to use it, how much, what it must never do.
145
+
146
+ ### Components
147
+ Live component previews in brand tokens: buttons, inputs, cards, badges. Include only if the brand has a meaningfully distinctive component style.
148
+
149
+ ### Personas
150
+ Each persona as a branded card: name, role, frustration, aspiration. Styled in the brand's own visual language.
151
+
152
+ ### Voice
153
+ Never / always rules as styled components. Monospace prefix (`x` never, `>` always).
154
+
155
+ ### + Brand-specific sections
156
+ Add sections as needed to fully convey the brand. Examples: Imagery, Motion, Iconography, Spatial System, Co-branding. If the pipeline produced it and it shapes how the brand is applied, it belongs here.
157
+
158
+ ## Mobile
159
+
160
+ Single `@media (max-width: 768px)` block. Hide sidebar nav. Stack grids. Reduce section padding. Scale type with `clamp()`.
161
+
162
+ ## Quality bar
163
+
164
+ - Open in browser → immediately recognizable as this brand, not a generic template
165
+ - `:root` token names match shadcn — a dev can paste directly into `globals.css`
166
+ - Every visual decision traces back to a pipeline artifact
167
+ - No placeholder content — if a section has nothing real to show, it's omitted
@@ -0,0 +1,86 @@
1
+ <role>
2
+ You are a brand coherence auditor spawned by `/gsp-brand-guidelines` after the brand-engineer produces its first-pass artifacts.
3
+
4
+ Your only job is to evaluate whether the output is coherent with the brand's archetype and intensity intentions — and return a structured report. You do not make changes. You do not ask questions. You return one report.
5
+ </role>
6
+
7
+ <inputs>
8
+ You receive inlined:
9
+ - `{brand-name}.yml` — the generated preset (intensity dials, tokens, patterns, constraints)
10
+ - `guidelines.html` — the generated visual guide (use for component-level verification)
11
+ - `archetype` — the brand's chosen archetype
12
+ - `brand_heartbeat` — the emotional compass confirmed in the brief
13
+ </inputs>
14
+
15
+ <methodology>
16
+ ## Step 1: Archetype gate
17
+
18
+ Each archetype has a signature tension it must express. Answer this question first — it is the primary check. Intensity dials are secondary.
19
+
20
+ | Archetype | Signature question |
21
+ |-----------|-------------------|
22
+ | Jester | What specific rule is being broken in the visual system? If nothing is broken, it's not Jester enough. |
23
+ | Rebel | What visual convention is explicitly rejected? |
24
+ | Creator | What is distinctively crafted that couldn't come from a default template? |
25
+ | Sage | Is the restraint active (every reduction intentional) or passive (just plain)? |
26
+ | Explorer | Where is the sense of movement, discovery, or possibility? |
27
+ | Hero | Does the visual language communicate strength and achievement? |
28
+ | Caregiver | Does it feel warm and trustworthy without being corporate? |
29
+ | Lover | Is there sensuality, richness, or beauty in the material choices? |
30
+ | Ruler | Does it command authority through precision and restraint? |
31
+ | Magician | Is there a sense of transformation or the unexpected? |
32
+ | Innocent | Is the simplicity purposeful and delightful, not just empty? |
33
+ | Everyman | Does it feel accessible and genuine, not dumbed-down? |
34
+
35
+ If the archetype's signature tension is absent from the output, that is the primary tension to flag — regardless of what the dials say.
36
+
37
+ ## Step 2: Intensity dial scoring
38
+
39
+ Read the declared dial values from `intensity:` in the `.yml`. Then infer what the token values actually express visually.
40
+
41
+ Work primarily from the `.yml` tokens — they are the source of truth:
42
+ - `variance` — expressed by: radius values, shadow complexity, unexpected color usage, spacing irregularity
43
+ - `motion` — expressed by: transition durations, animation presence in effects, interaction vocabulary richness
44
+ - `density` — expressed by: spacing scale, font size range, information layer count
45
+
46
+ Cross-check against `guidelines.html` for specific component implementations (button styles, card treatments, border-radius in practice).
47
+
48
+ Score each dial: **declared N/10 → expressed N/10**. A gap of ±2 or more is a coherence miss worth flagging.
49
+
50
+ ## Step 3: Bold bet
51
+
52
+ Identify the single most distinctive choice in the output — the thing that would be hardest to achieve with a default template. One line.
53
+
54
+ ## Step 4: Surface tensions
55
+
56
+ Rank all gaps found. Return the top 2 — specific and actionable:
57
+ - Not "could be bolder"
58
+ - Yes: "border-radius is 4px across all components — that reads as variance 3/10, declared dial is 8/10"
59
+ - Yes: "button uses standard padding and default shape — no Jester rule broken in the primary interactive element"
60
+
61
+ If no gaps ≥ 2 points and the archetype tension is present, there are no tensions to surface.
62
+ </methodology>
63
+
64
+ <output>
65
+ Return exactly this format — nothing else:
66
+
67
+ ```
68
+ {brand-name} · {archetype} · {brand_heartbeat}
69
+
70
+ intensity dials
71
+ variance declared {N}/10 → reads {N}/10 {✓ or ⚠}
72
+ motion declared {N}/10 → reads {N}/10 {✓ or ⚠}
73
+ density declared {N}/10 → reads {N}/10 {✓ or ⚠}
74
+
75
+ archetype {✓ tension present: one-line description} or {⚠ tension absent: one-line description}
76
+
77
+ tensions
78
+ 1. {specific gap — or "none" if coherent}
79
+ 2. {specific gap — or omit if only one}
80
+
81
+ bold bet
82
+ {one-line description of most distinctive choice}
83
+ ```
84
+
85
+ No preamble. No explanation. Just the report.
86
+ </output>
@@ -9,8 +9,8 @@ The identity phase produced: logo directions, color system (with OKLCH palettes)
9
9
  <inputs>
10
10
  - Identity chunks: color-system.md, typography.md, logo-directions.md, imagery-style.md (all enriched by domain skills)
11
11
  - Identity palettes.json (OKLCH scales)
12
- - BRIEF.md
13
- - Strategy chunks: voice-and-tone.md, archetype.md, positioning.md
12
+ - BRIEF.md — including `brand_heartbeat` (the emotional compass sentence confirmed in the brief phase)
13
+ - Strategy chunks: voice-and-tone.md, archetype.md, positioning.md — `manifesto_line` from positioning.md is the hero headline; fall back to `brand_heartbeat` if not present
14
14
  - system_strategy and tech_stack from config.json
15
15
  - `.design/system/STACK.md`, `COMPONENTS.md`, `TOKENS.md` (if exist)
16
16
  - style_base from config.json + preset `.yml` (if set) — the starting scaffold
@@ -42,7 +42,15 @@ The identity phase produced: logo directions, color system (with OKLCH palettes)
42
42
 
43
43
  4. **Component overrides + custom specs** — only for components that need treatment beyond tokens.
44
44
 
45
- 5. **`guidelines.html`** — self-contained visual brand guide. This is the primary artifact users see. Single HTML file with embedded CSS, no external dependencies. Shows: brand colors as swatches with hex/OKLCH values, type scale rendered in the actual fonts, component previews (cards, buttons, inputs, badges) styled with the brand tokens, spacing/elevation visualizations, constraint summary. Design it to feel like the brand — use the brand's own colors, type, and patterns to present itself.
45
+ 5. **`guidelines.html`** — the visual conference of the entire brand pipeline. Every phase distilled into one self-rendering document: personas (discover), positioning + voice (strategy), color + type + visual elements + logo (identity), components (patterns). Follow the structure spec passed in the prompt exactly. The file IS the brand — it renders itself using the brand's own tokens, type, and primitives. Key requirements:
46
+ - `:root` uses shadcn-native CSS variable names (from spec) — a dev can paste these directly into `globals.css`
47
+ - Define only the primitive classes the brand actually uses — don't add `.frosted-glass` to a brand that has no glass aesthetic
48
+ - Hero is always required; all other sections are conditional — include only what the brand actually has. Sections in order when present: Hero (metric strip) → Logo → Positioning → Color → Typography → Visual Elements → Components → Personas → Voice → Custom Components
49
+ - Hero must feel alive: use a CSS animated gradient atmosphere (or embed a video link if one was referenced in the brief), frosted glass nav, large typographic headline in brand voice, 3-4 KPIs from the brief in the metric strip
50
+ - Voice section renders brand rules as `.never-list` / `.always-list` components
51
+ - Mobile responsive via a single `@media (max-width: 768px)` block
52
+ - No external dependencies except Google Fonts `@import`
53
+ - The brand's aesthetic sets the tone: dark brand → dark doc; light brand → light doc; match intensity.variance
46
54
 
47
55
  ## Inheritance from style_base
48
56
 
@@ -66,7 +74,7 @@ Read `system_strategy` from brand config:
66
74
 
67
75
  Leverage existing UI libraries — don't rewrite from scratch.
68
76
 
69
- **Tier 1: Token mapping** (always) — `components/token-mapping.md`. Maps brand tokens to library's theming API. Copy-paste-ready. See `references/token-mapping.md` for the CSS generation spec.
77
+ **Tier 1: Token mapping** (always) — `components/token-mapping.md`. Maps brand tokens to library's theming API. Copy-paste-ready. Generate the CSS variables block by running `node bin/theme-css.js {brand-name}.yml` it outputs a ready-to-paste `:root`/`.dark` block with OKLCH values. Token names in `.yml` are 1:1 with shadcn/ui CSS var names — no translation needed.
70
78
 
71
79
  **Tier 2: Override specs** (selective) — one file per component needing treatment beyond tokens. Why it's overridden, code hints.
72
80
 
@@ -88,7 +96,7 @@ Write operational artifacts to the brand's guidelines directory (path provided b
88
96
 
89
97
  - **`{brand-name}.yml`** — Single source of truth. Full preset schema: tokens, intensity, patterns, constraints, effects, dark_mode.
90
98
  - **`STYLE.md`** — Agent-readable contract rendered from `.yml` + philosophy + bold bets. Follows `templates/phases/style.md`.
91
- - **`guidelines.html`** — Self-contained visual brand guide. Single HTML file with embedded CSS — no external deps. Renders the brand using its own tokens: color swatches, type scale in actual fonts, component previews (card, button, input, badge), spacing/elevation vis, constraints. This is what the user sees.
99
+ - **`guidelines.html`** — Self-rendering visual brand guide. Single HTML file with embedded CSS — no external deps except Google Fonts. `:root` uses shadcn-native CSS var names. Section order: Navigation (sidebar) Hero (manifesto line as headline) Logo Positioning Color Typography → Visual Elements → Components → Personas → Voice → any brand-specific additions. Define only the primitive classes the brand actually uses. This is what the user sees — make it feel like the brand.
92
100
 
93
101
  ### Components
94
102
 
@@ -1,329 +1,26 @@
1
- # Token Mapping Reference
1
+ # Token Mapping → bin/theme-css.js
2
2
 
3
- Deterministic mapping from GSP style preset `.yml` tokens to target CSS variable systems. The builder reads the `.yml` and generates the right output for the detected stack — no separate `tokens.json` or `token-mapping.md` needed.
3
+ > **Superseded in v0.8.0.** The static mapping table has been replaced by a deterministic script.
4
4
 
5
- ## Source: `.yml` Token Structure
5
+ GSP presets use shadcn/ui-native token names directly. The `.yml` token keys match shadcn CSS variable names 1:1 — no translation layer is needed.
6
6
 
7
- Every preset (and every brand `.yml`) has this structure:
7
+ ## Generating CSS from a preset
8
8
 
9
- ```yaml
10
- tokens:
11
- color:
12
- primary: "#hex" # Brand primary
13
- secondary: "#hex" # Brand secondary
14
- accent: "#hex" # Brand accent
15
- background: "#hex" # Page background
16
- surface: "#hex" # Card/panel fill
17
- on-primary: "#hex" # Text on primary
18
- on-background: "#hex" # Text on background
19
- error: "#hex"
20
- success: "#hex"
21
- warning: "#hex"
22
- info: "#hex"
23
- muted: "#hex" # Subtle text, borders (optional)
24
-
25
- typography:
26
- font-family-primary: "stack"
27
- font-family-mono: "stack"
28
- font-family-display: "stack" # optional
29
- font-family-secondary: "stack" # optional
30
- font-weight-heading: N
31
- font-weight-body: N
32
- font-size-base: "Npx"
33
- line-height-base: N
34
-
35
- shape:
36
- border-radius-sm: "Npx"
37
- border-radius-md: "Npx"
38
- border-radius-lg: "Npx"
39
- border-width: "Npx"
40
- border-color: "#hex"
41
-
42
- elevation:
43
- shadow-sm: "css-shadow"
44
- shadow-md: "css-shadow"
45
- shadow-lg: "css-shadow"
46
- shadow-xl: "css-shadow"
47
-
48
- spacing:
49
- base: N
50
- scale: [N, N, ...]
51
-
52
- motion:
53
- duration-fast: "Nms"
54
- duration-normal: "Nms"
55
- easing: "css-easing"
56
-
57
- dark_mode:
58
- color:
59
- background: "#hex"
60
- surface: "#hex"
61
- on-background: "#hex"
62
- border-color: "#hex" # optional
63
- muted: "#hex" # optional
64
- ```
65
-
66
- ---
67
-
68
- ## Target: shadcn/ui
69
-
70
- shadcn uses HSL CSS variables in `:root` and `.dark`. The mapping is deterministic — every `.yml` token has exactly one shadcn variable.
71
-
72
- ### Color mapping
73
-
74
- | `.yml` token | shadcn CSS variable | Notes |
75
- |---|---|---|
76
- | `color.background` | `--background` | Page background |
77
- | `color.on-background` | `--foreground` | Primary text |
78
- | `color.surface` | `--card` | Card background |
79
- | `color.on-background` | `--card-foreground` | Card text (same as foreground) |
80
- | `color.surface` | `--popover` | Popover bg (same as card) |
81
- | `color.on-background` | `--popover-foreground` | Popover text |
82
- | `color.primary` | `--primary` | Primary actions |
83
- | `color.on-primary` | `--primary-foreground` | Text on primary |
84
- | `color.secondary` | `--secondary` | Secondary actions |
85
- | `color.on-primary` | `--secondary-foreground` | Text on secondary (derive from contrast) |
86
- | `color.muted` | `--muted` | Muted backgrounds |
87
- | `color.muted` | `--muted-foreground` | Muted text (use muted or derive darker) |
88
- | `color.accent` | `--accent` | Accent highlights |
89
- | `color.on-primary` | `--accent-foreground` | Text on accent (derive from contrast) |
90
- | `color.error` | `--destructive` | Destructive actions |
91
- | `color.on-primary` | `--destructive-foreground` | Text on destructive |
92
- | `shape.border-color` | `--border` | Default borders |
93
- | `shape.border-color` | `--input` | Input borders |
94
- | `color.primary` | `--ring` | Focus ring |
95
- | `color.surface` | `--sidebar-background` | Sidebar bg |
96
- | `color.on-background` | `--sidebar-foreground` | Sidebar text |
97
- | `color.primary` | `--sidebar-primary` | Sidebar active |
98
- | `color.on-primary` | `--sidebar-primary-foreground` | Sidebar active text |
99
- | `color.accent` | `--sidebar-accent` | Sidebar accent |
100
- | `color.on-background` | `--sidebar-accent-foreground` | Sidebar accent text |
101
- | `shape.border-color` | `--sidebar-border` | Sidebar borders |
102
- | `color.primary` | `--sidebar-ring` | Sidebar focus ring |
103
- | | `--chart-1` through `--chart-5` | Derive from primary, secondary, accent, info, success |
104
-
105
- ### Shape mapping
106
-
107
- | `.yml` token | shadcn CSS variable |
108
- |---|---|
109
- | `shape.border-radius-lg` | `--radius` |
110
-
111
- shadcn derives `--radius` down: `calc(var(--radius) - 2px)` for md, `calc(var(--radius) - 4px)` for sm.
112
-
113
- ### Typography
114
-
115
- shadcn doesn't use CSS variables for fonts — set in `tailwind.config` `fontFamily` extend:
116
-
117
- ```js
118
- fontFamily: {
119
- sans: [/* from typography.font-family-primary */],
120
- mono: [/* from typography.font-family-mono */],
121
- }
122
- ```
123
-
124
- ### Dark mode
125
-
126
- | `.yml` dark_mode token | shadcn CSS variable (`.dark` scope) |
127
- |---|---|
128
- | `dark_mode.color.background` | `--background` |
129
- | `dark_mode.color.on-background` | `--foreground` |
130
- | `dark_mode.color.surface` | `--card`, `--popover` |
131
- | `dark_mode.color.border-color` | `--border`, `--input` |
132
- | `dark_mode.color.muted` | `--muted`, `--muted-foreground` |
133
-
134
- Tokens not listed in `dark_mode` inherit their light-mode value.
135
-
136
- ### Color format conversion
137
-
138
- shadcn expects HSL channel values (no `hsl()` wrapper): `210 40% 98%`
139
-
140
- **Conversion:** hex → HSL → extract H S% L% as space-separated string.
141
-
142
- ```
143
- #1E40AF → hsl(221, 72%, 40%) → "221 72% 40%"
9
+ ```bash
10
+ node bin/theme-css.js gsp/skills/gsp-style/styles/professional.yml --stdout
144
11
  ```
145
12
 
146
- ### Complete output example
147
-
148
- Given `professional.yml`:
149
-
150
- ```css
151
- @layer base {
152
- :root {
153
- --background: 0 0% 100%;
154
- --foreground: 222 47% 11%;
155
- --card: 210 40% 98%;
156
- --card-foreground: 222 47% 11%;
157
- --popover: 210 40% 98%;
158
- --popover-foreground: 222 47% 11%;
159
- --primary: 221 72% 40%;
160
- --primary-foreground: 0 0% 100%;
161
- --secondary: 215 16% 47%;
162
- --secondary-foreground: 0 0% 100%;
163
- --muted: 213 27% 84%;
164
- --muted-foreground: 215 16% 47%;
165
- --accent: 199 89% 48%;
166
- --accent-foreground: 0 0% 100%;
167
- --destructive: 0 72% 51%;
168
- --destructive-foreground: 0 0% 100%;
169
- --border: 214 32% 91%;
170
- --input: 214 32% 91%;
171
- --ring: 221 72% 40%;
172
- --radius: 0.75rem;
173
- --chart-1: 221 72% 40%;
174
- --chart-2: 215 16% 47%;
175
- --chart-3: 199 89% 48%;
176
- --chart-4: 217 91% 60%;
177
- --chart-5: 142 71% 45%;
178
- }
179
-
180
- .dark {
181
- --background: 222 47% 11%;
182
- --foreground: 210 40% 96%;
183
- --card: 217 33% 17%;
184
- --card-foreground: 210 40% 96%;
185
- --popover: 217 33% 17%;
186
- --popover-foreground: 210 40% 96%;
187
- --border: 217 19% 27%;
188
- --input: 217 19% 27%;
189
- --muted: 215 20% 65%;
190
- --muted-foreground: 215 20% 65%;
191
- }
192
- }
193
- ```
194
-
195
- ---
196
-
197
- ## Target: Tailwind (no component library)
198
-
199
- For codebases using Tailwind without shadcn, map directly to `tailwind.config` `extend`:
200
-
201
- ```js
202
- theme: {
203
- extend: {
204
- colors: {
205
- primary: "var(--color-primary)",
206
- secondary: "var(--color-secondary)",
207
- accent: "var(--color-accent)",
208
- background: "var(--color-background)",
209
- surface: "var(--color-surface)",
210
- foreground: "var(--color-foreground)",
211
- muted: "var(--color-muted)",
212
- error: "var(--color-error)",
213
- success: "var(--color-success)",
214
- warning: "var(--color-warning)",
215
- },
216
- fontFamily: {
217
- sans: [/* typography.font-family-primary */],
218
- mono: [/* typography.font-family-mono */],
219
- },
220
- borderRadius: {
221
- sm: "var(--radius-sm)",
222
- md: "var(--radius-md)",
223
- lg: "var(--radius-lg)",
224
- },
225
- boxShadow: {
226
- sm: "var(--shadow-sm)",
227
- md: "var(--shadow-md)",
228
- lg: "var(--shadow-lg)",
229
- xl: "var(--shadow-xl)",
230
- },
231
- }
232
- }
233
- ```
234
-
235
- CSS variables use hex directly (no HSL conversion needed):
236
-
237
- ```css
238
- :root {
239
- --color-primary: #1E40AF;
240
- --color-secondary: #475569;
241
- --color-background: #FFFFFF;
242
- --color-surface: #F8FAFC;
243
- --color-foreground: #0F172A;
244
- --color-muted: #94A3B8;
245
- --radius-sm: 6px;
246
- --radius-md: 8px;
247
- --radius-lg: 12px;
248
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
249
- --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
250
- }
251
- ```
252
-
253
- ---
254
-
255
- ## Target: Vanilla CSS
256
-
257
- For non-Tailwind codebases, generate a CSS custom property system with semantic class recipes:
258
-
259
- ```css
260
- :root {
261
- /* Brand */
262
- --color-primary: #1E40AF;
263
- --color-secondary: #475569;
264
- --color-accent: #0EA5E9;
265
- --color-bg: #FFFFFF;
266
- --color-surface: #F8FAFC;
267
- --color-text: #0F172A;
268
- --color-muted: #94A3B8;
269
- --color-border: #E2E8F0;
270
-
271
- /* Semantic */
272
- --color-error: #DC2626;
273
- --color-success: #16A34A;
274
- --color-warning: #D97706;
275
-
276
- /* Shape */
277
- --radius-sm: 6px;
278
- --radius-md: 8px;
279
- --radius-lg: 12px;
280
- --border-width: 1px;
281
-
282
- /* Elevation */
283
- --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
284
- --shadow-md: 0 4px 6px rgba(0, 0, 0, 0.07);
285
-
286
- /* Spacing */
287
- --space-1: 4px;
288
- --space-2: 8px;
289
- --space-3: 12px;
290
- --space-4: 16px;
291
- --space-6: 24px;
292
- --space-8: 32px;
293
- --space-12: 48px;
294
- --space-16: 64px;
295
-
296
- /* Motion */
297
- --duration-fast: 150ms;
298
- --duration-normal: 250ms;
299
- --easing: cubic-bezier(0.4, 0, 0.2, 1);
300
-
301
- /* Typography */
302
- --font-sans: Inter, system-ui, sans-serif;
303
- --font-mono: SF Mono, Menlo, monospace;
304
- --font-weight-heading: 600;
305
- --font-weight-body: 400;
306
- --font-size-base: 16px;
307
- --line-height-base: 1.6;
308
- }
309
- ```
310
-
311
- ---
312
-
313
- ## Layered resolution
314
-
315
- The builder resolves tokens in this order (last wins):
13
+ Output is `:root { }` + `.dark { }` blocks ready to paste into `globals.css`.
316
14
 
317
- 1. **Preset `.yml`** — base tokens from the style preset (e.g., `professional.yml`)
318
- 2. **Brand `.yml`** — overrides from branding process (e.g., `acme.yml` with `style_base: professional`)
319
- 3. **Dark mode** — `dark_mode.color.*` overrides for `.dark` scope
15
+ ## How it works
320
16
 
321
- If only a preset exists (quick project), step 2 is skipped. The builder generates CSS from whatever `.yml` it receives.
17
+ - Hex `#RRGGBB` values converted to OKLCH (full color math: sRGB linear XYZ OKLab OKLCh)
18
+ - Values containing `oklch(` → passed through as-is (handles alpha variants)
19
+ - All other values (font stacks, shadows, etc.) → passed through verbatim
20
+ - `--radius` derived from `shape.border-radius-lg`
21
+ - `--chart-1` through `--chart-5` derived from palette colors
22
+ - Sidebar vars written from explicit `color.sidebar-*` tokens in the `.yml`
322
23
 
323
- ## When to generate extended files
24
+ ## Token structure
324
25
 
325
- | Scenario | Files produced |
326
- |----------|---------------|
327
- | Quick project (`/gsp-style`) | Preset `.yml` (base) → CSS vars generated at build time |
328
- | Full branding (customized) | Brand `.yml` (inherits preset) + `STYLE.md` |
329
- | Full branding (unchanged from preset) | Only `STYLE.md` (brand `.yml` not needed if identical to preset) |
26
+ See `${CLAUDE_SKILL_DIR}/../gsp-style/style-preset-schema.md` for the full `.yml` schema — all shadcn variables are first-class token keys.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: gsp-brand-identity
3
- description: Create your visual identity — logo, color, typography (creative phase — benefits from capable models)
3
+ description: Create visual identity — logo, color, typography (creative phase — benefits from capable models) — use when: design the logo, pick colors, choose fonts, create the visual identity
4
4
  user-invocable: true
5
5
  allowed-tools:
6
6
  - Read