get-shit-pretty 0.7.4 → 0.8.3
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.
- package/README.md +21 -14
- package/bin/install.js +10 -10
- package/bin/theme-css.js +331 -0
- package/gsp/agents/gsp-brand-coherence.md +7 -0
- package/gsp/skills/get-shit-pretty/SKILL.md +3 -1
- package/gsp/skills/gsp-brand-brief/SKILL.md +50 -5
- package/gsp/skills/gsp-brand-guidelines/SKILL.md +51 -31
- package/gsp/skills/gsp-brand-guidelines/design-tokens.md +2 -0
- package/gsp/skills/gsp-brand-guidelines/guidelines-structure.md +167 -0
- package/gsp/skills/gsp-brand-guidelines/methodology/gsp-brand-coherence.md +86 -0
- package/gsp/skills/gsp-brand-guidelines/methodology/gsp-brand-engineer.md +13 -5
- package/gsp/skills/gsp-brand-guidelines/token-mapping.md +16 -319
- package/gsp/skills/gsp-brand-identity/SKILL.md +1 -1
- package/gsp/skills/gsp-brand-refine/SKILL.md +5 -6
- package/gsp/skills/gsp-brand-research/SKILL.md +1 -1
- package/gsp/skills/gsp-brand-strategy/SKILL.md +1 -1
- package/gsp/skills/gsp-design-system/SKILL.md +1 -1
- package/gsp/skills/gsp-doctor/SKILL.md +54 -6
- package/gsp/skills/gsp-progress/SKILL.md +1 -1
- package/gsp/skills/gsp-project-brief/SKILL.md +40 -6
- package/gsp/skills/gsp-project-build/SKILL.md +22 -29
- package/gsp/skills/gsp-project-build/flows/figma.md +50 -0
- package/gsp/skills/gsp-project-build/flows/revision.md +64 -0
- package/gsp/skills/gsp-project-build/methodology/gsp-project-builder.md +57 -4
- package/gsp/skills/gsp-project-build/shadcn-composition.md +217 -0
- package/gsp/skills/gsp-project-critique/SKILL.md +3 -1
- package/gsp/skills/gsp-project-design/SKILL.md +3 -1
- package/gsp/skills/gsp-project-research/SKILL.md +3 -1
- package/gsp/skills/gsp-project-review/SKILL.md +10 -1
- package/gsp/skills/gsp-scaffold/SKILL.md +49 -12
- package/gsp/skills/gsp-scaffold/shadcn-rules.md +433 -0
- package/gsp/skills/gsp-scaffold/shadcn-theming.md +310 -0
- package/gsp/skills/gsp-start/SKILL.md +18 -2
- package/gsp/skills/gsp-style/SKILL.md +1 -1
- package/gsp/skills/gsp-style/style-preset-schema.md +59 -14
- package/gsp/skills/gsp-style/styles/academia.yml +58 -8
- package/gsp/skills/gsp-style/styles/art-deco.yml +39 -7
- package/gsp/skills/gsp-style/styles/bauhaus.yml +39 -8
- package/gsp/skills/gsp-style/styles/bold-typography.yml +39 -8
- package/gsp/skills/gsp-style/styles/botanical.yml +39 -9
- package/gsp/skills/gsp-style/styles/claymorphism.yml +39 -9
- package/gsp/skills/gsp-style/styles/cyberpunk.yml +39 -7
- package/gsp/skills/gsp-style/styles/enterprise.yml +39 -10
- package/gsp/skills/gsp-style/styles/flat-design.yml +39 -9
- package/gsp/skills/gsp-style/styles/fluent.yml +39 -10
- package/gsp/skills/gsp-style/styles/glassmorphism.yml +39 -8
- package/gsp/skills/gsp-style/styles/humanist-literary.yml +39 -9
- package/gsp/skills/gsp-style/styles/industrial.yml +59 -9
- package/gsp/skills/gsp-style/styles/kinetic.yml +32 -7
- package/gsp/skills/gsp-style/styles/liquid-glass.yml +59 -9
- package/gsp/skills/gsp-style/styles/luxury.yml +59 -9
- package/gsp/skills/gsp-style/styles/material.yml +59 -9
- package/gsp/skills/gsp-style/styles/maximalism.yml +32 -6
- package/gsp/skills/gsp-style/styles/minimal-dark.yml +32 -7
- package/gsp/skills/gsp-style/styles/modern-dark.yml +32 -7
- package/gsp/skills/gsp-style/styles/monochrome.yml +59 -10
- package/gsp/skills/gsp-style/styles/neubrutalism.yml +59 -9
- package/gsp/skills/gsp-style/styles/neumorphism.yml +32 -7
- package/gsp/skills/gsp-style/styles/newsprint.yml +32 -7
- package/gsp/skills/gsp-style/styles/nothing.yml +44 -13
- package/gsp/skills/gsp-style/styles/organic.yml +42 -9
- package/gsp/skills/gsp-style/styles/playful-geometric.yml +43 -9
- package/gsp/skills/gsp-style/styles/professional.yml +41 -10
- package/gsp/skills/gsp-style/styles/retro.yml +42 -8
- package/gsp/skills/gsp-style/styles/saas.yml +42 -9
- package/gsp/skills/gsp-style/styles/sketch.yml +42 -9
- package/gsp/skills/gsp-style/styles/swiss-minimalist.yml +41 -10
- package/gsp/skills/gsp-style/styles/terminal.yml +42 -8
- package/gsp/skills/gsp-style/styles/vaporwave.yml +42 -7
- package/gsp/skills/gsp-style/styles/web3.yml +42 -9
- package/gsp/skills/gsp-update/SKILL.md +9 -6
- package/gsp/templates/branding/brief.md +9 -0
- package/gsp/templates/branding/config.json +1 -1
- package/gsp/templates/design-claude.md +6 -0
- package/gsp/templates/phases/patterns.md +2 -2
- package/gsp/templates/projects/config.json +6 -3
- package/gsp/templates/projects/state.md +1 -1
- package/gsp/templates/system/STACK.md +1 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsp-project-build
|
|
3
|
-
description: Translate designs to code (technical phase — benefits from capable models)
|
|
3
|
+
description: Translate designs to code (technical phase — benefits from capable models) — use when: build this, implement, code this up, build me a X, add a X to the app, make the X page
|
|
4
4
|
user-invocable: true
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
@@ -70,6 +70,8 @@ Implement designs as production-ready code in the codebase via phased pipeline w
|
|
|
70
70
|
<process>
|
|
71
71
|
## Step 0: Resolve project and brand
|
|
72
72
|
|
|
73
|
+
If `.design/projects/` does not exist: output "No GSP project found. Run `/gsp-start` to begin." and stop.
|
|
74
|
+
|
|
73
75
|
Resolve project from `.design/projects/` (one → use it, multiple → ask). Set `PROJECT_PATH`.
|
|
74
76
|
|
|
75
77
|
Read `{PROJECT_PATH}/brand.ref` → set `BRAND_PATH`.
|
|
@@ -83,7 +85,9 @@ Exception: if `design_scope` is `tokens` in config.json, skip this check (tokens
|
|
|
83
85
|
|
|
84
86
|
## Step 1: Load config and check state
|
|
85
87
|
|
|
86
|
-
Read `{PROJECT_PATH}/config.json` to get `implementation_target`, `design_scope`, `codebase_type`.
|
|
88
|
+
Read `{PROJECT_PATH}/config.json` to get `implementation_target`, `design_scope`, `codebase_type`, `app_path`.
|
|
89
|
+
|
|
90
|
+
Set `APP_PATH` = value of `app_path`. If empty, default to `.` (repo root).
|
|
87
91
|
|
|
88
92
|
### Branch check
|
|
89
93
|
|
|
@@ -132,7 +136,7 @@ Read `${CLAUDE_SKILL_DIR}/methodology/gsp-project-builder.md`. Include the full
|
|
|
132
136
|
Read these reference files:
|
|
133
137
|
- `${CLAUDE_SKILL_DIR}/visual-effects.md`
|
|
134
138
|
- `${CLAUDE_SKILL_DIR}/../gsp-project-design/block-patterns.md`
|
|
135
|
-
- `${CLAUDE_SKILL_DIR}
|
|
139
|
+
- `${CLAUDE_SKILL_DIR}/shadcn-composition.md`
|
|
136
140
|
|
|
137
141
|
Hold their content for inlining into agent prompts in Steps 3, 4.5, 5, 7, and 8.
|
|
138
142
|
|
|
@@ -149,12 +153,13 @@ Spawn `gsp-project-builder` agent with **execution_mode: foundations**.
|
|
|
149
153
|
| `{BRAND_PATH}/patterns/{brand-name}.yml` | Token values only — used with token-mapping.md to generate CSS variables. Do NOT re-read patterns/constraints/effects from here — those are in STYLE.md. |
|
|
150
154
|
| `{BRAND_PATH}/patterns/STYLE.md` | Design law — philosophy, patterns, constraints, effects, bold bets, implementation hints (if exists; fall back to `{brand-name}.md`) |
|
|
151
155
|
| `{PROJECT_PATH}/brief/target-adaptations.md` | Component adaptations for target |
|
|
152
|
-
| `.design/system/STACK.md` | Stack state |
|
|
156
|
+
| `.design/system/STACK.md` | Stack state (or `.design/system/stacks/{APP_NAME}.md` for monorepos) |
|
|
153
157
|
| `.design/system/CONVENTIONS.md` | Codebase conventions (if exists) |
|
|
154
158
|
| `.design/system/COMPONENTS.md` | Existing components (if exists) |
|
|
155
|
-
| `{PROJECT_PATH}/config.json` | Tech stack, target |
|
|
159
|
+
| `{PROJECT_PATH}/config.json` | Tech stack, target, `app_path` |
|
|
160
|
+
| `APP_PATH = {APP_PATH}` | Working directory — all file writes and build commands run here |
|
|
156
161
|
| Build output template (from execution_context) | Build log structure |
|
|
157
|
-
| Token mapping ref (loaded in Step 2.6) |
|
|
162
|
+
| Token mapping ref (loaded in Step 2.6) | shadcn component composition rules, semantic token usage, `cn()`, `cva`, RSC patterns |
|
|
158
163
|
| Visual effects, block patterns refs (loaded in Step 2.6) | Design patterns + CSS recipes |
|
|
159
164
|
| Agent methodology (loaded in Step 2.5) | Builder role, process, quality standards |
|
|
160
165
|
|
|
@@ -164,7 +169,7 @@ Spawn `gsp-project-builder` agent with **execution_mode: foundations**.
|
|
|
164
169
|
>
|
|
165
170
|
> Build token integration, global styles, and layout primitives ONLY.
|
|
166
171
|
>
|
|
167
|
-
> 1. Integrate design tokens into the codebase
|
|
172
|
+
> 1. Integrate design tokens into the codebase: run `node bin/theme-css.js {brand-name}.yml --stdout` and paste the OKLCH `:root`/`.dark` output into `globals.css`. For shadcn targets, follow the `@theme inline` pattern from `shadcn-rules.md`. Map ALL variables — background, foreground, card, popover, primary, secondary, muted, accent, destructive, border, input, ring, sidebar-*, chart-1 through chart-5, and --radius.
|
|
168
173
|
> 2. Create global CSS (resets, base styles, font imports, dark mode setup)
|
|
169
174
|
> 3. Create root layout with nav shell and footer shell (structure only — no page content)
|
|
170
175
|
> 4. Create shared utilities (cn helper, theme provider if needed)
|
|
@@ -178,14 +183,14 @@ Spawn `gsp-project-builder` agent with **execution_mode: foundations**.
|
|
|
178
183
|
|
|
179
184
|
### Checkpoint: Compile check
|
|
180
185
|
|
|
181
|
-
After the foundations agent completes, run the build command
|
|
186
|
+
After the foundations agent completes, run the build command in `APP_PATH`:
|
|
182
187
|
|
|
183
188
|
| Stack | Build command |
|
|
184
189
|
|-------|--------------|
|
|
185
|
-
| Next.js | `npx next build` |
|
|
186
|
-
| Vite | `npx vite build` |
|
|
187
|
-
| TypeScript only | `npx tsc --noEmit` |
|
|
188
|
-
| Generic | `npm run build` |
|
|
190
|
+
| Next.js | `cd {APP_PATH} && npx next build` |
|
|
191
|
+
| Vite | `cd {APP_PATH} && npx vite build` |
|
|
192
|
+
| TypeScript only | `cd {APP_PATH} && npx tsc --noEmit` |
|
|
193
|
+
| Generic | `cd {APP_PATH} && npm run build` |
|
|
189
194
|
|
|
190
195
|
**Pass:** Continue to preview verification, then Step 4.
|
|
191
196
|
**Fail:** Log the error. Do NOT re-spawn the agent. Surface the error to the user and ask how to proceed.
|
|
@@ -497,25 +502,13 @@ Invoke `/gsp-phase-transition` with phase `build` and output directory `{PROJECT
|
|
|
497
502
|
|
|
498
503
|
## Step 7: Figma fallback
|
|
499
504
|
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
## Step 8: Revision mode
|
|
503
|
-
|
|
504
|
-
For `needs-revision` status, spawn a single `gsp-project-builder` agent with execution_mode: `full` and `review/issues.md` contents. The agent fixes QA issues in the codebase and appends revision sections to BUILD-LOG.md.
|
|
505
|
+
Read `${CLAUDE_SKILL_DIR}/flows/figma.md` for full instructions.
|
|
505
506
|
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
After the revision agent completes, run the build command (same stack table as Step 3 checkpoint).
|
|
509
|
-
|
|
510
|
-
**Pass:** Continue to brand feedback check below.
|
|
511
|
-
**Fail:** Log the error. Surface to user: "Revision introduced build errors: {error}. Fix before finalizing?"
|
|
507
|
+
For `implementation_target: figma`, skip the phased pipeline. Produce Figma-ready implementation specs instead of editing the codebase. Then continue from Step 6 (finalize).
|
|
512
508
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
After the revision agent completes, check if any QA fixes changed token-level values (colors, typography, spacing, shadows). If so:
|
|
509
|
+
## Step 8: Revision mode
|
|
516
510
|
|
|
517
|
-
|
|
518
|
-
2. If yes, spawn a background `gsp-brand-engineer` agent with the changed values to update `{BRAND_PATH}/patterns/`.
|
|
511
|
+
Read `${CLAUDE_SKILL_DIR}/flows/revision.md` for full instructions.
|
|
519
512
|
|
|
520
|
-
Then continue from Step 6 (finalize).
|
|
513
|
+
For `needs-revision` status, fix QA issues from `review/issues.md` via a single revision agent. Then continue from Step 6 (finalize).
|
|
521
514
|
</process>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
# Build Flow: Figma Fallback
|
|
2
|
+
|
|
3
|
+
Activated when `implementation_target` is `figma` in `config.json`.
|
|
4
|
+
|
|
5
|
+
## When this runs
|
|
6
|
+
|
|
7
|
+
When the project's target is Figma (designer handoff), there is no codebase to edit. Instead, the builder produces structured implementation specs that a developer can use to implement in Figma or hand off to their dev team.
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
### 1. Log intent
|
|
12
|
+
|
|
13
|
+
Log: "Figma target — producing implementation specs (no codebase to edit)"
|
|
14
|
+
|
|
15
|
+
### 2. Spawn spec agent
|
|
16
|
+
|
|
17
|
+
Spawn a single `gsp-project-builder` agent with:
|
|
18
|
+
- `execution_mode: full`
|
|
19
|
+
- `spec_only: true`
|
|
20
|
+
- All design chunks from `{PROJECT_PATH}/design/` inlined
|
|
21
|
+
- Brand system: `{BRAND_PATH}/patterns/STYLE.md` and `{BRAND_PATH}/patterns/{brand-name}.yml`
|
|
22
|
+
- Brief: `{PROJECT_PATH}/brief/target-adaptations.md` and `{PROJECT_PATH}/brief/scope.md`
|
|
23
|
+
- Agent methodology (loaded in Step 2.5 of main flow)
|
|
24
|
+
|
|
25
|
+
Agent instructions:
|
|
26
|
+
|
|
27
|
+
> execution_mode: full
|
|
28
|
+
> spec_only: true
|
|
29
|
+
>
|
|
30
|
+
> Produce Figma-ready implementation specs — no codebase to edit.
|
|
31
|
+
>
|
|
32
|
+
> Output:
|
|
33
|
+
> 1. `{PROJECT_PATH}/build/CODE.md` — component-by-component implementation guide:
|
|
34
|
+
> - For each screen: component tree, token values, interaction states, responsive behavior
|
|
35
|
+
> - For each component: props, variants, accessibility requirements
|
|
36
|
+
> - Token table: all CSS variables with values from the brand `.yml`
|
|
37
|
+
>
|
|
38
|
+
> 2. `{PROJECT_PATH}/build/components/` — one `.md` file per significant custom component:
|
|
39
|
+
> - Structure (HTML/JSX pseudocode)
|
|
40
|
+
> - Variants and states
|
|
41
|
+
> - Token usage (which CSS variables drive which properties)
|
|
42
|
+
> - Accessibility notes (ARIA roles, keyboard, focus)
|
|
43
|
+
>
|
|
44
|
+
> Format specs for developer consumption — be precise about measurements, colors (include both OKLCH and hex), and interaction behavior.
|
|
45
|
+
|
|
46
|
+
### 3. Finalize
|
|
47
|
+
|
|
48
|
+
After the spec agent completes, continue from Step 6 (Finalize) of the main build flow.
|
|
49
|
+
|
|
50
|
+
`BUILD-LOG.md` in this mode documents spec files produced rather than codebase changes.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Build Flow: Revision Mode
|
|
2
|
+
|
|
3
|
+
Activated when `{PROJECT_PATH}/STATE.md` shows build status `needs-revision`.
|
|
4
|
+
|
|
5
|
+
## When this runs
|
|
6
|
+
|
|
7
|
+
After `/gsp-project-review` completes and writes `{PROJECT_PATH}/review/issues.md` with QA issues, the next invocation of `/gsp-project-build` enters revision mode automatically.
|
|
8
|
+
|
|
9
|
+
## Steps
|
|
10
|
+
|
|
11
|
+
### 1. Read issues
|
|
12
|
+
|
|
13
|
+
Read `{PROJECT_PATH}/review/issues.md`. This file contains QA issues prioritized by severity.
|
|
14
|
+
|
|
15
|
+
Log: "Revision mode — addressing QA issues from review/issues.md"
|
|
16
|
+
|
|
17
|
+
### 2. Spawn revision agent
|
|
18
|
+
|
|
19
|
+
Spawn a single `gsp-project-builder` agent with:
|
|
20
|
+
- `execution_mode: full`
|
|
21
|
+
- `revision: true`
|
|
22
|
+
- Full content of `review/issues.md` inlined
|
|
23
|
+
- Agent methodology (loaded in Step 2.5 of main flow)
|
|
24
|
+
- Visual effects and block patterns refs (loaded in Step 2.6 of main flow)
|
|
25
|
+
|
|
26
|
+
Agent instructions:
|
|
27
|
+
|
|
28
|
+
> execution_mode: full
|
|
29
|
+
> revision: true
|
|
30
|
+
>
|
|
31
|
+
> Fix the QA issues from review/issues.md in the codebase.
|
|
32
|
+
>
|
|
33
|
+
> 1. Work through issues in priority order (critical → high → medium → low)
|
|
34
|
+
> 2. Read the relevant codebase files before editing — don't guess at existing structure
|
|
35
|
+
> 3. Do NOT modify foundation files unless the QA issue explicitly requires it
|
|
36
|
+
> 4. Do NOT refactor or improve code outside the scope of the listed issues
|
|
37
|
+
> 5. Leave changes unstaged
|
|
38
|
+
>
|
|
39
|
+
> After completing revisions, append a `## Revision` section to `{PROJECT_PATH}/build/BUILD-LOG.md` listing each issue addressed (issue ID, file changed, what was fixed).
|
|
40
|
+
|
|
41
|
+
### 3. Compile check
|
|
42
|
+
|
|
43
|
+
After the revision agent completes, run the build command:
|
|
44
|
+
|
|
45
|
+
| Stack | Build command |
|
|
46
|
+
|-------|--------------|
|
|
47
|
+
| Next.js | `npx next build` |
|
|
48
|
+
| Vite | `npx vite build` |
|
|
49
|
+
| TypeScript only | `npx tsc --noEmit` |
|
|
50
|
+
| Generic | `npm run build` |
|
|
51
|
+
|
|
52
|
+
**Pass:** Continue to brand feedback check.
|
|
53
|
+
**Fail:** Log the error. Surface to user: "Revision introduced build errors: {error}. Fix before finalizing?"
|
|
54
|
+
|
|
55
|
+
### 4. Brand feedback on revisions
|
|
56
|
+
|
|
57
|
+
After the revision agent completes, check if any QA fixes changed token-level values (colors, typography, spacing, shadows). If so:
|
|
58
|
+
|
|
59
|
+
1. Ask: "These revisions changed brand-level values. Update brand patterns so future projects inherit the fix?"
|
|
60
|
+
2. If yes, spawn a background `gsp-brand-engineer` agent with the changed values to update `{BRAND_PATH}/patterns/`.
|
|
61
|
+
|
|
62
|
+
### 5. Finalize
|
|
63
|
+
|
|
64
|
+
Continue from Step 6 (Finalize) of the main build flow.
|
|
@@ -17,7 +17,7 @@ You are spawned with an `execution_mode` parameter. Follow the mode strictly:
|
|
|
17
17
|
|
|
18
18
|
### `foundations`
|
|
19
19
|
Build token integration, global styles, and layout primitives ONLY. Stop after foundations.
|
|
20
|
-
- Design tokens → CSS variables / Tailwind config.
|
|
20
|
+
- Design tokens → CSS variables / Tailwind config. Run `node bin/theme-css.js <preset.yml> --stdout` to generate a ready-to-paste `:root` and `.dark` block in OKLCH format. If `bin/theme-css.js` is unavailable, convert hex to OKLCH manually. Write ALL variables in `:root` and `.dark` scopes (background, foreground, card, popover, primary, secondary, muted, accent, destructive, border, input, ring, sidebar-*, chart-1 through chart-5, --radius). Write only **global tokens**: brand colors, font families, spacing scale, base radius, base shadows. Do NOT write screen-specific tokens yet.
|
|
21
21
|
- Global CSS (resets, base styles, dark mode)
|
|
22
22
|
- Layout components (root layout, nav shell, footer shell)
|
|
23
23
|
- Shared utilities (cn helper, theme provider)
|
|
@@ -125,19 +125,72 @@ These rules are always enforced for shadcn targets. They reflect the official sh
|
|
|
125
125
|
- Use full Card composition (`CardHeader`/`CardTitle`/`CardDescription`/`CardContent`/`CardFooter`)
|
|
126
126
|
- `TabsTrigger` must be inside `TabsList`
|
|
127
127
|
- `Avatar` always needs `AvatarFallback`
|
|
128
|
-
- Use `Alert` for callouts, `Badge` for status, `Skeleton` for loading, `Separator` for dividers, `sonner` for toast
|
|
128
|
+
- Use `Alert` for callouts, `Badge` for status, `Skeleton` for loading, `Separator` for dividers, `Empty` for empty states, `sonner` for toast
|
|
129
|
+
- `Button` has no `isPending`/`isLoading` prop — compose with `<Spinner data-icon="inline-start" />` + `disabled`
|
|
130
|
+
|
|
131
|
+
**Forms:**
|
|
132
|
+
- Use `FieldGroup` + `Field` for form layout — never raw `div` with `space-y-*` or `grid gap-*`
|
|
133
|
+
- Option sets (2–7 choices) use `ToggleGroup` + `ToggleGroupItem` — not a loop of `Button` with manual active state
|
|
134
|
+
- Buttons inside inputs use `InputGroup` + `InputGroupAddon` — not `relative` positioning with `absolute` button
|
|
135
|
+
- Use `InputGroupInput` / `InputGroupTextarea` inside `InputGroup` — not raw `Input`/`Textarea`
|
|
136
|
+
- Group related checkboxes/radios with `FieldSet` + `FieldLegend` — not `div` with a heading
|
|
137
|
+
- Field validation: `data-invalid` on `Field`, `aria-invalid` on the control; `data-disabled` on `Field`, `disabled` on the control
|
|
138
|
+
|
|
139
|
+
**base vs radix API (check `base` from `npx shadcn@latest info`):**
|
|
140
|
+
- Custom triggers: `asChild` (radix) vs `render` prop (base)
|
|
141
|
+
- Button as link: `<Button asChild><a>` (radix) vs `<Button render={<a />} nativeButton={false}>` (base)
|
|
142
|
+
- `ToggleGroup`: radix uses `type="single"/"multiple"` + string `defaultValue`; base uses no `type` + array `defaultValue`
|
|
143
|
+
- `Slider`: radix always uses array (`defaultValue={[50]}`); base uses plain number for single thumb
|
|
144
|
+
- `Select`: base requires `items` prop on root; radix uses inline JSX only
|
|
129
145
|
|
|
130
146
|
**Icons:**
|
|
131
|
-
- Icons in `Button` use `data-icon` attribute (`data-icon="inline-start"` or `data-icon="inline-end"`)
|
|
147
|
+
- Icons in `Button` use `data-icon` attribute (`data-icon="inline-start"` or `data-icon="inline-end"`) — do NOT add `mr-2`/`ml-2` margin; the component handles spacing via CSS
|
|
132
148
|
- No sizing classes on icons inside components — components handle icon sizing via CSS
|
|
133
149
|
|
|
134
150
|
**CLI awareness:**
|
|
135
151
|
- Install components via `npx shadcn@latest add {name}` — never copy/paste from GitHub
|
|
136
|
-
- Use `npx shadcn@latest search` to find components before building custom ones
|
|
152
|
+
- Use `npx shadcn@latest search {name}` to find components before building custom ones
|
|
153
|
+
- Use `npx shadcn@latest docs {name}` to get live docs and example URLs before implementing or debugging a component
|
|
154
|
+
- Use `npx shadcn@latest add {name} --dry-run` to preview all affected files before writing
|
|
155
|
+
- Use `npx shadcn@latest add {name} --diff {file}` to preview a specific file's changes before overwriting
|
|
137
156
|
- After installing components from registries, verify imports match the project's alias config
|
|
157
|
+
- After installing from community registries, check added non-UI files for hardcoded `@/components/ui/...` paths — rewrite to match the project's actual aliases
|
|
158
|
+
|
|
159
|
+
**Charts (Recharts v3):**
|
|
160
|
+
- Color references: `fill="var(--chart-1)"` or `fill="var(--color-chart-1)"` — **no `hsl()` wrapper** (tokens are OKLCH, not HSL channels)
|
|
161
|
+
- `<ChartContainer>` **requires** an explicit height — add `className="min-h-[200px]"` or `aspect-video`; no implicit height is set
|
|
162
|
+
- Add `accessibilityLayer` prop to chart root elements (`<BarChart accessibilityLayer>`)
|
|
163
|
+
- The `layout` prop belongs on the parent chart (`<BarChart layout="vertical">`), not on `<Bar>`
|
|
164
|
+
|
|
165
|
+
**Forms (React Hook Form + Field API):**
|
|
166
|
+
- New projects use the `<Field>/<Controller>` API — not `<FormField>/<FormItem>/<FormControl>/<FormMessage>`:
|
|
167
|
+
```jsx
|
|
168
|
+
<Controller
|
|
169
|
+
name="email"
|
|
170
|
+
control={form.control}
|
|
171
|
+
render={({ field, fieldState }) => (
|
|
172
|
+
<Field data-invalid={fieldState.invalid}>
|
|
173
|
+
<FieldLabel htmlFor={field.name}>Email</FieldLabel>
|
|
174
|
+
<Input {...field} id={field.name} aria-invalid={fieldState.invalid} />
|
|
175
|
+
{fieldState.invalid && <FieldError errors={[fieldState.error]} />}
|
|
176
|
+
</Field>
|
|
177
|
+
)}
|
|
178
|
+
/>
|
|
179
|
+
```
|
|
180
|
+
- Components: `Field`, `FieldLabel`, `FieldDescription`, `FieldError`, `FieldGroup`, `FieldSet`, `FieldLegend`
|
|
181
|
+
- If the existing project has the old `form.tsx` (with `FormField`/`FormItem`), match its pattern — do not mix APIs
|
|
182
|
+
|
|
183
|
+
**Sidebar:**
|
|
184
|
+
- Set custom sidebar width via inline CSS prop on `<SidebarProvider>`:
|
|
185
|
+
```jsx
|
|
186
|
+
<SidebarProvider style={{ "--sidebar-width": "20rem" } as React.CSSProperties}>
|
|
187
|
+
```
|
|
188
|
+
- Do not override `--sidebar-width` in `globals.css` — it belongs on the provider instance
|
|
138
189
|
|
|
139
190
|
Full reference: `references/anti-patterns.md` (available via Read for the complete list with fixes).
|
|
140
191
|
|
|
192
|
+
**Theming reference:** when building or fixing themes, read `${CLAUDE_SKILL_DIR}/../../gsp-scaffold/shadcn-theming.md` — full token table, dark mode setup, common theming bugs and fixes.
|
|
193
|
+
|
|
141
194
|
## Visual Quality Checklist
|
|
142
195
|
|
|
143
196
|
Every screen must pass these before marking complete. When `STYLE.md` is provided, it overrides these defaults.
|
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
# shadcn/ui Rules — Tier 2: Component Composition
|
|
2
|
+
|
|
3
|
+
Rules for the build phase. The builder agent reads this to compose shadcn components correctly.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The `cn()` helper
|
|
8
|
+
|
|
9
|
+
All conditional class merging uses `cn()` from `@/lib/utils`:
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { cn } from "@/lib/utils"
|
|
13
|
+
|
|
14
|
+
// Correct
|
|
15
|
+
<Button className={cn("mt-4", isActive && "ring-2 ring-ring")} />
|
|
16
|
+
|
|
17
|
+
// Wrong — never string-concatenate classes
|
|
18
|
+
<Button className={"mt-4" + (isActive ? " ring-2 ring-ring" : "")} />
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`cn` is `clsx` + `tailwind-merge`. It handles class deduplication and Tailwind conflict resolution automatically.
|
|
22
|
+
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
## Semantic color tokens — always use these
|
|
26
|
+
|
|
27
|
+
| Instead of | Use |
|
|
28
|
+
|------------|-----|
|
|
29
|
+
| `bg-white` / `bg-black` | `bg-background` |
|
|
30
|
+
| `text-gray-900` | `text-foreground` |
|
|
31
|
+
| `text-gray-500` | `text-muted-foreground` |
|
|
32
|
+
| `bg-gray-100` | `bg-muted` |
|
|
33
|
+
| `bg-gray-50` | `bg-secondary` |
|
|
34
|
+
| `border-gray-200` | `border-border` |
|
|
35
|
+
| `ring-blue-500` | `ring-ring` |
|
|
36
|
+
| raw hex/rgb | Never — always a token |
|
|
37
|
+
|
|
38
|
+
shadcn components use these tokens internally. Using them in custom code makes dark mode automatic.
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## Slot pattern (asChild)
|
|
43
|
+
|
|
44
|
+
Use `asChild` to merge props into a child component without an extra DOM node:
|
|
45
|
+
|
|
46
|
+
```tsx
|
|
47
|
+
// Button as a link
|
|
48
|
+
<Button asChild>
|
|
49
|
+
<Link href="/dashboard">Dashboard</Link>
|
|
50
|
+
</Button>
|
|
51
|
+
|
|
52
|
+
// Never add an <a> inside <Button> without asChild
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
## Variants with `cva`
|
|
58
|
+
|
|
59
|
+
For custom components that need multiple variants, use `cva` (class-variance-authority):
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
import { cva, type VariantProps } from "class-variance-authority"
|
|
63
|
+
|
|
64
|
+
const cardVariants = cva(
|
|
65
|
+
"rounded-lg border bg-card text-card-foreground shadow",
|
|
66
|
+
{
|
|
67
|
+
variants: {
|
|
68
|
+
size: {
|
|
69
|
+
sm: "p-4",
|
|
70
|
+
md: "p-6",
|
|
71
|
+
lg: "p-8",
|
|
72
|
+
},
|
|
73
|
+
elevated: {
|
|
74
|
+
true: "shadow-lg",
|
|
75
|
+
false: "shadow-sm",
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
defaultVariants: {
|
|
79
|
+
size: "md",
|
|
80
|
+
elevated: false,
|
|
81
|
+
},
|
|
82
|
+
}
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
interface CardProps extends VariantProps<typeof cardVariants> {
|
|
86
|
+
className?: string
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
---
|
|
91
|
+
|
|
92
|
+
## Composing shadcn primitives
|
|
93
|
+
|
|
94
|
+
shadcn components are composed from their sub-parts:
|
|
95
|
+
|
|
96
|
+
```tsx
|
|
97
|
+
// Card with all sub-parts
|
|
98
|
+
<Card>
|
|
99
|
+
<CardHeader>
|
|
100
|
+
<CardTitle>Title</CardTitle>
|
|
101
|
+
<CardDescription>Subtitle</CardDescription>
|
|
102
|
+
</CardHeader>
|
|
103
|
+
<CardContent>Content here</CardContent>
|
|
104
|
+
<CardFooter>
|
|
105
|
+
<Button>Action</Button>
|
|
106
|
+
</CardFooter>
|
|
107
|
+
</Card>
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**Rule:** never nest card-level markup inside `<Card>` without using `CardHeader`/`CardContent`/`CardFooter` — it breaks the spacing contract.
|
|
111
|
+
|
|
112
|
+
---
|
|
113
|
+
|
|
114
|
+
## Dialog / Sheet
|
|
115
|
+
|
|
116
|
+
```tsx
|
|
117
|
+
<Dialog>
|
|
118
|
+
<DialogTrigger asChild>
|
|
119
|
+
<Button>Open</Button>
|
|
120
|
+
</DialogTrigger>
|
|
121
|
+
<DialogContent>
|
|
122
|
+
<DialogHeader>
|
|
123
|
+
<DialogTitle>Title</DialogTitle>
|
|
124
|
+
<DialogDescription>Description</DialogDescription>
|
|
125
|
+
</DialogHeader>
|
|
126
|
+
{/* content */}
|
|
127
|
+
<DialogFooter>
|
|
128
|
+
<Button type="submit">Save</Button>
|
|
129
|
+
</DialogFooter>
|
|
130
|
+
</DialogContent>
|
|
131
|
+
</Dialog>
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
`DialogDescription` is required for accessibility — the dialog announces it to screen readers. Omitting it triggers a console warning.
|
|
135
|
+
|
|
136
|
+
---
|
|
137
|
+
|
|
138
|
+
## Form + react-hook-form
|
|
139
|
+
|
|
140
|
+
shadcn Form wraps react-hook-form. Always use the `<Form>` components for labeled inputs — never raw `<input>`:
|
|
141
|
+
|
|
142
|
+
```tsx
|
|
143
|
+
<Form {...form}>
|
|
144
|
+
<form onSubmit={form.handleSubmit(onSubmit)}>
|
|
145
|
+
<FormField
|
|
146
|
+
control={form.control}
|
|
147
|
+
name="email"
|
|
148
|
+
render={({ field }) => (
|
|
149
|
+
<FormItem>
|
|
150
|
+
<FormLabel>Email</FormLabel>
|
|
151
|
+
<FormControl>
|
|
152
|
+
<Input placeholder="you@example.com" {...field} />
|
|
153
|
+
</FormControl>
|
|
154
|
+
<FormDescription>We'll never share your email.</FormDescription>
|
|
155
|
+
<FormMessage />
|
|
156
|
+
</FormItem>
|
|
157
|
+
)}
|
|
158
|
+
/>
|
|
159
|
+
</form>
|
|
160
|
+
</Form>
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
`FormMessage` renders validation errors automatically from react-hook-form's state.
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## Sizing utilities
|
|
168
|
+
|
|
169
|
+
| Instead of | Use |
|
|
170
|
+
|------------|-----|
|
|
171
|
+
| `w-6 h-6` | `size-6` (when width === height) |
|
|
172
|
+
| `space-y-4` | `gap-4` (prefer `flex`/`grid` with `gap`) |
|
|
173
|
+
| `mr-2` on icon | `gap-2` on parent flex container |
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
## Server Components (RSC)
|
|
178
|
+
|
|
179
|
+
Check `isRSC` from `npx shadcn@latest info --json`. If true:
|
|
180
|
+
- shadcn components work as Server Components by default
|
|
181
|
+
- Only add `"use client"` when a component uses `useState`, `useEffect`, event handlers, or browser APIs
|
|
182
|
+
- Prefer `onClick` on leaf elements rather than wrapping entire sections in `"use client"`
|
|
183
|
+
|
|
184
|
+
```tsx
|
|
185
|
+
// Correct — only the interactive button is a client component
|
|
186
|
+
// page.tsx (Server Component)
|
|
187
|
+
import { SubmitButton } from "./submit-button" // "use client"
|
|
188
|
+
|
|
189
|
+
// Wrong — entire section becomes client component unnecessarily
|
|
190
|
+
"use client"
|
|
191
|
+
export function Section() { ... }
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
---
|
|
195
|
+
|
|
196
|
+
## Icon imports
|
|
197
|
+
|
|
198
|
+
Use the icon library from `shadcn info`:
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
// lucide-react (default for most styles)
|
|
202
|
+
import { ChevronRight, Settings, User } from "lucide-react"
|
|
203
|
+
|
|
204
|
+
// @tabler/icons-react (some styles)
|
|
205
|
+
import { IconChevronRight, IconSettings } from "@tabler/icons-react"
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Never import from both in the same project — check `iconLibrary` once and use it everywhere.
|
|
209
|
+
|
|
210
|
+
---
|
|
211
|
+
|
|
212
|
+
## Customization rules
|
|
213
|
+
|
|
214
|
+
1. **Override via className** — always add `className` on top of the component's defaults, never fork the component file unless strictly necessary
|
|
215
|
+
2. **CSS variables over arbitrary values** — `text-[#FF0000]` is a code smell; use a token instead
|
|
216
|
+
3. **Brand effects go in globals.css as utilities** — create `.shadow-brand`, `.glow-accent` etc. as CSS utilities; use them as Tailwind class names
|
|
217
|
+
4. **Never edit generated component files for visual tweaks** — only edit for structural/API changes. Token changes in globals.css automatically propagate
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsp-project-critique
|
|
3
|
-
description: Critique
|
|
3
|
+
description: Critique designs + accessibility audit (creative phase — benefits from capable models) — use when: review the designs, critique this, check accessibility, what's wrong with, give feedback on
|
|
4
4
|
user-invocable: true
|
|
5
5
|
context: fork
|
|
6
6
|
allowed-tools:
|
|
@@ -26,6 +26,8 @@ Critique design quality and audit accessibility compliance.
|
|
|
26
26
|
<process>
|
|
27
27
|
## Step 0: Resolve project and brand
|
|
28
28
|
|
|
29
|
+
If `.design/projects/` does not exist: output "No GSP project found. Run `/gsp-start` to begin." and stop.
|
|
30
|
+
|
|
29
31
|
Resolve project from `.design/projects/` (one → use it, multiple → ask). Set `PROJECT_PATH`.
|
|
30
32
|
|
|
31
33
|
Read `{PROJECT_PATH}/brand.ref` → set `BRAND_PATH`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsp-project-design
|
|
3
|
-
description: Design screens and interaction flows (creative phase — benefits from capable models)
|
|
3
|
+
description: Design screens and interaction flows (creative phase — benefits from capable models) — use when: design this, mock up, create wireframes, how should X look, lay out the UI for
|
|
4
4
|
user-invocable: true
|
|
5
5
|
context: fork
|
|
6
6
|
allowed-tools:
|
|
@@ -32,6 +32,8 @@ Design core UI/UX screens and interaction flows.
|
|
|
32
32
|
<process>
|
|
33
33
|
## Step 0: Resolve project and brand
|
|
34
34
|
|
|
35
|
+
If `.design/projects/` does not exist: output "No GSP project found. Run `/gsp-start` to begin." and stop.
|
|
36
|
+
|
|
35
37
|
Resolve project from `.design/projects/` (one → use it, multiple → ask). Set `PROJECT_PATH`.
|
|
36
38
|
|
|
37
39
|
Read `{PROJECT_PATH}/brand.ref` → set `BRAND_PATH`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsp-project-research
|
|
3
|
-
description: Research UX patterns and technical approaches
|
|
3
|
+
description: Research UX patterns and technical approaches — use when: research this, look up how X works, find patterns for, what's the best approach for
|
|
4
4
|
user-invocable: true
|
|
5
5
|
allowed-tools:
|
|
6
6
|
- Read
|
|
@@ -35,6 +35,8 @@ Deep research into UX patterns, competitor experiences, and technical approaches
|
|
|
35
35
|
<process>
|
|
36
36
|
## Step 0: Resolve project and brand
|
|
37
37
|
|
|
38
|
+
If `.design/projects/` does not exist: output "No GSP project found. Run `/gsp-start` to begin." and stop.
|
|
39
|
+
|
|
38
40
|
Resolve project from `.design/projects/` (one → use it, multiple → ask). Set `PROJECT_PATH`.
|
|
39
41
|
|
|
40
42
|
Read `{PROJECT_PATH}/brand.ref` → set `BRAND_PATH`.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: gsp-project-review
|
|
3
|
-
description: QA review — validate implementation against designs
|
|
3
|
+
description: QA review — validate implementation against designs — use when: review the build, QA this, does it match the designs, check what was built, verify implementation
|
|
4
4
|
user-invocable: true
|
|
5
5
|
context: fork
|
|
6
6
|
allowed-tools:
|
|
@@ -32,6 +32,8 @@ QA validate the codebase implementation against design intent.
|
|
|
32
32
|
<process>
|
|
33
33
|
## Step 0: Resolve project and brand
|
|
34
34
|
|
|
35
|
+
If `.design/projects/` does not exist: output "No GSP project found. Run `/gsp-start` to begin." and stop.
|
|
36
|
+
|
|
35
37
|
Resolve project from `.design/projects/` (one → use it, multiple → ask). Set `PROJECT_PATH`.
|
|
36
38
|
|
|
37
39
|
Read `{PROJECT_PATH}/brand.ref` → set `BRAND_PATH`.
|
|
@@ -133,6 +135,13 @@ Update `{PROJECT_PATH}/STATE.md`:
|
|
|
133
135
|
- If Pass or Conditional Pass: Set Prettiness Level to 100%
|
|
134
136
|
- Update `## Screen Build Status` table — set Review Status per screen based on acceptance-report.md findings
|
|
135
137
|
|
|
138
|
+
If Pass or Conditional Pass, update `.design/CLAUDE.md` — replace the existing `### {project-name}` entry (written by gsp-project-brief when started) with the completed entry:
|
|
139
|
+
|
|
140
|
+
```markdown
|
|
141
|
+
### {project-name} · complete · {DATE}
|
|
142
|
+
brand: {brand-name} · .design/projects/{project-name}/
|
|
143
|
+
```
|
|
144
|
+
|
|
136
145
|
### QA loop — if Fail
|
|
137
146
|
|
|
138
147
|
If verdict is **Fail**:
|