@hegemonart/get-design-done 1.36.3 → 1.37.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.
- package/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +43 -0
- package/README.md +8 -0
- package/SKILL.md +1 -0
- package/agents/design-component-generator.md +30 -2
- package/agents/ds-generator.md +74 -0
- package/connections/builder-io.md +131 -0
- package/connections/connections.md +13 -1
- package/connections/framer.md +126 -0
- package/connections/penpot.md +148 -0
- package/connections/plasmic.md +112 -0
- package/connections/v0-dev.md +100 -0
- package/connections/webflow.md +107 -0
- package/package.json +1 -1
- package/reference/ds-bootstrap-rubric.md +51 -0
- package/reference/registry.json +7 -0
- package/scripts/lib/ds/token-scale.cjs +88 -0
- package/skills/bootstrap-ds/SKILL.md +43 -0
- package/skills/connections/SKILL.md +4 -4
- package/skills/connections/connections-onboarding.md +58 -4
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Penpot — Connection Specification
|
|
2
|
+
|
|
3
|
+
This file is the connection specification for **Penpot** within the get-design-done pipeline. Penpot is an open-source, self-hostable design and prototyping platform — an AI-native (Wave 2) alternative to Figma. It is a **canvas-category** tool: GDD reads boards and components, exports tokens, and writes design proposals back. See `connections/connections.md` for the full connection index and capability matrix, and `connections/figma.md` for the sibling canvas-category connection.
|
|
4
|
+
|
|
5
|
+
GDD connects to **your** Penpot instance. It does **not** install, bundle, or host Penpot — there is no bundled dependency. You bring a running Penpot (self-hosted or cloud) plus an access token.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Setup
|
|
10
|
+
|
|
11
|
+
### Prerequisites
|
|
12
|
+
|
|
13
|
+
- **A Penpot instance.** One of two deployment shapes:
|
|
14
|
+
- **Cloud** — the hosted service at [penpot.app](https://penpot.app). Base URL is `https://design.penpot.app`. No infrastructure to run.
|
|
15
|
+
- **Self-hosted** — a Penpot deployment you operate (Docker/Kubernetes), reachable at your own origin, e.g. `https://penpot.internal.example.com`. See [help.penpot.app](https://help.penpot.app) for deployment guidance.
|
|
16
|
+
- **An access token.** Generated from your Penpot profile under **Settings → Access tokens**. Tokens are scoped to your account on whichever instance issued them — a cloud token does not authenticate against a self-hosted instance, and vice versa.
|
|
17
|
+
- **One access path** — either:
|
|
18
|
+
- the **Penpot REST API / plugin** reached over `PENPOT_BASE_URL` + token (the env path), or
|
|
19
|
+
- a **Penpot MCP server** registered in the session (the MCP path).
|
|
20
|
+
|
|
21
|
+
### Configuration
|
|
22
|
+
|
|
23
|
+
The pipeline supports two interchangeable access paths. You only need one; if both are present, the probe resolves precedence (see **Probe Pattern**).
|
|
24
|
+
|
|
25
|
+
**Env path (REST API / plugin).** Set two environment variables:
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
export PENPOT_BASE_URL="https://design.penpot.app" # cloud
|
|
29
|
+
# or, self-hosted:
|
|
30
|
+
export PENPOT_BASE_URL="https://penpot.internal.example.com"
|
|
31
|
+
export PENPOT_ACCESS_TOKEN="<your-penpot-access-token>"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
`PENPOT_BASE_URL` is the **distinguishing signal** between cloud and self-hosted. The pipeline records the host so downstream stages know which deployment they are talking to.
|
|
35
|
+
|
|
36
|
+
**MCP path.** Register a Penpot MCP server in Claude Code settings (`mcpServers.penpot`), passing `PENPOT_BASE_URL` and `PENPOT_ACCESS_TOKEN` through the server's `env`. Restart the session after install.
|
|
37
|
+
|
|
38
|
+
### Verification
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
ToolSearch({ query: "penpot", max_results: 5 })
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
A non-empty result confirms the MCP path. For the env path, a `200` from `GET $PENPOT_BASE_URL/api/rpc/command/get-profile` (header `Authorization: Token $PENPOT_ACCESS_TOKEN`) confirms the credentials resolve. If the env path is unset and `ToolSearch` is empty, Penpot is `not_configured`.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Probe Pattern
|
|
49
|
+
|
|
50
|
+
Penpot exposes **two independent access paths**, and the probe checks **both** before resolving. This is the load-bearing distinction for this connection (SC#2): the env path additionally carries the **self-hosted-vs-cloud** signal, which downstream stages need.
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
Step 1 — Env probe (self-hosted vs cloud):
|
|
54
|
+
Read PENPOT_BASE_URL and PENPOT_ACCESS_TOKEN from the environment.
|
|
55
|
+
Both set → env path present.
|
|
56
|
+
Classify deployment from the host of PENPOT_BASE_URL:
|
|
57
|
+
host == design.penpot.app → deployment=cloud
|
|
58
|
+
any other host → deployment=self-hosted
|
|
59
|
+
Either unset → env path absent.
|
|
60
|
+
|
|
61
|
+
Step 2 — MCP probe:
|
|
62
|
+
ToolSearch({ query: "penpot", max_results: 5 })
|
|
63
|
+
Non-empty → MCP path present (record resolved prefix mcp__<name>__).
|
|
64
|
+
Empty → MCP path absent.
|
|
65
|
+
|
|
66
|
+
Step 3 — Resolve which is present:
|
|
67
|
+
env + MCP → available (path=mcp, deployment=<cloud|self-hosted>) # prefer MCP for tool calls; keep deployment from env
|
|
68
|
+
MCP only → available (path=mcp, deployment=unknown) # deployment not derivable without PENPOT_BASE_URL
|
|
69
|
+
env only → available (path=api, deployment=<cloud|self-hosted>)
|
|
70
|
+
neither → not_configured
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
Write the result to `.design/STATE.md` `<connections>` immediately after probing, using the **three-value schema** below:
|
|
74
|
+
|
|
75
|
+
```xml
|
|
76
|
+
<connections>
|
|
77
|
+
penpot: available (path=mcp, deployment=self-hosted)
|
|
78
|
+
figma: not_configured
|
|
79
|
+
</connections>
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Other valid values: `penpot: available (path=api, deployment=cloud)`, `penpot: available (path=mcp, deployment=unknown)`, `penpot: not_configured`.
|
|
83
|
+
|
|
84
|
+
| Field | Values | Meaning |
|
|
85
|
+
|-------|--------|---------|
|
|
86
|
+
| status | `available` / `not_configured` | At least one access path resolved, or none did |
|
|
87
|
+
| `path` | `mcp` / `api` | Which access path the stage should use for tool/REST calls |
|
|
88
|
+
| `deployment` | `cloud` / `self-hosted` / `unknown` | Derived from `PENPOT_BASE_URL` host; `unknown` when only the MCP path is present and no base URL is exported |
|
|
89
|
+
|
|
90
|
+
Consumers MUST read `path` to decide whether to call MCP tools (`mcp__<prefix>__*`) or REST endpoints, and SHOULD surface `deployment` when an operation differs by host (e.g. rate limits or shared-library scope on cloud vs self-hosted).
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## Penpot Tools
|
|
95
|
+
|
|
96
|
+
Tools are described generically — the concrete tool names depend on the resolved `path` (MCP tool names `mcp__<prefix>__<tool>`, or REST commands under `$PENPOT_BASE_URL/api/...`). All capabilities below exist on both cloud and self-hosted instances.
|
|
97
|
+
|
|
98
|
+
| Capability | Stage | Purpose |
|
|
99
|
+
|------------|-------|---------|
|
|
100
|
+
| **List/read boards** | design | Enumerate projects, files, and boards (frames); read the node tree, names, and layout of a selected board |
|
|
101
|
+
| **Read components** | design | Resolve components and component instances from the file's component library; read variants and overrides |
|
|
102
|
+
| **Export tokens** | scan + discover | Read design tokens (color, spacing, typography) and library assets; Penpot's token format is W3C-style design tokens, so values export cleanly into DESIGN.md |
|
|
103
|
+
| **Read prototype/flows** | design (secondary) | Inspect interactions and flows between boards for reference |
|
|
104
|
+
| **Write proposals** | design (write) | Create or annotate boards/frames with proposed design changes; attach comments carrying D-XX decisions onto the relevant boards |
|
|
105
|
+
|
|
106
|
+
Reads are the default. Writes are gated behind the same **proposal → confirm** UX used by the Figma connection (see `connections/figma.md`): the agent builds a numbered operation list and presents it before any write executes. No automatic insertion into the user's Penpot file.
|
|
107
|
+
|
|
108
|
+
---
|
|
109
|
+
|
|
110
|
+
## Pipeline Integration
|
|
111
|
+
|
|
112
|
+
Penpot is a **canvas-category** connection. It feeds the **design** stage like Figma and paper.design — the same slot in the pipeline, a different backing tool.
|
|
113
|
+
|
|
114
|
+
| Stage | What Penpot provides |
|
|
115
|
+
|-------|----------------------|
|
|
116
|
+
| scan | **Token augmentation**: export Penpot design tokens to supplement grep-based CSS token extraction. DESIGN.md notes `source: penpot-tokens` |
|
|
117
|
+
| discover | **Decisions pre-population**: pre-fill D-XX color/spacing/typography decisions from exported tokens before the interview |
|
|
118
|
+
| design | **Board/component reads** for design context; **write proposals** (boards, frames, comments) via the proposal→confirm path when `path` resolves |
|
|
119
|
+
| plan | Not used |
|
|
120
|
+
| verify | Not used |
|
|
121
|
+
|
|
122
|
+
When multiple canvas-category connections are `available` (e.g. both `figma` and `penpot`), the design stage uses whichever the active design source points to; it does not merge them. The user's source-of-truth selection decides.
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## Fallback Behavior
|
|
127
|
+
|
|
128
|
+
When `penpot` is `not_configured`, stages **degrade to code-only** — Penpot is an enhancement, never a requirement, and a missing connection **never blocks** the pipeline.
|
|
129
|
+
|
|
130
|
+
**scan stage:**
|
|
131
|
+
|
|
132
|
+
- Skip Penpot token export.
|
|
133
|
+
- Rely on grep-based CSS custom property extraction alone.
|
|
134
|
+
- DESIGN.md token section uses `source: CSS custom properties` (not `source: penpot-tokens`).
|
|
135
|
+
|
|
136
|
+
**discover stage:**
|
|
137
|
+
|
|
138
|
+
- Skip token pre-population.
|
|
139
|
+
- Populate D-XX decisions via interview only (manual elicitation from the user).
|
|
140
|
+
|
|
141
|
+
**design stage:**
|
|
142
|
+
|
|
143
|
+
- `penpot: not_configured` → skip the write-proposal offer entirely (no prompt, no output).
|
|
144
|
+
- `penpot: available` → offer the opt-in proposal prompt after the design step completes.
|
|
145
|
+
|
|
146
|
+
Stages do not append a `<blocker>` for a missing Penpot connection. Only if a `must_have` explicitly requires Penpot data (reads or writes) does a stage append a blocker. Always re-probe at stage entry — both the access `path` and the resolved MCP prefix can change between sessions.
|
|
147
|
+
|
|
148
|
+
Do NOT edit the connection index here — the 37.1 wiring plan adds the Active-Connections row + matrix entry.
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Plasmic — Connection Specification
|
|
2
|
+
|
|
3
|
+
This file is the connection specification for Plasmic within the get-design-done pipeline. Plasmic is a **dual-category** tool: it is both a **visual canvas** (a hosted design/builder surface whose pages and components can be read as a design source, like Figma) **and** a **code generator** (it emits real component code via its codegen loader/API). Because of this, Plasmic earns entries in **both** the `canvas` column **and** the `generator` column of the capability matrix. It integrates via the Plasmic MCP (preferred) or via a project token + loader/codegen API. See `connections/connections.md` for the full connection index and capability matrix.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
|
|
11
|
+
**Path A — Plasmic MCP (preferred):**
|
|
12
|
+
- The Plasmic MCP enabled in your Claude environment
|
|
13
|
+
- A Plasmic project (the design lives at [plasmic.app](https://plasmic.app))
|
|
14
|
+
- No additional manual setup when the MCP is present
|
|
15
|
+
|
|
16
|
+
**Path B — Token + loader/codegen API fallback:**
|
|
17
|
+
- A Plasmic account and a project at [plasmic.app](https://plasmic.app)
|
|
18
|
+
- A project ID + API token (project tokens, found in the project's Code/Configure panel)
|
|
19
|
+
- `PLASMIC_PROJECT_ID` and `PLASMIC_API_TOKEN` environment variables set
|
|
20
|
+
- Loader/codegen access per the docs at [docs.plasmic.app](https://docs.plasmic.app)
|
|
21
|
+
|
|
22
|
+
### Verification
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
ToolSearch({ query: "plasmic", max_results: 5 })
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Non-empty results (canvas-read + codegen tools) → Plasmic MCP available (Path A).
|
|
29
|
+
Empty → check `PLASMIC_PROJECT_ID` / `PLASMIC_API_TOKEN` and use Path B, then restart the Claude Code session.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Probe Pattern
|
|
34
|
+
|
|
35
|
+
Plasmic uses an MCP-first, two-path probe. Check the MCP first; fall back to the token env path.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
ToolSearch({ query: "plasmic", max_results: 5 })
|
|
39
|
+
→ Non-empty → plasmic: available (mcp)
|
|
40
|
+
→ Empty → check PLASMIC_PROJECT_ID + PLASMIC_API_TOKEN env vars
|
|
41
|
+
both set → plasmic: available (token)
|
|
42
|
+
either unset → plasmic: not_configured
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Write the three-value result to `.design/STATE.md` `<connections>`: `plasmic: <status>`
|
|
46
|
+
where `<status>` ∈ { `available (mcp)`, `available (token)`, `not_configured` }.
|
|
47
|
+
|
|
48
|
+
Because Plasmic is dual-category, a single `available` status enables **both** roles at once — the canvas read **and** the generator emit. The pipeline decides which role to invoke per stage (see Pipeline Integration); the probe does not split the status.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Plasmic Tools
|
|
53
|
+
|
|
54
|
+
Plasmic exposes tools spanning **both** capability columns. Describe them generically — exact tool names resolve at probe time via `ToolSearch`.
|
|
55
|
+
|
|
56
|
+
| Tool (generic) | Column | Stage | Purpose |
|
|
57
|
+
|----------------|--------|-------|---------|
|
|
58
|
+
| `plasmic_list_projects` / `plasmic_get_project` | canvas | canvas | Enumerate Plasmic projects and read project/page/component metadata |
|
|
59
|
+
| `plasmic_read_component` / `plasmic_get_design` | canvas | canvas | Read a page or component from the visual canvas as a design source (structure, props, tokens) |
|
|
60
|
+
| `plasmic_get_tokens` | canvas | canvas | Extract design tokens (color, spacing, typography) defined in the Plasmic project |
|
|
61
|
+
| `plasmic_generate_code` / `plasmic_emit_component` | generator | generator | Emit real component code for a canvas component (codegen / loader) |
|
|
62
|
+
| `plasmic_sync` | generator | generator | Sync/regenerate emitted code after canvas changes (roundtrip) |
|
|
63
|
+
|
|
64
|
+
Token-path equivalents: the loader/codegen API at [docs.plasmic.app](https://docs.plasmic.app) provides the same two roles — read the project (canvas) and pull generated component code (generator) — when the MCP is absent.
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
## Pipeline Integration
|
|
69
|
+
|
|
70
|
+
Plasmic plugs into **two distinct stages**, one per capability column. This is the explicit dual-column behavior (SC#5): the same connection is a design **source** at the canvas stage and a code **emitter** at the generator stage.
|
|
71
|
+
|
|
72
|
+
| Stage | Column | What Plasmic provides |
|
|
73
|
+
|-------|--------|-----------------------|
|
|
74
|
+
| canvas | canvas | **Read the Plasmic design as a source** — pages, components, and tokens, the same way Figma is read. Feeds DESIGN.md and `.design/STATE.md` `<design_system>` token blocks. |
|
|
75
|
+
| generator | generator | **Emit component code** — via `agents/design-component-generator.md`'s `<!-- impl: plasmic -->` section. Returns component source the generator stage writes into the project. |
|
|
76
|
+
|
|
77
|
+
### Canvas stage — design as source
|
|
78
|
+
|
|
79
|
+
When `plasmic: available`, the canvas stage may treat a Plasmic project as a first-class design source (peer to Figma):
|
|
80
|
+
|
|
81
|
+
1. `plasmic_list_projects` → resolve the target project (or read `PLASMIC_PROJECT_ID`).
|
|
82
|
+
2. `plasmic_read_component` / `plasmic_get_design` → pull the page/component structure into the design read.
|
|
83
|
+
3. `plasmic_get_tokens` → extract tokens into `.design/STATE.md` `<design_system>` for downstream generator targeting.
|
|
84
|
+
|
|
85
|
+
This is a **read** — no code is emitted at this stage. The canvas read is what later stages reason about.
|
|
86
|
+
|
|
87
|
+
### Generator stage — emit code
|
|
88
|
+
|
|
89
|
+
The generator stage delegates to `agents/design-component-generator.md`. That agent's `<!-- impl: plasmic -->` section calls the Plasmic codegen path:
|
|
90
|
+
|
|
91
|
+
1. The agent resolves the canvas component to emit (from the canvas-stage read).
|
|
92
|
+
2. It calls `plasmic_generate_code` / `plasmic_emit_component` (or the loader/codegen API on the token path).
|
|
93
|
+
3. The emitted source is surfaced as a **proposal**, not auto-inserted.
|
|
94
|
+
|
|
95
|
+
### Proposal → Confirm
|
|
96
|
+
|
|
97
|
+
Both roles are non-destructive. The canvas read is informational; the generator emit is a **proposal**. The design-executor surfaces the proposed component code to the user/executor, who confirms before any code is written into the project. No automatic insertion, no automatic overwrite of existing components.
|
|
98
|
+
|
|
99
|
+
---
|
|
100
|
+
|
|
101
|
+
## Fallback Behavior
|
|
102
|
+
|
|
103
|
+
When `plasmic: not_configured`:
|
|
104
|
+
- Print: `Plasmic not configured — canvas read and code emit skipped.`
|
|
105
|
+
- **Canvas role** degrades gracefully: the canvas stage falls back to other available design sources (e.g. Figma); Plasmic is simply not offered as a source.
|
|
106
|
+
- **Generator role** degrades to code-only: the generator stage falls back to other available generators (Magic Patterns if `magic-patterns: available`, then 21st.dev if `21st-dev: available` — see `connections/21st-dev.md`), and finally to a manual component build.
|
|
107
|
+
|
|
108
|
+
Plasmic is **additive and never blocks**: with neither role configured, the pipeline proceeds on its existing canvas source and existing generators exactly as before.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
Do NOT edit the connection index here — the 37.1 wiring plan adds the Active-Connections row + matrix entries (canvas + generator).
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
# v0.dev — Connection Specification
|
|
2
|
+
|
|
3
|
+
This file is the connection specification for v0.dev within the get-design-done pipeline. v0.dev is Vercel's generative-UI tool (AI-native, Wave 2): prompt in, React/Tailwind/shadcn component code out. It is a **generator-category** connection — same family as [21st.dev](21st-dev.md) and [Magic Patterns](magic-patterns.md) — and plugs into the shared component-generator agent as a new implementation (Phase 14 pattern). See `connections/connections.md` for the full connection index and capability matrix.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
|
|
11
|
+
**Path A — MCP (preferred):**
|
|
12
|
+
- A v0.dev MCP server reachable from your Claude environment (probe surfaces the tools).
|
|
13
|
+
- No additional setup once the server is registered and the session is restarted.
|
|
14
|
+
|
|
15
|
+
**Path B — REST + API key (fallback, phase default):**
|
|
16
|
+
- A v0.dev account and API key from [v0.dev](https://v0.dev) (Vercel's **v0 Platform API**).
|
|
17
|
+
- `V0_API_KEY` environment variable set.
|
|
18
|
+
- Calls hit the v0 Platform API over HTTPS; no local server required.
|
|
19
|
+
|
|
20
|
+
Per the phase default, **probe MCP first, then fall back to REST + `V0_API_KEY`**. The Platform API is the stable contract; MCP tool names may evolve, so treat MCP as the fast path and the key as the durable one.
|
|
21
|
+
|
|
22
|
+
### Verification
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
ToolSearch({ query: "v0", max_results: 5 })
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Non-empty results including a v0 generate tool → MCP available (Path A).
|
|
29
|
+
Empty → check `V0_API_KEY`; if set, Path B is active. If unset, v0.dev is not configured.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Probe Pattern
|
|
34
|
+
|
|
35
|
+
v0.dev uses a two-path probe — MCP-first, then API key.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
ToolSearch({ query: "v0", max_results: 5 })
|
|
39
|
+
→ Non-empty → v0: available (mcp)
|
|
40
|
+
→ Empty → check V0_API_KEY env var
|
|
41
|
+
set → v0: available (api)
|
|
42
|
+
unset → v0: not_configured
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
This resolves to a **three-value** status. Write the result to `.design/STATE.md` `<connections>`:
|
|
46
|
+
|
|
47
|
+
```
|
|
48
|
+
v0: <not_configured | available (mcp) | available (api)>
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The generator stage reads this value to decide whether the v0 implementation path is selectable.
|
|
52
|
+
|
|
53
|
+
---
|
|
54
|
+
|
|
55
|
+
## v0.dev Tools / API
|
|
56
|
+
|
|
57
|
+
v0.dev contributes a single core capability at the generator stage: **generate a component from a prompt plus design-system context**. Exact tool/endpoint names are not pinned here — verify them at runtime via the probe (MCP) or the current Platform API docs (REST).
|
|
58
|
+
|
|
59
|
+
| Capability | Stage | Purpose |
|
|
60
|
+
|------------|-------|---------|
|
|
61
|
+
| generate component | generator | Prompt + DS context → React/Tailwind/shadcn source; returns `{ code, preview_url }` (shape verified at runtime) |
|
|
62
|
+
| iterate / refine | generator | Follow-up prompt against a prior generation to refine output before any write |
|
|
63
|
+
|
|
64
|
+
**MCP path:** call the discovered generate tool with the DS-aware prompt; read code + preview from its response.
|
|
65
|
+
**REST path:** POST the prompt to the v0 Platform API generate endpoint with `Authorization: Bearer ${V0_API_KEY}`; parse code + preview from the JSON response.
|
|
66
|
+
|
|
67
|
+
Both paths return generated source plus (typically) a hosted preview URL. Field names differ by transport — resolve them at runtime, do not hardcode against this table.
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
## Pipeline Integration
|
|
72
|
+
|
|
73
|
+
v0.dev is **generator-category**: it contributes at the **generator** stage only, as one implementation inside the shared generator agent. The agent's `<!-- impl: v0 -->` section in `agents/design-component-generator.md` holds the v0-specific prompt assembly and response handling.
|
|
74
|
+
|
|
75
|
+
| Stage | What v0.dev provides |
|
|
76
|
+
|-------|----------------------|
|
|
77
|
+
| generator | Prompt + DS context → component source via the `<!-- impl: v0 -->` path in `agents/design-component-generator.md` |
|
|
78
|
+
| generator | `preview_url` (when returned) written to `.design/STATE.md` `<generator>` block for the verify stage |
|
|
79
|
+
|
|
80
|
+
### DS-Aware Prompting
|
|
81
|
+
|
|
82
|
+
Before invoking v0.dev, the generator reads the detected design system from `.design/STATE.md` `<design_system>` (populated upstream — see [Magic Patterns](magic-patterns.md) for the shared DS-detection logic). The `<!-- impl: v0 -->` section folds that context into the prompt: target framework (React), styling (Tailwind), and component library (shadcn/ui when present), plus any token or convention notes. v0.dev is shadcn-native, so a shadcn target maps cleanly; other systems are passed as explicit prompt constraints.
|
|
83
|
+
|
|
84
|
+
### Proposal → Confirm
|
|
85
|
+
|
|
86
|
+
v0.dev output is **proposed, never auto-written**. The generator surfaces the generated code (and preview, if any) as a proposal; the executor confirms with the user before anything lands in `src/`. This matches the prior-art and proposal gates used by the sibling generator implementations — no automatic code insertion.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
## Fallback Behavior
|
|
91
|
+
|
|
92
|
+
When `v0: not_configured`:
|
|
93
|
+
- Print: `v0.dev not configured — generator impl skipped.`
|
|
94
|
+
- Falls back to another generator implementation if available: [21st.dev](21st-dev.md) or [Magic Patterns](magic-patterns.md).
|
|
95
|
+
- If no generator is configured, the generator stage proceeds with a code-only manual build.
|
|
96
|
+
- v0.dev **never blocks** the pipeline — it degrades to a sibling generator or to manual code, and the stage continues either way.
|
|
97
|
+
|
|
98
|
+
---
|
|
99
|
+
|
|
100
|
+
Do NOT edit the connection index here — the 37.1 wiring plan adds the Active-Connections row + matrix entry.
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
# Webflow — Connection Specification
|
|
2
|
+
|
|
3
|
+
This file is the connection specification for Webflow within the get-design-done (GDD) pipeline. Webflow is an AI-native Wave 2 generator-category, code-capable canvas: GDD reads a Webflow site's structure and styles and uses them as a **design-adaptation source** — it reads the site's existing design language and emits it as a source for adaptation. GDD does **not** author Webflow CMS schemas, publish content, or write back to the site. See `connections/21st-dev.md` for the structural template this spec follows, and `connections/connections.md` for the full connection index and capability matrix.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Setup
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
|
|
11
|
+
You need a Webflow site to read from, plus one read path:
|
|
12
|
+
|
|
13
|
+
**Path A — Webflow MCP (preferred):**
|
|
14
|
+
- The Webflow MCP server registered in your Claude environment (exposes the Webflow Data API as tools).
|
|
15
|
+
- No additional env setup required once the connector is enabled.
|
|
16
|
+
|
|
17
|
+
**Path B — API token fallback:**
|
|
18
|
+
- A Webflow account with at least one site, at [webflow.com](https://webflow.com).
|
|
19
|
+
- A Data API token (Site settings → Apps & integrations → API access) scoped read-only.
|
|
20
|
+
- `WEBFLOW_API_TOKEN` environment variable set, used against the Data API at [developers.webflow.com](https://developers.webflow.com).
|
|
21
|
+
|
|
22
|
+
### Verification
|
|
23
|
+
|
|
24
|
+
```
|
|
25
|
+
ToolSearch({ query: "webflow", max_results: 5 })
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Non-empty results (e.g. a site-list / pages / styles read tool) → Webflow MCP available (Path A).
|
|
29
|
+
Empty → check `WEBFLOW_API_TOKEN` and fall back to direct Data API reads (Path B), then restart the Claude Code session if you just registered the connector.
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## Probe Pattern
|
|
34
|
+
|
|
35
|
+
Webflow uses an MCP-first probe with an API-token env fallback. Resolve to one of three values and write it to `.design/STATE.md` `<connections>`.
|
|
36
|
+
|
|
37
|
+
```
|
|
38
|
+
ToolSearch({ query: "webflow", max_results: 5 })
|
|
39
|
+
→ Non-empty → webflow: available (MCP path)
|
|
40
|
+
→ Empty → check WEBFLOW_API_TOKEN env var
|
|
41
|
+
set → webflow: available (API-token path)
|
|
42
|
+
unset → webflow: not_configured
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
A separate `unavailable` status is reserved for the case where the MCP tool is present in the session but errors on probe (auth failure, site offline, rate-limited) — treat it the same as `not_configured` for gating (skip Webflow steps), but record it distinctly.
|
|
46
|
+
|
|
47
|
+
Three-value status schema (mirrors `connections/connections.md`):
|
|
48
|
+
|
|
49
|
+
| Status | Meaning |
|
|
50
|
+
|--------|---------|
|
|
51
|
+
| `available` | Webflow read path confirmed (MCP tool responsive, or `WEBFLOW_API_TOKEN` set) |
|
|
52
|
+
| `unavailable` | MCP tool present but errored on probe (auth/site/rate-limit) |
|
|
53
|
+
| `not_configured` | No MCP tool and no API token — Webflow not wired in this session |
|
|
54
|
+
|
|
55
|
+
Write result to STATE.md `<connections>`: `webflow: <status>`
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Webflow Tools
|
|
60
|
+
|
|
61
|
+
Tools are described generically — exact names depend on the registered MCP server (Path A) or are equivalent Data API read calls (Path B). All are **read-only** in GDD's usage.
|
|
62
|
+
|
|
63
|
+
| Tool (generic) | Stage | Purpose |
|
|
64
|
+
|----------------|-------|---------|
|
|
65
|
+
| read site structure | design | Enumerate the site's pages and DOM/element hierarchy — the structural skeleton of the existing design |
|
|
66
|
+
| read styles | design | Read style classes, typography, color, spacing, and breakpoint definitions — the site's existing design language |
|
|
67
|
+
| read components | design | Read reusable components / symbols and their composition, for pattern adaptation |
|
|
68
|
+
|
|
69
|
+
These reads supply raw material for adaptation. GDD never calls a Webflow write/publish/CMS-mutation tool, even when the registered MCP server exposes one.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Pipeline Integration
|
|
74
|
+
|
|
75
|
+
Webflow is a **generator-category** connection that contributes at the **design** stage as a structure/adaptation source.
|
|
76
|
+
|
|
77
|
+
| Stage | What Webflow provides |
|
|
78
|
+
|-------|------------------------|
|
|
79
|
+
| design | **Adaptation source**: read the existing site's structure, styles, and components; emit the design language as a source the design stage adapts from |
|
|
80
|
+
|
|
81
|
+
### Adaptation-source flow (design stage)
|
|
82
|
+
|
|
83
|
+
1. Probe resolves `webflow: available`.
|
|
84
|
+
2. Read site structure + styles (+ components) via the available path.
|
|
85
|
+
3. Emit the extracted design language as an **adaptation source** for the design stage — structure and style become reference material the generator adapts, alongside other sources (e.g. the project design system, 21st.dev prior art).
|
|
86
|
+
4. The design-executor produces GDD-native output (code / DESIGN.md) informed by that source. Nothing is written back to Webflow.
|
|
87
|
+
|
|
88
|
+
This is a **read-and-adapt** integration, not a round trip. The Webflow site is treated as inspiration and structural reference; GDD owns the emitted output.
|
|
89
|
+
|
|
90
|
+
### Explicitly out of scope
|
|
91
|
+
|
|
92
|
+
- GDD reads structure; it does **not** author or mutate Webflow **CMS schemas** (collections, fields, items). It is a design-adaptation source, not a CMS authoring tool.
|
|
93
|
+
- No publishing, no content writes, no site mutations of any kind.
|
|
94
|
+
|
|
95
|
+
---
|
|
96
|
+
|
|
97
|
+
## Fallback Behavior
|
|
98
|
+
|
|
99
|
+
When `webflow: not_configured` (or `unavailable`):
|
|
100
|
+
|
|
101
|
+
- Print: `Webflow not configured — adaptation source skipped, proceeding code-only.`
|
|
102
|
+
- The design stage **degrades to code-only**: it proceeds from the project design system and any other available sources without the Webflow design language.
|
|
103
|
+
- Webflow never blocks the pipeline. A missing Webflow connection only removes one optional adaptation source; the design stage continues normally.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
Do NOT edit the connection index here — the 37.1 wiring plan adds the Active-Connections row + matrix entry.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hegemonart/get-design-done",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.37.2",
|
|
4
4
|
"description": "A design-quality pipeline for AI coding agents: brief, plan, implement, and verify UI work against your design system.",
|
|
5
5
|
"author": "Hegemon",
|
|
6
6
|
"homepage": "https://github.com/hegemonart/get-design-done",
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Greenfield Design-System Bootstrap Rubric
|
|
2
|
+
|
|
3
|
+
Emission rules for `/gdd:bootstrap-ds` + `agents/ds-generator.md` — how to turn a brand input (a primary color + optional secondary + tone tags + target framework) into a coherent token system, **without inventing a brand**. The deterministic math lives in `scripts/lib/ds/token-scale.cjs`; the color-theory grounding lives in `reference/color-theory.md`. This file is the rulebook the generator obeys.
|
|
4
|
+
|
|
5
|
+
GDD does not author a brand identity (logomarks, voice) — it emits a **starter token system + a few proof components** a greenfield project can build on.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Color
|
|
10
|
+
|
|
11
|
+
- **Primary → 9 tints/shades.** Convert the brand primary to OKLCH `{l, c, h}`, then call `oklchScale(primary)` → 9 stops (`100`…`900`) emitted as native CSS `oklch()`. Stop `500` is the primary exactly; lighter stops interpolate L toward white with damped chroma; darker stops toward black. Native `oklch()` — **no hex conversion, no color library**.
|
|
12
|
+
- **Never auto-generate more than 2 brand colors.** Primary is always emitted. A **secondary** scale is emitted **only if the user supplies one**. Never invent a third brand hue.
|
|
13
|
+
- **Neutrals** — a low-chroma gray ramp (chroma ≤ 0.02) sharing the primary's hue for a subtle tint, or pure neutral (`c = 0`). 9 stops via `oklchScale({ l, c: 0.012, h: primary.h })`.
|
|
14
|
+
- **Semantic colors** — success / warning / danger / info derived at fixed hues (≈145 / 85 / 25 / 255) at the brand's mid-lightness + chroma, so they sit in the same family. These are functional, not "brand" colors (they do not count against the ≤2 rule).
|
|
15
|
+
- **Contrast** — every text-on-surface pairing must clear WCAG AA (see `reference/color-theory.md`); the generator checks the chosen `500`/`700` against white/`50`.
|
|
16
|
+
|
|
17
|
+
## Typography
|
|
18
|
+
|
|
19
|
+
- **Modular scale** via `typeScale(baseRem, ratio, steps)`. Base `1rem` (16px). **Ratio ∈ {1.2 (minor third), 1.25 (major third), 1.333 (perfect fourth)}** — pick by tone (calm → 1.2, default → 1.25, editorial/bold → 1.333).
|
|
20
|
+
- Emit named steps (`xs`…`5xl`) from the scale; line-height pairs (tight 1.2 for headings, 1.5 for body).
|
|
21
|
+
- Font family is a **slot**, not a choice — emit a system-font stack placeholder + a `--font-sans` / `--font-mono` variable the user swaps. GDD does not pick a typeface (brand territory).
|
|
22
|
+
|
|
23
|
+
## Spacing
|
|
24
|
+
|
|
25
|
+
- **4pt or 8pt baseline** via `spacingScale(basePx, count)` (8pt is the default; 4pt for dense/data UIs). Emit the standard `[1,2,3,4,6,8,12,16]` multiples as `--space-*`.
|
|
26
|
+
|
|
27
|
+
## Radius + Motion
|
|
28
|
+
|
|
29
|
+
- **Radius** via `radiusScale(basePx)` → `sm/md/lg/xl/full` (`full = 9999` pill).
|
|
30
|
+
- **Motion defaults** — durations `fast 150ms / base 250ms / slow 400ms`; easing `ease-out` for enters, a standard curve for moves; **always** respect `prefers-reduced-motion` (emit the media-query guard).
|
|
31
|
+
|
|
32
|
+
## The 3 variants (D-02 — user picks one)
|
|
33
|
+
|
|
34
|
+
The generator emits three coherent variants; the user picks ONE before first-component scaffolding:
|
|
35
|
+
|
|
36
|
+
| Variant | Chroma | Type ratio | Spacing | Radius | Feel |
|
|
37
|
+
|---|---|---|---|---|---|
|
|
38
|
+
| **conservative** | damped (×0.8) | 1.2 | 8pt | sm (4) | calm, corporate, dense-friendly |
|
|
39
|
+
| **balanced** (default) | as given | 1.25 | 8pt | md (8) | versatile default |
|
|
40
|
+
| **bold** | boosted (×1.15, clamped) | 1.333 | 8pt | lg (12) | expressive, marketing-forward |
|
|
41
|
+
|
|
42
|
+
## Emission format
|
|
43
|
+
|
|
44
|
+
- Emit **CSS custom properties** (`:root { --color-primary-500: oklch(...); --space-4: 16px; ... }`) as the canonical artifact, plus a target-framework mapping:
|
|
45
|
+
- **web (default)** — a Tailwind `theme.extend` block (or shadcn CSS variables) + the `:root` tokens.
|
|
46
|
+
- **native** — route the token set through `reference/native-platforms.md` (Phase 34) for SwiftUI / Compose / Flutter theme objects.
|
|
47
|
+
- Tokens are **named by role, not value** (`--color-primary-500`, not `--blue-500`) so a rebrand is a one-line hue change.
|
|
48
|
+
|
|
49
|
+
## First-component scaffolding (proof artifact)
|
|
50
|
+
|
|
51
|
+
After the user picks a variant, emit **button + input + card** in the detected target framework, consuming only the emitted tokens — a proof the system is coherent, not a full component library (that is out of scope).
|
package/reference/registry.json
CHANGED
|
@@ -972,6 +972,13 @@
|
|
|
972
972
|
"type": "heuristic",
|
|
973
973
|
"phase": 36.3,
|
|
974
974
|
"description": "Phase 36.3 Tier-3 conversational-UI patterns (voice + chatbot): voice-flow no-input/no-match reprompts + confirmation + human handoff, multi-turn dialogue (context carryover, slot-filling, repair), prompt-as-UX (the assistant persona/tone/boundaries as a versioned design artifact), chatbot empty-states + suggested replies, voice-first onboarding, error recovery + accessibility (transcripts/captions). Carries Detection signals + an Audit checklist; loaded by design-context-builder for the conversational project type. CLI/REPL UX out of scope."
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
"name": "ds-bootstrap-rubric",
|
|
978
|
+
"path": "reference/ds-bootstrap-rubric.md",
|
|
979
|
+
"type": "heuristic",
|
|
980
|
+
"phase": 37.2,
|
|
981
|
+
"description": "Phase 37.2 greenfield DS emission rules for /gdd:bootstrap-ds + agents/ds-generator.md: primary→9 OKLCH tints (native oklch(), no color library), never >2 brand colors, neutrals + semantic colors, modular type scale (ratio 1.2/1.25/1.333), 4pt/8pt spacing, radius + motion defaults, the 3 variants (conservative/balanced/bold), role-named CSS-custom-property emission + framework mapping, and button/input/card proof scaffolding. Deterministic math in scripts/lib/ds/token-scale.cjs."
|
|
975
982
|
}
|
|
976
983
|
]
|
|
977
984
|
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* scripts/lib/ds/token-scale.cjs — Phase 37.2 greenfield token-scale generator.
|
|
4
|
+
*
|
|
5
|
+
* Pure + dep-free (D-01): zero `require`, no color-conversion library. Emits native CSS
|
|
6
|
+
* `oklch(L C H)` strings — modern browsers render OKLCH directly, so no OKLab→sRGB→hex
|
|
7
|
+
* conversion is needed. Deterministic: same input → byte-identical output (hermetic tests).
|
|
8
|
+
*
|
|
9
|
+
* - oklchScale(primary, opts?) → 9 tint/shade stops {stop, oklch}, anchored at the primary,
|
|
10
|
+
* interpolating lightness toward white/black and damping chroma at the extremes.
|
|
11
|
+
* - typeScale(baseRem, ratio, steps?) → a modular type scale {step, rem}.
|
|
12
|
+
* - spacingScale(basePx, count?) → a 4pt/8pt geometric spacing scale (px).
|
|
13
|
+
* - radiusScale(basePx?) → sm/md/lg/xl/full radii (px / 9999 for full).
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
const round = (n, d) => {
|
|
17
|
+
const f = Math.pow(10, d);
|
|
18
|
+
return Math.round(n * f) / f;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const DEFAULT_STOPS = [100, 200, 300, 400, 500, 600, 700, 800, 900];
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* oklchScale({ l, c, h }, opts) — l ∈ 0..1 (lightness), c ∈ 0..~0.4 (chroma), h ∈ 0..360 (hue).
|
|
25
|
+
* Anchors the `anchorStop` (default 500) at the primary, then interpolates L toward `lLight`
|
|
26
|
+
* for lighter stops and `lDark` for darker stops, damping chroma toward the extremes.
|
|
27
|
+
*/
|
|
28
|
+
function oklchScale(primary, opts = {}) {
|
|
29
|
+
const { l, c, h } = primary || {};
|
|
30
|
+
if (typeof l !== 'number' || typeof c !== 'number' || typeof h !== 'number') {
|
|
31
|
+
throw new TypeError('oklchScale: primary must be { l:number, c:number, h:number }');
|
|
32
|
+
}
|
|
33
|
+
const stops = opts.stops || DEFAULT_STOPS;
|
|
34
|
+
const anchor = opts.anchorStop || 500;
|
|
35
|
+
const lLight = opts.lLight != null ? opts.lLight : 0.97;
|
|
36
|
+
const lDark = opts.lDark != null ? opts.lDark : 0.22;
|
|
37
|
+
const i500 = stops.indexOf(anchor) === -1 ? Math.floor(stops.length / 2) : stops.indexOf(anchor);
|
|
38
|
+
|
|
39
|
+
return stops.map((stop, i) => {
|
|
40
|
+
let L;
|
|
41
|
+
let C;
|
|
42
|
+
if (i === i500) {
|
|
43
|
+
L = l; C = c;
|
|
44
|
+
} else if (i < i500) {
|
|
45
|
+
const t = (i500 - i) / i500; // 0..1 toward the lightest stop
|
|
46
|
+
L = l + (lLight - l) * t;
|
|
47
|
+
C = c * (1 - 0.75 * t); // damp chroma toward white
|
|
48
|
+
} else {
|
|
49
|
+
const t = (i - i500) / (stops.length - 1 - i500); // 0..1 toward the darkest stop
|
|
50
|
+
L = l + (lDark - l) * t;
|
|
51
|
+
C = c * (1 - 0.45 * t); // damp chroma toward black (less than toward white)
|
|
52
|
+
}
|
|
53
|
+
return { stop, oklch: `oklch(${round(L, 3)} ${round(Math.max(C, 0), 4)} ${round(h, 2)})` };
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* typeScale(baseRem, ratio, steps) — a modular scale. Returns `steps.length` entries,
|
|
59
|
+
* each `{ step, rem }` with rem = baseRem * ratio^step (step 0 = base). Default steps -1..5.
|
|
60
|
+
*/
|
|
61
|
+
function typeScale(baseRem = 1, ratio = 1.25, steps = [-1, 0, 1, 2, 3, 4, 5]) {
|
|
62
|
+
if (!(baseRem > 0) || !(ratio > 1)) throw new TypeError('typeScale: baseRem > 0 and ratio > 1 required');
|
|
63
|
+
return steps.map((step) => ({ step, rem: round(baseRem * Math.pow(ratio, step), 3) }));
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* spacingScale(basePx, count) — a geometric spacing scale off a 4pt/8pt baseline.
|
|
68
|
+
* Returns `count` entries `{ step, px }` following the standard [1,2,3,4,6,8,12,16,...] multiples.
|
|
69
|
+
*/
|
|
70
|
+
function spacingScale(basePx = 4, count = 8) {
|
|
71
|
+
if (![4, 8].includes(basePx)) throw new RangeError('spacingScale: basePx must be 4 or 8 (a 4pt/8pt baseline)');
|
|
72
|
+
const mult = [1, 2, 3, 4, 6, 8, 12, 16, 24, 32];
|
|
73
|
+
return mult.slice(0, count).map((m, i) => ({ step: i + 1, px: basePx * m }));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/** radiusScale(basePx) — sm/md/lg/xl/full. full = 9999 (pill). */
|
|
77
|
+
function radiusScale(basePx = 8) {
|
|
78
|
+
if (!(basePx > 0)) throw new TypeError('radiusScale: basePx > 0 required');
|
|
79
|
+
return {
|
|
80
|
+
sm: round(basePx / 2, 2),
|
|
81
|
+
md: basePx,
|
|
82
|
+
lg: basePx * 2,
|
|
83
|
+
xl: basePx * 3,
|
|
84
|
+
full: 9999,
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
module.exports = { oklchScale, typeScale, spacingScale, radiusScale, DEFAULT_STOPS };
|