diff --git a/AGENTS.md b/AGENTS.md index 3328994..8f5cc0a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -4,7 +4,7 @@ Guidance for Claude Code, Cursor, Copilot, Codex CLI, and other AI agents workin ## What this repo is -A collection of Claude Code **skills** — 35 packaged instructions and scripts that extend AI agents with Stitch-specific capabilities: text-to-UI generation, design iteration (edit, variants, design systems), design token extraction, and multi-framework conversion. Think of it as a Stitch co-pilot that wraps 13 of the 15 Stitch MCP tools and knows the footguns so you don't have to learn them the hard way. +A collection of Claude Code **skills** — 36 packaged instructions and scripts that extend AI agents with Stitch-specific capabilities: text-to-UI generation, design iteration (edit, variants, design systems), design token extraction, and multi-framework conversion. Think of it as a Stitch co-pilot that wraps all 15 Stitch MCP tools and knows the footguns so you don't have to learn them the hard way. ## Skill structure @@ -15,7 +15,7 @@ skills/{skill-name}/ ├── SKILL.md ← Required: activation instructions and workflow ├── examples/ ← Required: worked examples (gold-standard reference) ├── resources/ ← Optional: templates, checklists, mapping tables -├── scripts/ ← Optional: bash scripts (fetch-stitch.sh, encode-image.sh, etc.) +├── scripts/ ← Optional: bash scripts (fetch-stitch.sh, init_stitch_skill.py, etc.) └── references/ ← Optional: style guides, contracts ``` @@ -88,7 +88,7 @@ For Stitch-based UI generation, load **`stitch-orchestrator`** or invoke the **` | Layer | Count | Purpose | |-------|-------|---------| | **Brain** (`stitch-ui-*`, `stitch-ideate`) | 5 | Design intelligence — ideation agent, specs, prompts, variants, UED guide | -| **Hands** (`stitch-mcp-*`) | 13 | MCP wrappers — one per Stitch API tool, handles ID format rules | +| **Hands** (`stitch-mcp-*`) | 15 | MCP wrappers — one per Stitch API tool, handles ID format rules | | **Conversion** | 7+ | Stitch HTML → framework components (Next.js, Svelte, React, HTML, RN, SwiftUI, shadcn) | | **Quality** | 3 | Design tokens, accessibility audit, animations | @@ -98,7 +98,7 @@ Skills marked `allowed-tools: ["stitch*:*"]` require the **Stitch MCP Server** c Setup guide: https://stitch.withgoogle.com/docs/mcp/setup -13 of the 15 Stitch MCP tools wrapped: `create_project`, `get_project`, `delete_project`, `list_projects`, `generate_screen_from_text`, `edit_screens`, `generate_variants`, `list_screens`, `get_screen`, `create_design_system`, `update_design_system`, `list_design_systems`, `apply_design_system` +All 15 Stitch MCP tools wrapped: `create_project`, `get_project`, `delete_project`, `list_projects`, `generate_screen_from_text`, `edit_screens`, `generate_variants`, `list_screens`, `get_screen`, `create_design_system`, `update_design_system`, `list_design_systems`, `apply_design_system`, `upload_design_md`, `create_design_system_from_design_md` Without MCP: the orchestrator falls back to prompt-only mode (generates ready-to-copy Stitch prompts instead of running the full workflow — still useful, just slower). @@ -113,6 +113,8 @@ Without MCP: the orchestrator falls back to prompt-only mode (generates ready-to | `stitch-mcp-edit-screens` | Edit existing screens with text prompts (iteration) | | `stitch-mcp-generate-variants` | Generate design alternatives with creativity controls | | `stitch-mcp-create-design-system` | Create reusable Stitch Design Systems | +| `stitch-mcp-upload-design-md` | Upload a DESIGN.md into a project (pairs with the next row) | +| `stitch-mcp-create-design-system-from-design-md` | Turn an uploaded DESIGN.md into a design system | | `stitch-mcp-apply-design-system` | Apply design systems to screens | | `stitch-mcp-get-screen` | Retrieve screen HTML + screenshot by ID | | `stitch-design-system` | Extract design tokens → CSS + Tailwind files | @@ -131,7 +133,7 @@ Without MCP: the orchestrator falls back to prompt-only mode (generates ready-to See [`docs/`](docs/) for: - `skills-index.md` — complete skills table with descriptions and layers -- `mcp-schemas/` — JSON Schema for the 13 Stitch MCP tools this repo wraps +- `mcp-schemas/` — JSON Schema for all 15 Stitch MCP tools - `color-prompt-guide.md` — 8 ready-to-use color palette prompts for Stitch - `tailwind-reference.md` — Tailwind utility class reference for conversions - `mcp-naming-convention.md` — MCP tool name → skill name mapping diff --git a/README.md b/README.md index 1777b6d..777ba2c 100644 --- a/README.md +++ b/README.md @@ -152,7 +152,9 @@ Without stitch-kit, your agent sends Stitch a half-baked prompt, gets confused b ## Ship to any framework -**Works on any HTML, not just Stitch output.** Each conversion skill takes a Stitch screen, a local HTML file, or a URL — point it at a template you bought, a page you already built, or something a different tool generated, and you get the same production components with dark mode, design tokens, TypeScript, and ARIA. Only the Stitch route needs an API key. +**Works on any HTML, not just Stitch output.** Each conversion skill takes a Stitch screen, a local HTML file, or a URL — point it at a template you bought, a page you already built, or something a different tool generated. Only the Stitch route needs an API key. + +Every target gets dark mode and design tokens. The rest depends on where you're shipping: TypeScript and ARIA on the web targets, Swift and native accessibility APIs on SwiftUI, plain semantic HTML with no build step on the HTML target. Pick your target: diff --git a/agents/stitch-kit.md b/agents/stitch-kit.md index 3493d76..ca07bfa 100644 --- a/agents/stitch-kit.md +++ b/agents/stitch-kit.md @@ -14,6 +14,7 @@ You are a Stitch design-to-code specialist. You handle the full pipeline from UI - Edit existing screens with text prompts (edit_screens) — iterate without regenerating - Generate design variants with configurable creativity and aspect controls (generate_variants) - Create, update, list, and apply Stitch Design Systems for cross-screen consistency +- Turn a DESIGN.md into a Stitch Design System (upload_design_md, then create_design_system_from_design_md — always both) - Convert Stitch HTML to Next.js 15 App Router, Svelte 5, Vite+React, HTML5, React Native/Expo, or SwiftUI - Extract design tokens → CSS custom properties (light + dark mode) - Build multi-page sites iteratively with the stitch-loop baton pattern @@ -69,9 +70,11 @@ Stitch uses inconsistent ID formats across tools. Use the `stitch-mcp-*` wrapper | `edit_screens` | Numeric | Numeric array | — | | `generate_variants` | Numeric | Numeric array | — | | `create_design_system` | Numeric (optional) | — | Returns Asset `name` | +| `upload_design_md` | Numeric | — | Body is base64; `base64 -i` on macOS | +| `create_design_system_from_design_md` | Numeric | Screen **instance** id + full `sourceScreen` path | Instance id is not the source screen id | | `update_design_system` | — | — | Asset `name` required | | `list_design_systems` | Numeric (optional) | — | Returns Asset names | -| `apply_design_system` | Numeric | Numeric array | `assetId` required | +| `apply_design_system` | Numeric | Screen **instances** (`{id, sourceScreen}`), not bare ids | `assetId` bare numeric, no `assets/` prefix | ## Framework selection guide diff --git a/bin/stitch-kit.mjs b/bin/stitch-kit.mjs index f7e678b..fb94e78 100644 --- a/bin/stitch-kit.mjs +++ b/bin/stitch-kit.mjs @@ -55,12 +55,27 @@ function logErr(msg) { console.error(` ✗ ${msg}`); } /** * Prompt the user for input via stdin. + * + * Resolves to an empty string whenever there's nobody to answer — no TTY, or + * stdin hits EOF. Callers treat empty as "skipped", which is what we want in + * CI, Docker, and `npx ... < /dev/null`: carry on with the rest of the install + * rather than hanging. + * * @param {string} question - The question to display - * @returns {Promise} The user's input (trimmed) + * @returns {Promise} The user's input (trimmed), or '' if unanswerable */ function prompt(question) { + // Non-interactive stdin: readline would wait forever for input that can't + // arrive. Skip straight to the default instead. + if (!process.stdin.isTTY) return Promise.resolve(''); + const rl = createInterface({ input: process.stdin, output: process.stdout }); return new Promise((resolve) => { + // `close` fires on EOF (ctrl-D, or a pipe closing). Without this the + // question callback never runs, the promise never settles, and node exits + // mid-install with "Detected unsettled top-level await" — an install that + // silently did nothing. + rl.on('close', () => resolve('')); rl.question(question, (answer) => { rl.close(); resolve(answer.trim()); diff --git a/docs/mcp-schemas/README.md b/docs/mcp-schemas/README.md index 1cde600..44f40f6 100644 --- a/docs/mcp-schemas/README.md +++ b/docs/mcp-schemas/README.md @@ -1,6 +1,6 @@ # Stitch MCP API Schemas -Formal JSON Schema definitions for the 13 Stitch MCP tools this repo wraps. +Formal JSON Schema definitions for the 15 Stitch MCP tools this repo wraps. Each file documents the full `arguments` (input) and `outputSchema` (output) for one tool. @@ -34,7 +34,9 @@ Each file documents the full `arguments` (input) and `outputSchema` (output) for | `create_design_system.json` | `create_design_system` | Create a reusable design system. Optional numeric `projectId`. | | `update_design_system.json` | `update_design_system` | Update an existing design system. Requires asset `name`. | | `list_design_systems.json` | `list_design_systems` | List available design systems. Optional numeric `projectId`. | -| `apply_design_system.json` | `apply_design_system` | Apply a design system to screens. **Numeric IDs** + `assetId`. | +| `apply_design_system.json` | `apply_design_system` | Apply a design system to screens. Screen **instances** (`{id, sourceScreen}`) + bare `assetId`. | +| `upload_design_md.json` | `upload_design_md` | Upload a DESIGN.md into a project. Numeric `projectId`, base64 body. | +| `create_design_system_from_design_md.json` | `create_design_system_from_design_md` | Turn an uploaded DESIGN.md into a design system. Numeric `projectId` + screen instance. | --- @@ -154,8 +156,10 @@ Useful for: targeted HTML extraction, component-level conversion, design audits. | `list_screens` | `projects/NUMERIC` | — | — | | `get_screen` | **NUMERIC only** | **NUMERIC only** | — | | `create_design_system` | **NUMERIC** (optional) | — | Returns Asset `name` | -| `update_design_system` | — | — | Asset `name` required | +| `update_design_system` | — | — | Asset `name` (prefixed) required | | `list_design_systems` | **NUMERIC** (optional) | — | Returns Asset names | -| `apply_design_system` | **NUMERIC only** | **NUMERIC array** | `assetId` required | +| `apply_design_system` | **NUMERIC only** | Screen **instances** (`{id, sourceScreen}`) | `assetId` bare numeric, no prefix | +| `upload_design_md` | **NUMERIC only** | — | Body is base64 | +| `create_design_system_from_design_md` | **NUMERIC only** | Screen **instance** (`{id, sourceScreen}`) | — | See `../mcp-naming-convention.md` for the full breakdown. diff --git a/docs/mcp-schemas/apply_design_system.json b/docs/mcp-schemas/apply_design_system.json index 90e65d5..d33a7f1 100644 --- a/docs/mcp-schemas/apply_design_system.json +++ b/docs/mcp-schemas/apply_design_system.json @@ -1,6 +1,6 @@ { "name": "apply_design_system", - "description": "Applies a Stitch Design System to one or more existing screens, updating their visual theme.\n\n**Input Requirements (CRITICAL):**\n1. **`projectId` (string - MANDATORY):** Numeric ID only.\n2. **`selectedScreenIds` (array - MANDATORY):** Numeric screen IDs.\n3. **`assetId` (string - MANDATORY):** Design system asset identifier.\n", + "description": "Applies a Stitch Design System to one or more existing screens, updating their visual theme.\n\n**Input Requirements (CRITICAL):**\n1. **`projectId` (string - MANDATORY):** Numeric ID only, no `projects/` prefix.\n2. **`selectedScreenInstances` (array of objects - MANDATORY):** Screen INSTANCES, each `{id, sourceScreen}`. NOT an array of bare screen ids. `id` is the screen instance id (from get_project's screenInstances), NOT the source screen id; `sourceScreen` is the full `projects/{p}/screens/{s}` path.\n3. **`assetId` (string - MANDATORY):** Bare numeric asset id, WITHOUT the `assets/` prefix.\n", "arguments": { "type": "object", "properties": { @@ -8,17 +8,23 @@ "description": "Required. Numeric project ID only — do NOT include 'projects/' prefix.", "type": "string" }, - "selectedScreenIds": { - "description": "Required. Array of numeric screen IDs to apply the design system to.", - "type": "array", - "items": { "type": "string" } - }, "assetId": { - "description": "Required. The design system asset identifier from list or create operations.", + "description": "Required. The asset id of the design system to apply, can be fetched from `list_design_systems`. Example: '15996705518239280238', without the `assets/` prefix.", "type": "string" + }, + "selectedScreenInstances": { + "description": "Required. The screen instances to edit, which is available in the Project info, fetched by `get_project`. NOT bare screen ids.", + "type": "array", + "items": { + "$ref": "#/$defs/SelectedScreenInstance" + } } }, - "required": ["projectId", "selectedScreenIds", "assetId"], + "required": [ + "projectId", + "selectedScreenInstances", + "assetId" + ], "description": "Request message for ApplyDesignSystem." }, "outputSchema": { @@ -28,9 +34,33 @@ "description": "Array of output components with updated screen data.", "type": "array" }, - "projectId": { "type": "string" }, - "sessionId": { "type": "string" } + "projectId": { + "type": "string" + }, + "sessionId": { + "type": "string" + } }, "description": "Response message for ApplyDesignSystem." + }, + "$defs": { + "SelectedScreenInstance": { + "type": "object", + "description": "A screen instance to be edited by the agent, selected by the user.", + "properties": { + "id": { + "description": "Required. The id of the screen instance, NOT the source screen id. Available in screenInstances from `get_project`.", + "type": "string" + }, + "sourceScreen": { + "description": "Required. The resource name of the source screen. Format: projects/{project}/screens/{screen}", + "type": "string" + } + }, + "required": [ + "id", + "sourceScreen" + ] + } } } diff --git a/docs/mcp-schemas/create_design_system.json b/docs/mcp-schemas/create_design_system.json index 31f2762..944a35d 100644 --- a/docs/mcp-schemas/create_design_system.json +++ b/docs/mcp-schemas/create_design_system.json @@ -28,14 +28,6 @@ "theme": { "$ref": "#/$defs/DesignTheme", "description": "Required. Visual theme configuration." - }, - "designTokens": { - "description": "Optional. CSS custom properties or token definitions.", - "type": "string" - }, - "styleGuidelines": { - "description": "Optional. Natural-language design rules.", - "type": "string" } }, "required": [ @@ -71,20 +63,6 @@ "description": "Primary color (hex).", "type": "string" }, - "backgroundLight": { - "description": "Light mode background (hex).", - "type": "string" - }, - "backgroundDark": { - "description": "Dark mode background (hex).", - "type": "string" - }, - "preset": { - "type": "string" - }, - "description": { - "type": "string" - }, "colorVariant": { "enum": [ "COLOR_VARIANT_UNSPECIFIED", @@ -319,15 +297,6 @@ ], "type": "string" }, - "namedColors": { - "type": "object", - "description": "Semantic color map (40+ tokens like primary, on_primary, surface, etc.)" - }, - "spacingScale": { - "format": "int32", - "type": "integer", - "description": "0=minimal, 1=compact, 2=normal, 3=spacious" - }, "designMd": { "type": "string", "description": "Auto-generated markdown design system document" @@ -360,6 +329,13 @@ "description": "Optional. Map of typography level name (e.g. \"h1\", \"body\") to Typography token overrides." } }, + "required": [ + "colorMode", + "headlineFont", + "bodyFont", + "roundness", + "customColor" + ], "type": "object" }, "Typography": { diff --git a/docs/mcp-schemas/create_design_system_from_design_md.json b/docs/mcp-schemas/create_design_system_from_design_md.json index 2b1bf12..ba3dcbb 100644 --- a/docs/mcp-schemas/create_design_system_from_design_md.json +++ b/docs/mcp-schemas/create_design_system_from_design_md.json @@ -24,25 +24,31 @@ ] } }, - "required": ["projectId", "selectedScreenInstance"], - "description": "Request message for CreateDesignSystemFromDesignMd." - }, - "$defs": { - "SelectedScreenInstance": { - "type": "object", - "description": "A screen instance to be edited by the agent, selected by the user.", - "properties": { - "id": { - "description": "Required. The id of the screen instance, NOT the source screen id. This is available in the screen instances in the Project info, fetched by `get_project`.", - "type": "string" + "$defs": { + "SelectedScreenInstance": { + "type": "object", + "description": "A screen instance to be edited by the agent, selected by the user.", + "properties": { + "id": { + "description": "Required. The id of the screen instance, NOT the source screen id. This is available in the screen instances in the Project info, fetched by `get_project`.", + "type": "string" + }, + "sourceScreen": { + "description": "Required. The source screen of the screen instance. The resource name of the source screen. Format: projects/{project}/screens/{screen}", + "type": "string" + } }, - "sourceScreen": { - "description": "Required. The source screen of the screen instance. The resource name of the source screen. Format: projects/{project}/screens/{screen}", - "type": "string" - } - }, - "required": ["id", "sourceScreen"] - } + "required": [ + "id", + "sourceScreen" + ] + } + }, + "required": [ + "projectId", + "selectedScreenInstance" + ], + "description": "Request message for CreateDesignSystemFromDesignMd." }, "outputSchema": { "type": "object", diff --git a/docs/mcp-schemas/generate_screen_from_text.json b/docs/mcp-schemas/generate_screen_from_text.json index 10e8e5e..1c41ffc 100644 --- a/docs/mcp-schemas/generate_screen_from_text.json +++ b/docs/mcp-schemas/generate_screen_from_text.json @@ -32,6 +32,10 @@ "prompt": { "description": "Required. The text prompt describing the screen to generate.", "type": "string" + }, + "designSystem": { + "description": "Optional. The design system id to use for generating the new screen, should always be configured for design consistency. Takes the `assets/` prefix. Example: 'assets/15996705518239280238'.", + "type": "string" } }, "required": ["projectId", "prompt"], diff --git a/docs/mcp-schemas/generate_variants.json b/docs/mcp-schemas/generate_variants.json index 08fa706..9d43a48 100644 --- a/docs/mcp-schemas/generate_variants.json +++ b/docs/mcp-schemas/generate_variants.json @@ -11,7 +11,9 @@ "selectedScreenIds": { "description": "Required. Array of numeric screen IDs to generate variants from.", "type": "array", - "items": { "type": "string" } + "items": { + "type": "string" + } }, "prompt": { "description": "Optional. Guidance text for the variant direction.", @@ -23,16 +25,32 @@ }, "deviceType": { "description": "Optional. Device type context.", - "enum": ["DEVICE_TYPE_UNSPECIFIED", "MOBILE", "DESKTOP", "TABLET", "AGNOSTIC"], + "enum": [ + "DEVICE_TYPE_UNSPECIFIED", + "MOBILE", + "DESKTOP", + "TABLET", + "AGNOSTIC" + ], "type": "string" }, "modelId": { "description": "Optional. GEMINI_3_1_PRO = latest Thinking model. GEMINI_3_PRO = deprecated (use 3_1_PRO). GEMINI_3_FLASH for speed.", - "enum": ["MODEL_ID_UNSPECIFIED", "GEMINI_3_PRO", "GEMINI_3_FLASH", "GEMINI_3_1_PRO"], + "enum": [ + "MODEL_ID_UNSPECIFIED", + "GEMINI_3_PRO", + "GEMINI_3_FLASH", + "GEMINI_3_1_PRO" + ], "type": "string" } }, - "required": ["projectId", "selectedScreenIds"], + "required": [ + "projectId", + "selectedScreenIds", + "prompt", + "variantOptions" + ], "description": "Request message for GenerateVariants.", "$defs": { "VariantOptions": { @@ -46,14 +64,26 @@ }, "creativeRange": { "description": "How much to deviate from the original design.", - "enum": ["CREATIVE_RANGE_UNSPECIFIED", "REFINE", "EXPLORE", "REIMAGINE"], + "enum": [ + "CREATIVE_RANGE_UNSPECIFIED", + "REFINE", + "EXPLORE", + "REIMAGINE" + ], "type": "string" }, "aspects": { "description": "Which design aspects to vary.", "type": "array", "items": { - "enum": ["ASPECT_UNSPECIFIED", "LAYOUT", "COLOR_SCHEME", "IMAGES", "TEXT_FONT", "TEXT_CONTENT"], + "enum": [ + "ASPECT_UNSPECIFIED", + "LAYOUT", + "COLOR_SCHEME", + "IMAGES", + "TEXT_FONT", + "TEXT_CONTENT" + ], "type": "string" } } @@ -69,8 +99,12 @@ "description": "Array of output components with generated variant screens.", "type": "array" }, - "projectId": { "type": "string" }, - "sessionId": { "type": "string" } + "projectId": { + "type": "string" + }, + "sessionId": { + "type": "string" + } }, "description": "Response message for GenerateVariants." } diff --git a/docs/mcp-schemas/get_screen.json b/docs/mcp-schemas/get_screen.json index 5442b97..bec8af9 100644 --- a/docs/mcp-schemas/get_screen.json +++ b/docs/mcp-schemas/get_screen.json @@ -4,16 +4,26 @@ "arguments": { "type": "object", "properties": { - "projectId": { - "description": "Required. Numeric project ID only — do NOT include 'projects/' prefix.", + "name": { + "description": "Required. Identifier. The resource name of the screen to retrieve. Format: `projects/{project}/screens/{screen}` Example: `projects/4044680601076201931/screens/98b50e2ddc9943efb387052637738f61`", "type": "string" }, + "projectId": { + "description": "Required. Numeric project ID only — do NOT include 'projects/' prefix. DEPRECATED — prefer the `name` field.", + "type": "string", + "deprecated": true + }, "screenId": { - "description": "Required. Numeric/hex screen ID — do NOT include path prefix.", - "type": "string" + "description": "Required. Numeric/hex screen ID — do NOT include path prefix. DEPRECATED — prefer the `name` field.", + "type": "string", + "deprecated": true } }, - "required": ["projectId", "screenId"], + "required": [ + "name", + "projectId", + "screenId" + ], "description": "Request message for GetScreen." }, "outputSchema": { @@ -21,10 +31,19 @@ "properties": { "deviceType": { "description": "The device type of the screen.", - "enum": ["DEVICE_TYPE_UNSPECIFIED", "MOBILE", "DESKTOP", "TABLET", "AGNOSTIC"], + "enum": [ + "DEVICE_TYPE_UNSPECIFIED", + "MOBILE", + "DESKTOP", + "TABLET", + "AGNOSTIC" + ], + "type": "string" + }, + "height": { + "description": "Screen height in pixels.", "type": "string" }, - "height": { "description": "Screen height in pixels.", "type": "string" }, "htmlCode": { "$ref": "#/$defs/File", "description": "The HTML code of the screen. Use downloadUrl to fetch the full HTML." @@ -38,8 +57,15 @@ "$ref": "#/$defs/File", "description": "PNG screenshot. Use downloadUrl to download." }, - "title": { "description": "Output only. Generated screen title.", "readOnly": true, "type": "string" }, - "width": { "description": "Screen width in pixels.", "type": "string" } + "title": { + "description": "Output only. Generated screen title.", + "readOnly": true, + "type": "string" + }, + "width": { + "description": "Screen width in pixels.", + "type": "string" + } }, "$defs": { "File": { @@ -65,7 +91,9 @@ "UserFeedback": { "description": "User feedback for a given interaction.", "properties": { - "comment": { "type": "string" }, + "comment": { + "type": "string" + }, "designFeedbackReason": { "enum": [ "DESIGN_FEEDBACK_REASON_UNSPECIFIED", @@ -80,7 +108,11 @@ "type": "string" }, "rating": { - "enum": ["RATING_UNSPECIFIED", "POSITIVE", "NEGATIVE"], + "enum": [ + "RATING_UNSPECIFIED", + "POSITIVE", + "NEGATIVE" + ], "type": "string" } }, diff --git a/docs/mcp-schemas/update_design_system.json b/docs/mcp-schemas/update_design_system.json index 69b4113..3361744 100644 --- a/docs/mcp-schemas/update_design_system.json +++ b/docs/mcp-schemas/update_design_system.json @@ -1,31 +1,54 @@ { "name": "update_design_system", - "description": "Updates an existing Stitch Design System's theme, tokens, or guidelines.\n", + "description": "Updates an existing Stitch Design System's display name and/or theme.\n", "arguments": { "type": "object", "properties": { + "name": { + "description": "Required. Identifier. The resource name of the design system to update. Format: `assets/{asset_id}` — WITH the `assets/` prefix. Example: `assets/15996705518239280238`. Note apply_design_system takes the same id BARE.", + "type": "string" + }, + "projectId": { + "description": "Required. The project ID to update the design system for, example: '4044680601076201931', without the `projects/` prefix.", + "type": "string" + }, "designSystem": { "description": "Required. Asset wrapper with name + updated fields. Full replacement, not merge.", "type": "object", "properties": { - "name": { "description": "Required. Asset name from create or list (e.g., assets/ds_abc123).", "type": "string" }, - "displayName": { "type": "string" }, - "theme": { "description": "Updated DesignTheme object.", "type": "object" }, - "designTokens": { "type": "string" }, - "styleGuidelines": { "type": "string" } + "displayName": { + "type": "string" + }, + "theme": { + "description": "Updated DesignTheme object.", + "type": "object" + } }, - "required": ["name"] + "required": [ + "displayName", + "theme" + ] } }, - "required": ["designSystem"], + "required": [ + "name", + "projectId", + "designSystem" + ], "description": "Request message for UpdateDesignSystem." }, "outputSchema": { "type": "object", "properties": { - "name": { "type": "string" }, - "displayName": { "type": "string" }, - "designSystem": { "type": "object" } + "name": { + "type": "string" + }, + "displayName": { + "type": "string" + }, + "designSystem": { + "type": "object" + } }, "description": "Updated Asset response." } diff --git a/docs/skills-index.md b/docs/skills-index.md index e782b38..89b2d9e 100644 --- a/docs/skills-index.md +++ b/docs/skills-index.md @@ -87,13 +87,16 @@ This is the most common source of bugs when calling Stitch MCP tools directly: | `list_screens` | `projects/NUMERIC_ID` | — | — | | `get_screen` | **Numeric only** | **Numeric only** | — | | `create_design_system` | **Numeric only** (optional) | — | Returns Asset `name` | -| `update_design_system` | — | — | Asset `name` required | +| `update_design_system` | — | — | Asset `name` (prefixed) required | | `list_design_systems` | **Numeric only** (optional) | — | Returns Asset names | -| `apply_design_system` | **Numeric only** | **Numeric array** | `assetId` required | +| `apply_design_system` | **Numeric only** | Screen **instances** (`{id, sourceScreen}`) | `assetId` bare numeric, no prefix | +| `upload_design_md` | **Numeric only** | — | Body is base64 | +| `create_design_system_from_design_md` | **Numeric only** | Screen **instance** (`{id, sourceScreen}`) | — | **Rules of thumb:** - **Read operations** (`get_project`, `list_screens`, `delete_project`) → `projects/ID` full path -- **Generation/mutation** (`generate_screen_from_text`, `edit_screens`, `generate_variants`, `apply_design_system`) → numeric only +- **Generation/mutation** (`generate_screen_from_text`, `edit_screens`, `generate_variants`) → numeric only +- **`apply_design_system`** → numeric `projectId`, but screen **instances** (not bare screenIds) and a bare (unprefixed) `assetId` - **Design system operations** → numeric `projectId` (optional), asset `name` for identity See `mcp-naming-convention.md` for full details. @@ -103,7 +106,7 @@ See `mcp-naming-convention.md` for full details. ## References - `mcp-naming-convention.md` — ID format rules -- `mcp-schemas/` — Formal JSON Schema definitions for the 13 Stitch MCP tools this repo wraps (fonts, roundness, componentRegions, outputComponents, variantOptions, designSystems) +- `mcp-schemas/` — Formal JSON Schema definitions for the 15 Stitch MCP tools this repo wraps (fonts, roundness, componentRegions, outputComponents, variantOptions, designSystems) - `color-prompt-guide.md` — 8 ready-to-use color palettes for Stitch prompts - `tailwind-reference.md` — Tailwind utility class reference for conversions - `prd-to-stitch-workflow.md` — PRD-driven design workflow diff --git a/skills/stitch-html-components/SKILL.md b/skills/stitch-html-components/SKILL.md index 21ae358..af59018 100644 --- a/skills/stitch-html-components/SKILL.md +++ b/skills/stitch-html-components/SKILL.md @@ -10,7 +10,7 @@ allowed-tools: # Stitch → HTML5 + CSS (Platform-Agnostic) -You are a frontend engineer specializing in clean, dependency-free HTML and CSS. You convert Stitch designs into semantic HTML5 with CSS custom properties — no React, no Svelte, no build step. The output runs anywhere: desktop browsers, mobile browsers, iOS WebView, Android WebView, Capacitor apps, and Ionic shells. +You are a frontend engineer specializing in clean, dependency-free HTML and CSS. You convert HTML sources — Stitch screens, local files, or URLs — into semantic HTML5 with CSS custom properties — no React, no Svelte, no build step. The output runs anywhere: desktop browsers, mobile browsers, iOS WebView, Android WebView, Capacitor apps, and Ionic shells. ## When to use this skill @@ -80,13 +80,19 @@ For multi-screen projects, each screen gets its own HTML file. Shared CSS lives ## Step 3: CSS custom properties -Map Stitch colors to semantic tokens. Always generate **both light and dark** at the same time. +Map source colors to semantic tokens. Always generate **both light and dark** at the same time. Resolve the hex values in this order: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** already in the source (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. ```css /* css/tokens.css */ :root { - /* Extract these from the Stitch HTML's tailwind.config in */ --color-background: [hex]; --color-surface: [hex]; --color-primary: [hex]; diff --git a/skills/stitch-mcp-apply-design-system/SKILL.md b/skills/stitch-mcp-apply-design-system/SKILL.md index 9254555..6467d3c 100644 --- a/skills/stitch-mcp-apply-design-system/SKILL.md +++ b/skills/stitch-mcp-apply-design-system/SKILL.md @@ -32,8 +32,13 @@ You must have: "name": "apply_design_system", "arguments": { "projectId": "3780309359108792857", - "selectedScreenIds": ["88805abc123def456", "99906xyz789ghi012"], - "assetId": "ds_abc123" + "selectedScreenInstances": [ + { + "id": "a1b2c3d4e5f6", + "sourceScreen": "projects/3780309359108792857/screens/98b50e2ddc9943efb387052637738f61" + } + ], + "assetId": "15996705518239280238" } } ``` @@ -47,26 +52,34 @@ You must have: ❌ "projects/3780309359108792857" ``` -### `selectedScreenIds` — array of numeric screen IDs +### `selectedScreenInstances` — array of objects, not screen IDs + +This is the one that catches people. It takes screen **instances**, each a `{id, sourceScreen}` pair — not a list of screen ids. ``` -✅ ["88805abc123def456"] -❌ ["projects/123/screens/88805abc123def456"] +✅ [{ "id": "a1b2c3d4e5f6", + "sourceScreen": "projects/3780.../screens/98b5..." }] + +❌ ["88805abc123def456"] ← bare screen ids +❌ [{ "id": "98b50e2ddc99...", ... }] ← source screen id in the id slot ``` -All selected screens will have the design system applied. +Get both values from `get_project` → `screenInstances`. The `id` is the **instance** id; `sourceScreen` is the full `projects/{p}/screens/{s}` path of the screen behind it. They are different values, and swapping them fails. -### `assetId` — the design system identifier +Same shape as `create_design_system_from_design_md`, which takes a single instance rather than an array. -The `name` field from a design system asset, or just the ID portion: +### `assetId` — bare numeric, no prefix ``` -✅ "ds_abc123" +✅ "15996705518239280238" +❌ "assets/15996705518239280238" ``` -Get this from: -- `stitch-mcp-list-design-systems` → extract from the `name` field of each asset -- `stitch-mcp-create-design-system` → returned in the response `name` field +Get it from: +- `stitch-mcp-list-design-systems` → take the `name` field (`assets/15996...`) and **strip the `assets/` prefix** +- `stitch-mcp-create-design-system` → same, strip the prefix from the returned `name` + +> `apply_design_system` wants it bare, but `generate_screen_from_text`'s `designSystem` param wants it **prefixed** (`assets/15996...`). Same identifier, two formats, depending on the tool. ## Output diff --git a/skills/stitch-mcp-create-design-system-from-design-md/SKILL.md b/skills/stitch-mcp-create-design-system-from-design-md/SKILL.md index aa36254..8ed712d 100644 --- a/skills/stitch-mcp-create-design-system-from-design-md/SKILL.md +++ b/skills/stitch-mcp-create-design-system-from-design-md/SKILL.md @@ -61,7 +61,7 @@ Take the newest entry in `screenInstances` and read off both `id` and `sourceScr ## Step 3: Confirm and capture the asset id -On success you get back a design system with an asset id in `assets/NUMERIC_ID` form. Store the numeric part — that's what applying and generating need. +On success you get back a design system with an asset id in `assets/NUMERIC_ID` form. Store both forms: `apply_design_system` wants the bare numeric part, `generate_screen_from_text`'s `designSystem` param wants the full `assets/NUMERIC_ID` string. Announce it: > "Design system created from your DESIGN.md (asset `15996705518239280238`). Want me to apply it to existing screens, or use it for the next generation?" diff --git a/skills/stitch-mcp-create-design-system/SKILL.md b/skills/stitch-mcp-create-design-system/SKILL.md index 53714af..7ecb9ad 100644 --- a/skills/stitch-mcp-create-design-system/SKILL.md +++ b/skills/stitch-mcp-create-design-system/SKILL.md @@ -30,18 +30,13 @@ Creates a new Stitch Design System — a reusable theme configuration that can b "displayName": "SaaS Dashboard Theme", "theme": { "colorMode": "LIGHT", - "font": "DM_SANS", "headlineFont": "DM_SANS", "bodyFont": "DM_SANS", "labelFont": "DM_SANS", "roundness": "ROUND_EIGHT", "customColor": "#6366F1", - "backgroundLight": "#FFFFFF", - "backgroundDark": "#18181B", - "description": "Professional SaaS aesthetic — clean, indigo accent, airy spacing" - }, - "designTokens": "--color-primary: #6366F1;\n--color-bg: #FFFFFF;\n--font-family: 'DM Sans';", - "styleGuidelines": "Use indigo for interactive elements. Gray-50 backgrounds for cards. 8px border radius." + "colorVariant": "TONAL_SPOT" + } }, "projectId": "3780309359108792857" } @@ -56,27 +51,28 @@ Creates a new Stitch Design System — a reusable theme configuration that can b |-------|------|----------|-------------| | `displayName` | string | Yes | Human-readable name for the design system | | `theme` | DesignTheme | Yes | Visual configuration — see below | -| `designTokens` | string | No | CSS custom properties or token definitions | -| `styleGuidelines` | string | No | Natural-language design rules | + +`designTokens` and `styleGuidelines` are **not** accepted — the live API has no such fields on `DesignSystemInput`. Don't send them. ### `theme` (DesignTheme) — the visual configuration +Required: `colorMode`, `headlineFont`, `bodyFont`, `roundness`, `customColor`. + | Field | Type | Values | Description | |-------|------|--------|-------------| | `colorMode` | enum | `LIGHT`, `DARK` | Base appearance mode | -| `font` | enum | See font list below | **Deprecated** — sets all three font roles. Use the specific fields below instead | | `headlineFont` | enum | See font list below | Typeface for headings and titles | | `bodyFont` | enum | See font list below | Typeface for body text and paragraphs | -| `labelFont` | enum | See font list below | Typeface for labels, captions, and UI chrome | +| `labelFont` | enum | See font list below | Optional. Typeface for labels, captions, and UI chrome | | `roundness` | enum | `ROUND_FOUR`, `ROUND_EIGHT`, `ROUND_TWELVE`, `ROUND_FULL` (`ROUND_TWO` also exists but is deprecated/unused) | Border radius scale | | `customColor` | string | Hex color | Primary brand color | -| `backgroundLight` | string | Hex color | Light mode background | -| `backgroundDark` | string | Hex color | Dark mode background | -| `preset` | string | — | Optional preset theme name | -| `description` | string | — | Brief aesthetic description | -| `overridePrimaryColor` / `overrideSecondaryColor` / `overrideTertiaryColor` / `overrideNeutralColor` | string | Hex color | Exact color overrides, take precedence over `customColor` | -| `spacing` | object | Map of name → CSS value | e.g. `{"sm": "8px"}` | -| `typography` | object | Map of level name → Typography token | Each token: `fontFamily`, `fontSize`, `fontWeight`, `letterSpacing`, `lineHeight` | +| `colorVariant` | enum | `MONOCHROME`, `NEUTRAL`, `TONAL_SPOT`, `VIBRANT`, `EXPRESSIVE`, `FIDELITY`, `CONTENT`, `RAINBOW`, `FRUIT_SALAD` | Optional. Palette generation strategy from `customColor` | +| `designMd` | string | — | Optional. Design system markdown document | +| `overridePrimaryColor` / `overrideSecondaryColor` / `overrideTertiaryColor` / `overrideNeutralColor` | string | Hex color | Optional. Exact color overrides, take precedence over `customColor` | +| `spacing` | object | Map of name → CSS value | Optional. e.g. `{"sm": "8px"}` | +| `typography` | object | Map of level name → Typography token | Optional. Each token: `fontFamily`, `fontSize`, `fontWeight`, `letterSpacing`, `lineHeight` | + +`font` (the deprecated singular font field), `backgroundLight`, `backgroundDark`, `preset`, and `description` are **not** accepted as input — they only ever appear in API *responses* (`get_project`, `list_projects`, etc.), never in what you send here. ### Available fonts (68 options) @@ -106,18 +102,19 @@ When creating from extracted `design-tokens.css`: | CSS Variable | → DesignTheme field | |---|---| | `--color-primary` | `customColor` | -| `--color-bg` or `--bg-light` | `backgroundLight` | -| `--bg-dark` | `backgroundDark` | -| `--font-family` | `font` (map to closest enum value) | +| `--font-family` (headings) | `headlineFont` (map to closest enum value) | +| `--font-family` (body) | `bodyFont` (map to closest enum value) | | `--radius` or `--border-radius` | `roundness` (4px→FOUR, 8px→EIGHT, 12px→TWELVE, 16px+→FULL) | +There's no input field for exact background hex values — `backgroundLight`/`backgroundDark` are response-only. Light/dark backgrounds come from `colorMode` plus the palette Stitch derives from `customColor` and `colorVariant`; use `overridePrimaryColor` etc. if you need to pin a specific palette slot instead. + ## Output Returns an Asset object with a `name` field — **store this** for future `update_design_system` and `apply_design_system` calls: ```json { - "name": "assets/ds_abc123", + "name": "assets/15996705518239280238", "displayName": "SaaS Dashboard Theme", "designSystem": { ... } } @@ -125,6 +122,9 @@ Returns an Asset object with a `name` field — **store this** for future `updat ## After creating -- Store the `name` value (e.g., `assets/ds_abc123`) — you'll need it for apply/update +- Store the `name` value (e.g., `assets/15996705518239280238`). It's used two different ways: + - `update_design_system`'s `designSystem.name` — pass it as-is, with the `assets/` prefix + - `apply_design_system`'s `assetId` — strip the prefix, pass the bare numeric id + - `generate_screen_from_text`'s `designSystem` param — pass it as-is, with the prefix - Offer: "Apply this design system to existing screens?" → `stitch-mcp-apply-design-system` - The orchestrator stores this for automatic application in Step 5b diff --git a/skills/stitch-mcp-create-project/SKILL.md b/skills/stitch-mcp-create-project/SKILL.md index 68bbb47..6c546e9 100644 --- a/skills/stitch-mcp-create-project/SKILL.md +++ b/skills/stitch-mcp-create-project/SKILL.md @@ -63,9 +63,9 @@ The tool returns a `name` field in the format `projects/NUMERIC_ID`. You must ex "colorVariant": "TONAL_SPOT", "roundness": "ROUND_TWELVE", "spacingScale": 1, - "headlineFont": "ROBOTO", - "bodyFont": "ROBOTO", - "labelFont": "ROBOTO", + "headlineFont": "INTER", + "bodyFont": "INTER", + "labelFont": "INTER", "namedColors": {}, "designMd": "" } diff --git a/skills/stitch-mcp-generate-screen-from-text/SKILL.md b/skills/stitch-mcp-generate-screen-from-text/SKILL.md index d1df6e3..818e310 100644 --- a/skills/stitch-mcp-generate-screen-from-text/SKILL.md +++ b/skills/stitch-mcp-generate-screen-from-text/SKILL.md @@ -32,13 +32,23 @@ You must have a `projectId` before calling this. If you don't have one: "projectId": "3780309359108792857", "prompt": "[Full structured prompt — see below]", "deviceType": "MOBILE", - "modelId": "GEMINI_3_1_PRO" + "modelId": "GEMINI_3_1_PRO", + "designSystem": "assets/15996705518239280238" } } ``` ## Parameter reference +### `designSystem` — optional, PREFIXED asset id + +``` +✅ "assets/15996705518239280238" +❌ "15996705518239280238" +``` + +This is how you get design consistency across generated screens — pass the `name` of a design system from `stitch-mcp-create-design-system`, `stitch-mcp-create-design-system-from-design-md`, or `stitch-mcp-list-design-systems` (used as-is, with the `assets/` prefix). This is the opposite format from `apply_design_system`'s `assetId`, which wants the prefix stripped. + ### `projectId` — numeric ID only, no `projects/` prefix ``` ✅ "3780309359108792857" diff --git a/skills/stitch-mcp-get-screen/SKILL.md b/skills/stitch-mcp-get-screen/SKILL.md index 52444ff..94850ec 100644 --- a/skills/stitch-mcp-get-screen/SKILL.md +++ b/skills/stitch-mcp-get-screen/SKILL.md @@ -36,26 +36,34 @@ The user may provide the screen reference in different formats: ## Step 2: Call the MCP tool -**Important: Both IDs must be numeric — no `projects/` or `screens/` prefix.** +`get_screen` is mid-migration: `name` is the current identifier and takes the **full resource path**, while `projectId` and `screenId` are marked deprecated but are still required. Send all three. ```json { "name": "get_screen", "arguments": { + "name": "projects/3780309359108792857/screens/88805abc123def456", "projectId": "3780309359108792857", "screenId": "88805abc123def456" } } ``` +The prefix rule differs per field, which is the whole reason this wrapper exists: + ``` +✅ name: "projects/3780309359108792857/screens/88805abc123def456" +❌ name: "88805abc123def456" + ✅ projectId: "3780309359108792857" ❌ projectId: "projects/3780309359108792857" -✅ screenId: "88805abc123def456" -❌ screenId: "screens/88805abc123def456" +✅ screenId: "88805abc123def456" +❌ screenId: "screens/88805abc123def456" ``` +> `name` is the full path; the other two are bare. Omitting `name` fails — it's required despite the deprecated pair still being mandatory too. + ## Output schema ```json diff --git a/skills/stitch-mcp-list-design-systems/SKILL.md b/skills/stitch-mcp-list-design-systems/SKILL.md index 2c84d0b..974717c 100644 --- a/skills/stitch-mcp-list-design-systems/SKILL.md +++ b/skills/stitch-mcp-list-design-systems/SKILL.md @@ -48,7 +48,7 @@ Returns an array of Asset objects: { "assets": [ { - "name": "assets/ds_abc123", + "name": "assets/15996705518239280238", "displayName": "SaaS Dashboard Theme", "designSystem": { "theme": { @@ -58,9 +58,7 @@ Returns an array of Asset objects: "customColor": "#6366F1", "backgroundLight": "#FFFFFF", "backgroundDark": "#18181B" - }, - "designTokens": "...", - "styleGuidelines": "..." + } } } ] @@ -73,11 +71,13 @@ Present as a readable table: | # | Name | Font | Color | Mode | Asset ID | |---|------|------|-------|------|----------| -| 1 | SaaS Dashboard Theme | DM Sans | #6366F1 | Light | `ds_abc123` | +| 1 | SaaS Dashboard Theme | DM Sans | #6366F1 | Light | `15996705518239280238` | Then offer: - "Apply one of these to a screen?" → `stitch-mcp-apply-design-system` - "Update an existing design system?" → `stitch-mcp-update-design-system` - "Create a new design system?" → `stitch-mcp-create-design-system` -Extract the `name` field from each asset — this is the `assetId` needed for `apply_design_system`. +Extract the `name` field from each asset (`assets/15996...`). It's used two different ways depending on the next call: +- `apply_design_system`'s `assetId` — strip the `assets/` prefix, pass the bare numeric id +- `update_design_system`'s `designSystem.name` — pass `name` as returned, with the prefix diff --git a/skills/stitch-mcp-update-design-system/SKILL.md b/skills/stitch-mcp-update-design-system/SKILL.md index 8ecbdab..42a13cc 100644 --- a/skills/stitch-mcp-update-design-system/SKILL.md +++ b/skills/stitch-mcp-update-design-system/SKILL.md @@ -29,22 +29,18 @@ You must have the design system's asset `name` before calling this. If you don't { "name": "update_design_system", "arguments": { + "name": "assets/15996705518239280238", + "projectId": "3780309359108792857", "designSystem": { - "name": "assets/ds_abc123", "displayName": "SaaS Dashboard Theme v2", "theme": { "colorMode": "DARK", - "font": "GEIST", "headlineFont": "GEIST", "bodyFont": "GEIST", "labelFont": "GEIST", "roundness": "ROUND_TWELVE", - "customColor": "#818CF8", - "backgroundLight": "#F9FAFB", - "backgroundDark": "#09090B" - }, - "designTokens": "--color-primary: #818CF8;\n--color-bg: #09090B;", - "styleGuidelines": "Dark mode first. Geist font. Subtle indigo accent." + "customColor": "#818CF8" + } } } } @@ -52,17 +48,24 @@ You must have the design system's asset `name` before calling this. If you don't ## Parameter reference -### `designSystem` — required, Asset wrapper +Three **sibling** top-level arguments — `name` is not nested inside `designSystem`: -The object must include the `name` field (asset identifier) plus any fields you want to update: +| Argument | Type | Required | Description | +|----------|------|----------|-------------| +| `name` | string | **Yes** | Asset identifier **with** the `assets/` prefix, e.g. `assets/15996705518239280238`. Top-level, not inside `designSystem`. | +| `projectId` | string | **Yes** | Bare numeric project id, no `projects/` prefix | +| `designSystem` | object | **Yes** | `{displayName, theme}` — see below | + +### `designSystem` — `{displayName, theme}` only | Field | Type | Required | Description | |-------|------|----------|-------------| -| `name` | string | **Yes** | Asset name from create or list (e.g., `assets/ds_abc123`) | -| `displayName` | string | No | Updated human-readable name | -| `theme` | DesignTheme | No | Updated visual configuration (see `stitch-mcp-create-design-system` for full reference) | -| `designTokens` | string | No | Updated CSS custom properties | -| `styleGuidelines` | string | No | Updated design rules | +| `displayName` | string | **Yes** | Human-readable name | +| `theme` | DesignTheme | **Yes** | Visual configuration (see `stitch-mcp-create-design-system` for the full field reference) | + +> `update_design_system` takes the asset id **prefixed** (`assets/159967...`), while `apply_design_system` takes the same id **bare**. Two tools, same identifier, different formats. + +`designTokens` and `styleGuidelines` are **not** accepted — the live API has no such fields on `DesignSystem`. Don't send them. **Note:** This is a full replacement, not a merge. Include all theme fields you want to keep, not just the ones you're changing. @@ -72,7 +75,7 @@ Returns the updated Asset object: ```json { - "name": "assets/ds_abc123", + "name": "assets/15996705518239280238", "displayName": "SaaS Dashboard Theme v2", "designSystem": { ... } } diff --git a/skills/stitch-nextjs-components/SKILL.md b/skills/stitch-nextjs-components/SKILL.md index 7906c47..2739f4e 100644 --- a/skills/stitch-nextjs-components/SKILL.md +++ b/skills/stitch-nextjs-components/SKILL.md @@ -10,7 +10,7 @@ allowed-tools: # Stitch → Next.js 15 App Router Components -You are a senior Next.js engineer. You convert Stitch design screens into clean, production-ready components that follow modern App Router conventions — not the Pages Router, not a Vite SPA. Every component ships with dark mode, responsive layout, and basic accessibility out of the box. +You are a senior Next.js engineer. You convert HTML sources — Stitch screens, local files, or URLs — into clean, production-ready components that follow modern App Router conventions — not the Pages Router, not a Vite SPA. Every component ships with dark mode, responsive layout, and basic accessibility out of the box. ## When to use this skill @@ -105,14 +105,21 @@ src/ ## Step 4: Dark mode with CSS variables -This project uses a CSS variable approach that works with `next-themes`. Extract colors from the Stitch design and map them to semantic tokens. +This project uses a CSS variable approach that works with `next-themes`. Resolve colors from the source in this order, then map them to semantic tokens: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** already in the source (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. In `app/globals.css`: ```css :root { --color-background: #ffffff; --color-surface: #f4f4f5; - --color-primary: /* dominant action color from Stitch design */; + --color-primary: /* dominant action color from the source */; --color-primary-foreground: #ffffff; --color-text: #09090b; --color-text-muted: #71717a; @@ -151,7 +158,7 @@ export default function RootLayout({ children }: { children: React.ReactNode }) All components must work at `sm` (640px), `md` (768px), `lg` (1024px), and `xl` (1280px) breakpoints. -Apply these patterns from the Stitch design: +Apply these patterns from the source design: - **Navigation**: `hidden md:flex` for desktop nav, `flex md:hidden` for mobile hamburger - **Grid**: `grid-cols-1 sm:grid-cols-2 lg:grid-cols-3` — start single column - **Typography**: `text-2xl md:text-4xl` — scale up on larger screens @@ -183,7 +190,7 @@ If the design has complex interactivity (modals, dropdowns, tabs), use the `stit ## Step 8: Animation (optional) -If the Stitch design contains clear motion intent (hover states, transitions, reveals), use the `stitch-animate` skill after components are built. Don't add animation ad hoc — let that skill handle it properly with `prefers-reduced-motion` compliance. +If the source design contains clear motion intent (hover states, transitions, reveals), use the `stitch-animate` skill after components are built. Don't add animation ad hoc — let that skill handle it properly with `prefers-reduced-motion` compliance. ## Troubleshooting diff --git a/skills/stitch-react-components/SKILL.md b/skills/stitch-react-components/SKILL.md index c9bc6ac..cd037f1 100644 --- a/skills/stitch-react-components/SKILL.md +++ b/skills/stitch-react-components/SKILL.md @@ -86,10 +86,17 @@ src/ ## Step 3: Extract design tokens -From the Stitch HTML ``, find the `tailwind.config` or CSS variable definitions. +Resolve tokens from whatever the HTML actually gives you, in this order: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. ```ts -// src/theme/tokens.ts — extract hex values from Stitch HTML +// src/theme/tokens.ts export const lightTokens = { background: '#FFFFFF', surface: '#F4F4F5', @@ -154,10 +161,10 @@ export function useTheme(): ThemeTokens { ### Tailwind class mapping -Use the Stitch HTML classes directly in JSX where they don't reference Stitch-specific tokens. Map Stitch tokens to CSS variables: +Use the source HTML's Tailwind classes directly in JSX where they don't reference custom tokens. Map custom tokens to CSS variables: ```tsx -// Stitch HTML: bg-primary → CSS variable → Tailwind arbitrary value +// Source HTML: bg-primary → CSS variable → Tailwind arbitrary value // OR: use inline style with token value // Option A — Tailwind arbitrary value (if custom tokens in tailwind.config) @@ -239,14 +246,14 @@ export function StitchComponent({ ## Step 6: Integration with shadcn/ui -After converting the Stitch design to base React components, you can layer in shadcn/ui: +After converting the design to base React components, you can layer in shadcn/ui: ```bash npx shadcn@latest init # Set up shadcn in your Vite project npx shadcn@latest add button card input dialog ``` -Then use `stitch-shadcn-ui` skill to replace raw HTML elements with shadcn components while preserving the Stitch design tokens. +Then use `stitch-shadcn-ui` skill to replace raw HTML elements with shadcn components while preserving the design tokens. ## Troubleshooting @@ -261,7 +268,7 @@ Then use `stitch-shadcn-ui` skill to replace raw HTML elements with shadcn compo - `resources/component-template.tsx` — Boilerplate component - `resources/architecture-checklist.md` — Pre-ship checklist -- `references/tailwind-to-react.md` — Token + class mapping guide (Stitch HTML → React/Tailwind) +- `references/tailwind-to-react.md` — Token + class mapping guide (source HTML → React/Tailwind) - `scripts/fetch-stitch.sh` — Reliable GCS HTML downloader - `stitch-shadcn-ui` — Add shadcn/ui components after base conversion - `docs/tailwind-reference.md` — Tailwind utility class lookup diff --git a/skills/stitch-react-native-components/SKILL.md b/skills/stitch-react-native-components/SKILL.md index adb6a16..7b7fe4d 100644 --- a/skills/stitch-react-native-components/SKILL.md +++ b/skills/stitch-react-native-components/SKILL.md @@ -10,14 +10,14 @@ allowed-tools: # Stitch → React Native / Expo Components -You are a React Native engineer. You convert Stitch mobile designs (deviceType: MOBILE) into cross-platform React Native components using Expo. You work in TypeScript, use `StyleSheet.create` for styles, and follow Expo Router conventions for navigation. +You are a React Native engineer. You convert mobile UI layouts — a Stitch screen generated with `deviceType: MOBILE`, a local HTML file, or a URL — into cross-platform React Native components using Expo. You work in TypeScript, use `StyleSheet.create` for styles, and follow Expo Router conventions for navigation. ## When to use this skill Use this skill when: -- The user wants a **native mobile app** (iOS + Android) from a Stitch design +- The user wants a **native mobile app** (iOS + Android) from an existing design - The user mentions "React Native", "Expo", "mobile app", "iOS", "Android" -- The Stitch design was generated with `deviceType: MOBILE` +- The source is a **mobile layout** — narrow, vertical, touch-sized targets (a Stitch screen with `deviceType: MOBILE`, or a local file/URL that reads as mobile) **Note:** For a mobile WebView app (Capacitor, Ionic, PWA), use `stitch-html-components` instead. React Native outputs actual native UI — not web views. @@ -39,9 +39,12 @@ Also: Everything downstream reads one file: `temp/source.html`. Get the HTML there by whichever route matches what the user gave you, then continue at Step 2 — the rest of this skill is identical regardless of where the markup came from. -**From a Stitch screen:** +This skill only works on a **mobile layout** — narrow, vertical, touch-sized targets. Desktop layouts don't translate to RN regardless of source. How you confirm mobile-ness depends on where the HTML came from: + +- **Stitch screen** — check it was generated with `deviceType: MOBILE`. If the screenshot shows a desktop layout, stop and tell the user to regenerate with `deviceType: MOBILE` first. +- **Local HTML file or URL** — inspect the markup: a `` tag, mobile-first media queries, a narrow `max-width` on the root container, touch-sized tap targets. If it's clearly a desktop layout (wide multi-column grid, hover-only interactions, no viewport meta), stop and tell the user the source isn't a mobile layout — don't tell them to "regenerate with deviceType: MOBILE," that instruction is meaningless outside Stitch. -Only call this skill for **MOBILE** Stitch designs. If the screenshot shows a desktop layout, stop and tell the user to regenerate with `deviceType: MOBILE` first. +**From a Stitch screen:** 1. **Namespace discovery** — `list_tools` to find the Stitch MCP prefix 2. **Fetch metadata** — `[prefix]:get_screen` for the design JSON @@ -49,7 +52,7 @@ Only call this skill for **MOBILE** Stitch designs. If the screenshot shows a de ```bash bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html" ``` -4. **Visual audit** — check `screenshot.downloadUrl` before converting. Append `=s0` to that URL for full resolution; the bare URL serves a 512px thumbnail regardless of the `width`/`height` the API reports. Confirm it's a mobile layout (narrow, vertical). +4. **Visual audit** — check `screenshot.downloadUrl` before converting. Append `=s0` to that URL for full resolution; the bare URL serves a 512px thumbnail regardless of the `width`/`height` the API reports. Confirm it's a mobile layout, per the check above. **From a local HTML file:** @@ -57,7 +60,7 @@ Only call this skill for **MOBILE** Stitch designs. If the screenshot shows a de mkdir -p temp && cp "path/to/design.html" temp/source.html ``` -Open it and confirm it's a mobile layout before converting. +Open it and confirm it's a mobile layout, per the check above. **From a URL:** @@ -65,7 +68,7 @@ Open it and confirm it's a mobile layout before converting. bash scripts/fetch-stitch.sh "https://example.com/page" "temp/source.html" ``` -Despite the name, that script is a generic hardened downloader — follows redirects, retries transient failures, handles gzip, and fails loudly on an empty result. It does not care whether the URL points at Stitch. Confirm the page is a mobile layout before converting. +Despite the name, that script is a generic hardened downloader — follows redirects, retries transient failures, handles gzip, and fails loudly on an empty result. It does not care whether the URL points at Stitch. Confirm the page is a mobile layout, per the check above. **From a screenshot:** there's no upload route — the Stitch MCP API has no image-upload tool. Either recreate the design from a text prompt via `stitch-mcp-generate-screen-from-text`, or hand-write the HTML and use the local-file route above. @@ -146,8 +149,17 @@ const spacing = { ### Color mapping +Pull the hex values below from whatever token source the HTML actually has, in this order: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. + ```ts -// src/theme/tokens.ts — extract from Stitch Tailwind config +// src/theme/tokens.ts export const lightTokens = { background: '#FFFFFF', // from --color-background surface: '#F4F4F5', @@ -343,7 +355,7 @@ const styles = StyleSheet.create({ ## Execution steps -1. **Verify** it's a MOBILE Stitch design +1. **Verify** the source is a mobile layout (see Step 1) 2. **Data layer** — create `src/data/mockData.ts` from the static content in the design 3. **Tokens** — create `src/theme/tokens.ts` from extracted colors, and `useTheme.ts` 4. **Components** — convert each visual section to a component using the mapping rules above diff --git a/skills/stitch-svelte-components/SKILL.md b/skills/stitch-svelte-components/SKILL.md index 0a2ceb6..ae3391d 100644 --- a/skills/stitch-svelte-components/SKILL.md +++ b/skills/stitch-svelte-components/SKILL.md @@ -10,7 +10,7 @@ allowed-tools: # Stitch → Svelte 5 / SvelteKit Components -You are a Svelte 5 engineer. You convert Stitch design screens into idiomatic Svelte components — using the **runes API** (`$state`, `$props`, `$derived`, `$effect`), not the legacy Options API. Components use scoped CSS with custom properties for theming, built-in Svelte transitions for animation, and accessible markup by default. +You are a Svelte 5 engineer. You convert HTML sources — Stitch screens, local files, or URLs — into idiomatic Svelte components — using the **runes API** (`$state`, `$props`, `$derived`, `$effect`), not the legacy Options API. Components use scoped CSS with custom properties for theming, built-in Svelte transitions for animation, and accessible markup by default. > **Note:** This is the only Stitch skill that targets Svelte. The official `react-components` skill targets Vite/React. Use this skill when the project uses SvelteKit. @@ -136,14 +136,21 @@ static/ ← Static assets ## Step 4: Scoped CSS with design tokens -Svelte scopes CSS to the component by default — use this aggressively. Map Stitch colors to custom properties in the `:root` (via `+layout.svelte` or `app.css`) and reference them in each component. +Svelte scopes CSS to the component by default — use this aggressively. Resolve colors from the source in this order, then map them to custom properties in the `:root` (via `+layout.svelte` or `app.css`) and reference them in each component: + +1. **Inline `tailwind.config`** in `` (what Stitch emits) — use it directly if present. +2. **CSS custom properties** already in the source (`:root { --color-primary: ... }`) — common in hand-written and templated HTML. +3. **A linked or inline stylesheet** — parse declared colors, font-families, radii, spacing. +4. **Last resort** — derive tokens from the most frequent computed values in the markup (dominant background, text color, accent, heading/body font, border radius), and tell the user what you inferred so they can correct it. + +The URL route only downloads the single HTML response — externally-linked stylesheets may not come along for the ride. If none of the above resolves a token, say so instead of inventing a palette. **In `src/app.css` (global):** ```css :root { --color-background: #ffffff; --color-surface: #f4f4f5; - --color-primary: /* dominant color from Stitch design */; + --color-primary: /* dominant color from the source */; --color-primary-foreground: #ffffff; --color-text: #09090b; --color-text-muted: #71717a; @@ -197,7 +204,7 @@ Svelte scopes CSS to the component by default — use this aggressively. Map Sti ## Step 5: Built-in transitions and animations -Svelte has first-class transition support. Apply these from the Stitch design intent: +Svelte has first-class transition support. Apply these from the source design's motion intent: ```svelte