Merge pull request #59 from google-labs-code/stitch-skills-plugins

Launch Stitch Skills plugins
This commit is contained in:
J XIA
2026-05-18 10:59:46 -07:00
committed by GitHub
77 changed files with 5496 additions and 493 deletions
+2 -2
View File
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
defaults:
run:
working-directory: skills/react-components
working-directory: plugins/stitch-build/skills/react-components
steps:
- uses: actions/checkout@v4
@@ -21,7 +21,7 @@ jobs:
with:
node-version: '18.x'
cache: 'npm'
cache-dependency-path: skills/react-components/package-lock.json
cache-dependency-path: plugins/stitch-build/skills/react-components/package-lock.json
- name: Install dependencies
run: npm ci
+78 -42
View File
@@ -1,76 +1,111 @@
# Stitch Agent Skills
# Stitch Design Skills
A library of Agent Skills designed to work with the Stitch MCP server. Each skill follows the Agent Skills open standard, for compatibility with coding agents such as Antigravity, Gemini CLI, Claude Code, Cursor.
A collection of agent skills and plugins for [Google Stitch](https://stitch.withgoogle.com), following the [Agent Skills](https://agentskills.io) open standard. Compatible with coding agents such as Antigravity, Gemini CLI, Claude Code, and Cursor.
## Installation & Discovery
## Quick Start
Install any skill from this repository using the `skills` CLI. This command will automatically detect your active coding agents and place the skill in the appropriate directory.
### 1. Install Plugins (Recommended)
The fastest way to set up the full Stitch plugin suite globally.
```bash
# List all available skills in this repository
npx skills add google-labs-code/stitch-skills --list
npx plugins add google-labs-code/stitch-skills --scope project --target claude-code
# Install a specific skill
npx skills add google-labs-code/stitch-skills --skill react:components --global
```
## Available Skills
### 2. Install Skills Selectively
Choose only the specific skills you need.
### stitch-design
Unified entry point for Stitch design work. Handles prompt enhancement (UI/UX keywords, atmosphere), design system synthesis (.stitch/DESIGN.md), and high-fidelity screen generation/editing via Stitch MCP.
> [!IMPORTANT]
> Stitch Design Skills often have inter-dependencies. If you choose to install skills selectively, ensure you include all required dependencies.
```bash
npx skills add google-labs-code/stitch-skills --skill stitch-design --global
npx skills add google-labs-code/stitch-skills
```
### stitch-loop
Generates a complete multi-page website from a single prompt using Stitch, with automated file organization and validation.
You can run the following commands to see the help documentation for plugins and skills:
```bash
npx skills add google-labs-code/stitch-skills --skill stitch-loop --global
npx plugins --help
npx skills --help
```
### design-md
Analyzes Stitch projects and generates comprehensive DESIGN.md files documenting design systems in natural, semantic language optimized for Stitch screen generation.
## Prerequisites
```bash
npx skills add google-labs-code/stitch-skills --skill design-md --global
```
These skills require the **Stitch MCP** server to be configured and running in your agent's environment. Make sure you have followed the [Stitch MCP Setup Instructions](https://stitch.withgoogle.com/docs/mcp/setup/) to register the server and set up appropriate environment variables and credentials.
### enhance-prompt
Transforms vague UI ideas into polished, Stitch-optimized prompts. Enhances specificity, adds UI/UX keywords, injects design system context, and structures output for better generation results.
## Available Plugins
```bash
npx skills add google-labs-code/stitch-skills --skill enhance-prompt --global
```
### Design (`stitch-design`)
### react-components
Converts Stitch screens to React component systems with automated validation and design token consistency.
Core design workflows for creating, managing, and optimizing designs within Stitch.
```bash
npx skills add google-labs-code/stitch-skills --skill react:components --global
```
| Skill | Description | Prompt Example |
|---|---|---|
| [stitch::code-to-design](plugins/stitch-design/skills/code-to-design/) | Convert frontend code (React, Vue, etc.) to a Stitch Design via HTML extraction + design system + upload | *"Upload the frontend code at `/path/to/dashboard` into a Stitch project named 'Dashboard-Migration-2026'."* |
| [stitch::generate-design](plugins/stitch-design/skills/generate-design/) | Generate new screens from text or images, edit existing screens, and create design variants | · *"Make a browse tab for a mobile app for romance and date night ideas."*<br>· *"Edit the login screen to add a 'Remember Me' checkbox and change the button color to blue."*<br>· *"Generate 3 design variants of the home screen with dark mode and high-density layouts."* |
| [stitch::manage-design-system](plugins/stitch-design/skills/manage-design-system/) | Manage design systems in Stitch — upload DESIGN.md and apply themes to screens | *"Upload our design system from `.stitch/DESIGN.md` and apply it to all screens."* |
| [stitch::extract-design-md](plugins/stitch-design/skills/extract-design-md/) | Extract a comprehensive DESIGN.md directly from frontend source code | *"Scan `/src` and extract the design system into `.stitch/DESIGN.md`."* |
| [stitch::extract-static-html](plugins/stitch-design/skills/extract-static-html/) | Extract self-contained static HTML from running web apps, inlining CSS and images | *"Extract a static HTML snapshot of `http://localhost:3000/profile`."* |
| [stitch::upload-to-stitch](plugins/stitch-design/skills/upload-to-stitch/) | Upload local assets (images, mockups, HTML) to a Stitch project | *"Upload `.stitch/landing_page.html` to Stitch project `projects/987654321`."* |
### remotion
Generates walkthrough videos from Stitch projects using Remotion with smooth transitions, zooming, and text overlays to showcase app screens professionally.
---
```bash
npx skills add google-labs-code/stitch-skills --skill remotion --global
```
### Build (`stitch-build`)
### shadcn-ui
Expert guidance for integrating and building applications with shadcn/ui components. Helps discover, install, customize, and optimize shadcn/ui components with best practices for React applications.
Code generation, framework integration, and asset compilation from Stitch designs.
```bash
npx skills add google-labs-code/stitch-skills --skill shadcn-ui --global
```
| Skill | Description | Prompt Example |
|---|---|---|
| [react-components](plugins/stitch-build/skills/react-components/) | Convert Stitch screens to React component systems with automated validation and design token consistency | *"Convert all screens in Stitch project `projects/123` to React components."* |
| [remotion](plugins/stitch-build/skills/remotion/) | Generate walkthrough videos from Stitch projects using Remotion with smooth transitions and zooming | *"Generate a walkthrough video of the Stitch project `projects/456`."* |
| [shadcn-ui](plugins/stitch-build/skills/shadcn-ui/) | Expert guidance for integrating and building applications with shadcn/ui components | *"Set up shadcn/ui and build a data table with sorting and filtering."* |
---
### Utilities (`stitch-utilities`)
Supporting tools for enhancing prompts, generating design specs, and enforcing design standards.
| Skill | Description | Prompt Example |
|---|---|---|
| [design-md](plugins/stitch-utilities/skills/design-md/) | Analyze Stitch projects and generate comprehensive DESIGN.md files in semantic language | *"Analyze Stitch project `projects/123` and generate a DESIGN.md."* |
| [enhance-prompt](plugins/stitch-utilities/skills/enhance-prompt/) | Transform vague UI ideas into polished, Stitch-optimized prompts with UI/UX keywords | *"Enhance this prompt: 'make a settings page'."* |
| [stitch-loop](plugins/stitch-utilities/skills/stitch-loop/) | Generate complete multi-page websites from a single prompt with automated validation | *"Build a 5-page portfolio website with Stitch."* |
| [taste-design](plugins/stitch-utilities/skills/taste-design/) | Generate DESIGN.md files enforcing premium, anti-generic UI standards | *"Generate a premium DESIGN.md with strict typography and calibrated colors."* |
## Repository Structure
Every directory within `skills/` or at the root level follows a standardized structure to ensure the AI agent has everything it needs to perform "few-shot" learning and automated quality checks.
```text
plugins/
├── stitch-design/ — Core design workflow plugin
│ ├── plugin.json
│ └── skills/
│ ├── code-to-design/
│ ├── generate-design/
│ ├── manage-design-system/
│ ├── extract-design-md/
│ ├── extract-static-html/
│ └── upload-to-stitch/
├── stitch-build/ — Code generation & build plugin
│ ├── plugin.json
│ └── skills/
│ ├── react-components/
│ ├── remotion/
│ └── shadcn-ui/
└── stitch-utilities/ — Design utilities & assistants plugin
├── plugin.json
└── skills/
├── design-md/
├── enhance-prompt/
├── stitch-loop/
└── taste-design/
```
Each skill follows the Agent Skills standard:
```text
skills/[category]/
skills/<skill-name>/
├── SKILL.md — The "Mission Control" for the agent
├── scripts/ — Executable enforcers (Validation & Networking)
├── resources/ — The knowledge base (Checklists & Style Guides)
@@ -78,6 +113,7 @@ skills/[category]/
```
## Adding New Skills
All new skills need to follow the file structure above to implement the Agent Skills open standard.
### Great candidates for new skills
+1 -1
View File
@@ -9,6 +9,6 @@
## Reporting a Vulnerability
To report a security vulnerability, please use the [GitHub Security Advisory "Report a Vulnerability" tab](https://github.com/google-labs-code/jules-sdk/security/advisories/new).
To report a security vulnerability, please use the [GitHub Security Advisory "Report a Vulnerability" tab](https://github.com/google-labs-code/stitch-skills/security/advisories/new).
> **Note:** This is not an officially supported Google product. This project is not eligible for the [Google Open Source Software Vulnerability Rewards Program](https://bughunters.google.com/open-source-security).
+20
View File
@@ -0,0 +1,20 @@
{
"name": "stitch-build",
"description": "Code generation and build tools for Google Stitch — convert designs to React components, generate walkthrough videos with Remotion, and integrate shadcn/ui.",
"version": "1.0.0",
"author": {
"name": "google-labs-code"
},
"homepage": "https://github.com/google-labs-code/stitch-skills",
"repository": "https://github.com/google-labs-code/stitch-skills",
"license": "Apache-2.0",
"keywords": [
"stitch",
"react",
"components",
"remotion",
"shadcn-ui",
"code-generation",
"video"
]
}
@@ -1,18 +1,3 @@
/**
* Copyright 2026 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React from 'react';
// Note for Agent: The '@' alias refers to the target project's src directory.
@@ -190,7 +190,7 @@ Create the video components following Remotion best practices:
**Reference Resources:**
- Use `resources/screen-slide-template.tsx` as starting point
- Follow `resources/composition-checklist.md` for completeness
- Review examples in `examples/walkthrough/` directory
- Review examples in `examples/` directory
### Step 3: Preview and Refine
+20
View File
@@ -0,0 +1,20 @@
{
"name": "stitch-design",
"description": "Design workflows for Google Stitch — convert code to designs, generate screens from text/images, manage design systems, extract static HTML, and upload assets.",
"version": "1.0.0",
"author": {
"name": "google-labs-code"
},
"homepage": "https://github.com/google-labs-code/stitch-skills",
"repository": "https://github.com/google-labs-code/stitch-skills",
"license": "Apache-2.0",
"keywords": [
"stitch",
"design",
"code-to-design",
"design-system",
"html-extraction",
"mcp",
"ui-generation"
]
}
@@ -0,0 +1,75 @@
---
name: stitch::code-to-design
description: >-
Convert frontend code (Vite, React, etc.) to a Stitch Design by chaining
static HTML extraction, design system extraction, and file upload. **ALWAYS** use this skill when the user's intent is to move existing web apps or React components into Stitch (e.g., requests to "save", "migrate", or "upload"). You must use this skill even for simple "save" operations, as it is the only way to ensure the design system is extracted and assets are properly linked.
allowed-tools:
- "stitch*:*"
- "Bash"
- "Read"
- "Write"
- "web_fetch"
---
# Code to Design
Transform your existing frontend code into a Stitch Design so you can iterate and improve it using Stitch.
This skill orchestrates three other skills in sequence:
1. `extract-static-html`: Extract a single self-contained HTML file from your build output.
2. `extract-design-md`: Analyze the source code to create a design system (DESIGN.md).
3. `upload-to-stitch`: Upload that HTML file and the design system to your Stitch project.
## Workflow
Follow these steps to convert your existing code.
### Prerequisites
- A built web application directory containing `index.html` and assets.
- Target Stitch `projectId` (use `list_projects` if unknown).
### Steps
#### 1. Extract Self-Contained HTML
Delegate to the `extract-static-html` skill to generate a standalone HTML file.
Read [skills/extract-static-html/SKILL.md](../extract-static-html/SKILL.md) for detailed instructions and script usage.
Expected output: A single file like `/path/to/extracted/standalone.html`.
#### 2. Verify HTML (Optional — User-Driven)
After extraction, inform the user of the output file path so they can manually
verify in a browser if desired. **Do not block on verification** — proceed
directly to Step 3.
If the user reports issues after reviewing, fix them before continuing.
#### 3. Extract Design System (File)
Delegate to the `extract-design-md` skill to analyze the project's source files
(components, stylesheets, theme configs) and produce a design system. Read
[skills/extract-design-md/SKILL.md](../extract-design-md/SKILL.md) for the
full analysis workflow.
Write `.stitch/DESIGN.md` following the `extract-design-md` skill's output
structure.
#### 4. Upload DESIGN.md and Create Design System in Stitch
Delegate to the `manage-design-system` skill to upload the `DESIGN.md` and
create the design system in Stitch. Read
[skills/manage-design-system/SKILL.md](../manage-design-system/SKILL.md) for
the full workflow (upload script usage, `create_design_system_from_design_md`
call, and required schemas).
#### 5. Upload HTML to Stitch
Use the same `upload-to-stitch` skill's script to upload the extracted HTML file.
Read [skills/upload-to-stitch/SKILL.md](../upload-to-stitch/SKILL.md) for detailed instructions and script usage.
You will need:
- The path to the standalone HTML file generated in Step 1.
- Your Stitch API Key (same key used in Step 4).
- The target `projectId`.
@@ -0,0 +1,365 @@
---
name: stitch::extract-design-md
description: >-
Extract a comprehensive design system (DESIGN.md) directly from frontend source
code — React, Vue, Svelte, Angular, plain HTML/CSS, or any web framework. Analyzes
component files, stylesheets, Tailwind configs, theme definitions, and design tokens
to produce a rich, Stitch-compatible design system document. Use this skill whenever
the user wants to reverse-engineer a design system from an existing codebase, audit
the visual language of a project, extract design tokens from source files, or
understand the styling patterns in a frontend repo — even if they just say "what
does this app look like?" or "pull out the design from this code."
allowed-tools:
- "stitch*:*"
- "Bash"
- "Read"
- "Write"
- "web_fetch"
---
# Extract Design System from Frontend Code
Analyze frontend source code to extract a comprehensive design system document
(DESIGN.md) that captures the project's visual language — colors, typography,
spacing, component patterns, and layout principles — directly from the source
files, without needing to build or render the application.
## Why This Exists
The `design-md` skill works from rendered HTML. But often you have a codebase
and want to understand its design system before you can even run the app —
maybe dependencies are missing, the build is broken, or you just want a quick
audit. This skill reads the source files themselves: stylesheets, component
files, theme configs, and Tailwind setups. It's faster and works anywhere.
## When to Use
- User has a frontend codebase and wants to extract or document its design system
- User wants to migrate a project's visual identity into Stitch
- User asks to "audit the styling" or "understand the design language" of a repo
- User wants to create a DESIGN.md from existing source code
- The app can't be built/rendered but the source is available
- User wants to unify or reconcile inconsistent styles across a codebase
## Prerequisites
- Access to the frontend project's source directory
- No build or runtime dependencies needed — this skill reads source files only
---
## Workflow
### Phase 1: Project Discovery
Start by understanding what you're working with. This determines which
extraction patterns to use.
#### 1. Detect the Framework and Stack
Scan the project root for telltale files:
| Signal File | Framework / Tool |
|:---|:---|
| `package.json` with `react` | React / Next.js |
| `package.json` with `vue` | Vue / Nuxt |
| `package.json` with `svelte` | Svelte / SvelteKit |
| `package.json` with `@angular/core` | Angular |
| `tailwind.config.js/ts` | Tailwind CSS |
| `postcss.config.js` | PostCSS pipeline |
| `styled-components` or `@emotion` in deps | CSS-in-JS |
| `.css` / `.scss` / `.less` files only | Plain CSS / SASS |
| `theme.js` / `theme.ts` / `tokens.js` | Design token files |
Read `package.json` first — it reveals the framework, CSS tooling, and any
design-token libraries (e.g., `style-dictionary`, `@chakra-ui/react`,
`@mui/material`, `ant-design`). This context tells you *where* to look for
styling information.
#### 2. Map the Source Tree
Identify the key directories and files you'll analyze:
```
src/
├── components/ ← Component-level styles
├── styles/ ← Global stylesheets
├── theme/ ← Theme definitions, tokens
├── assets/ ← Fonts, images
├── app.css ← Root styles
└── index.css ← Entry CSS
```
Also check for:
- `tailwind.config.js` / `tailwind.config.ts` — Custom colors, fonts, spacing
- `globals.css` / `global.css` — CSS custom properties (variables)
- Any `theme.*` or `tokens.*` files
- Component library config (e.g., `chakra-theme.ts`, `vuetify.config.ts`)
#### 3. Read Framework-Specific Guidance
Consult the appropriate reference for extraction patterns:
- **React / Next.js / Tailwind** → [references/react-tailwind.md](references/react-tailwind.md)
- **Vue / Nuxt** → [references/vue.md](references/vue.md)
- **Svelte / SvelteKit** → [references/svelte.md](references/svelte.md)
- **Angular** → [references/angular.md](references/angular.md)
- **Plain CSS / SASS / Less** → [references/plain-css.md](references/plain-css.md)
These references contain framework-specific patterns for locating colors,
typography, spacing, and component styles. Read the one that matches before
proceeding.
---
### Phase 2: Deep Extraction
Work through each design dimension systematically. For each one, gather raw
data from the source files, then synthesize it into descriptive language.
The goal isn't to dump every CSS property — it's to understand the *intent*
behind the styling choices and describe them in human, editorial language that
another designer (or Stitch) can use to recreate the same visual feel.
#### 1. Visual Theme & Atmosphere
Read the broadest styling first to understand the overall mood:
- **Root background**: What's the `body` or root element background? Light
cream (#f-range) signals airy/clean; dark (#0-#2 range) signals moody/dramatic.
- **Whitespace philosophy**: Are spacing values generous (32px+) or tight?
Check padding/margin values on root containers, section wrappers, and card components.
- **Density**: Count the components per page/section. Few with space = minimal;
many packed tight = information-dense.
- **Color temperature**: Are the neutrals warm (creams, tans) or cool (blue-grays, slates)?
- **Overall feel**: Synthesize into 1-2 rich sentences that capture the mood.
Look for these signals in the source:
| Source Location | What It Tells You |
|:---|:---|
| Root `background-color` or Tailwind `bg-*` on layouts | Overall lightness/darkness |
| Spacing scale in Tailwind config or CSS vars | Whitespace philosophy |
| Number of components vs. wrapper padding | Density |
| Custom property naming (`--warm-*` vs `--cool-*`) | Color temperature intent |
| Comments in theme files | Design intent in the developer's own words |
#### 2. Color Palette & Roles
Extract every unique color from the codebase and assign functional roles.
Search across all layers:
**Where to find colors:**
| Layer | What to Search |
|:---|:---|
| CSS custom properties | `--color-*`, `--primary`, `--bg-*` |
| Tailwind config | `theme.extend.colors` |
| Theme/token files | Color objects, palettes |
| Component styles | `background-color`, `color`, `border-color` |
| Inline/scoped styles | `bg-*`, `text-*` classes in templates |
| CSS-in-JS theme objects | `colors`, `palette` keys |
**How to organize:** Group colors by function, not by hue:
1. **Primary Foundation** — Background and surface colors
2. **Accent & Interactive** — CTA buttons, active states, links
3. **Typography & Text Hierarchy** — Primary, secondary, tertiary text
4. **Functional States** — Success, error, warning, info
For each color, create a descriptive name that evokes the color's character
rather than its raw hex value:
-`#294056` → "Blue"
-`#294056`**"Deep Muted Teal-Navy"** — Primary CTA, active navigation
**Deduplication matters.** Codebases often have near-duplicate colors (e.g.,
`#333` and `#2C2C2C`). Consolidate them under one name that best represents
the intended color.
#### 3. Typography Rules
Extract the complete typographic system:
**Font families:**
- Check CSS `font-family`, Tailwind `fontFamily`, Google Fonts links, or
local `@font-face` declarations.
- Note the **character** of each font: geometric vs humanist, serif vs sans,
the feeling it evokes.
**Type scale (hierarchy):**
- Find every heading level (H1-H6) and body text, noting:
- `font-size` (in rem or px)
- `font-weight` (numeric value + descriptive name)
- `letter-spacing` (and why — elegance? compactness?)
- `line-height` (generous for readability? tight for display?)
- Map component usage: Which heading level do product cards use? What about
hero sections?
**Spacing principles:**
- How does text spacing relate to the overall spacing scale?
- Letter-spacing patterns on headings vs body
- Line-height philosophy (generous/relaxed for body, tighter for display)
#### 4. Component Stylings
Analyze the 4-5 most important UI primitives:
**Buttons:**
- Corner radius (and what it communicates — playful? professional? minimal?)
- Color scheme for primary, secondary, and ghost variants
- Hover/focus/active states and transition timing
- Padding ratios (horizontal vs vertical)
**Cards / Containers:**
- Corner radius (often different from buttons — slightly rounder)
- Shadow strategy: flat, subtle hover shadows, or always elevated?
- Border treatment: hairline borders, colored accents, or none?
- Internal padding (generous or compact?)
- Image treatment within cards (full-bleed, padded, rounded?)
**Navigation:**
- Layout pattern (horizontal bar, vertical sidebar, drawer)
- Typography treatment (uppercase, letter-spacing, weight)
- Active/hover state indicators (underline, color, background)
- Mobile behavior (hamburger, bottom nav, drawer)
**Inputs & Forms:**
- Border style and focus state behavior
- Corner style consistency with buttons
- Padding and touch-target sizing
**Domain-Specific Components:**
- Identify 1-2 components unique to this project (e.g., product cards,
dashboard widgets, chat bubbles) and describe their styling patterns.
#### 5. Layout Principles
Extract the structural system:
**Grid & Structure:**
- Max content width (from `max-width` on containers)
- Column system (CSS Grid, Flexbox patterns, defined breakpoints)
- Responsive breakpoints (from media queries or Tailwind config)
**Whitespace Strategy:**
- Base spacing unit (8px grid? 4px? custom?)
- Section margins (how much space between major sections)
- Edge padding (page margins at different breakpoints)
**Alignment & Visual Balance:**
- Text alignment patterns (centered heroes, left-aligned body)
- Image-to-text ratios
- Visual weight distribution
**Responsive Behavior:**
- Mobile-first or desktop-first?
- How do grids collapse? Padding scale?
- Touch target sizing
#### 6. Stitch Generation Notes
Synthesize the extraction into actionable prompts for Stitch:
- **Atmosphere language**: Translate the mood into natural descriptors
- **Color references**: List colors by descriptive name + hex
- **Component prompts**: Write 2-3 example prompts that would recreate
key components in Stitch
- **Iteration guidance**: Tips for refining screens in this design system
---
### Phase 3: Write the DESIGN.md
Assemble everything into the standard DESIGN.md format. Place it at
`.stitch/DESIGN.md` in the project directory (create the `.stitch/` directory
if it doesn't exist).
> [!IMPORTANT]
> You **MUST** include the YAML frontmatter at the top of the file with `name` and `colors` mapping, exactly as shown in the example at [examples/DESIGN.md](examples/DESIGN.md). This structured data is required for other skills to parse the design system.
>
> Failure to include this YAML block with at least the core color tokens is a failure to use this skill correctly.
Use the format from the example at [examples/DESIGN.md](examples/DESIGN.md) as your template. The file must start with the YAML block, followed by the markdown sections:
```markdown
# Design System: [Project Name]
**Project ID:** [If known, otherwise omit]
## 1. Visual Theme & Atmosphere
[Rich 2-paragraph description of mood, philosophy, and key characteristics]
## 2. Color Palette & Roles
### Primary Foundation
### Accent & Interactive
### Typography & Text Hierarchy
### Functional States
## 3. Typography Rules
### Hierarchy & Weights
### Spacing Principles
## 4. Component Stylings
### Buttons
### Cards & [Domain-Specific Containers]
### Navigation
### Inputs & Forms
### [Domain-Specific Components]
## 5. Layout Principles
### Grid & Structure
### Whitespace Strategy
### Alignment & Visual Balance
### Responsive Behavior & Touch
## 6. Design System Notes for Stitch Generation
### Language to Use
### Color References
### Component Prompts
### Incremental Iteration
```
---
### Phase 4: Integration (Optional)
If the user wants to push the design system into Stitch:
1. Hand off to the `manage-design-system` skill for the MCP create/update calls
2. The DESIGN.md you wrote is the input — the manage-design-system skill handles
the Stitch API integration
If the user just wants the document, you're done after Phase 3.
---
## Quality Checklist
Before delivering the DESIGN.md, verify:
- [ ] Every color has a descriptive name, hex code, and functional role
- [ ] Typography includes font family, character description, and full hierarchy
- [ ] Component styles describe shape, color, states, and transitions
- [ ] Layout includes max-width, grid, breakpoints, and spacing strategy
- [ ] Stitch generation notes use natural language, not CSS syntax
- [ ] The atmosphere section reads like editorial copy, not technical docs
- [ ] Near-duplicate colors are consolidated
- [ ] The document captures the *intent* behind styling, not just raw values
## Tips for Better Extraction
- **Read comments and commit messages.** Developers often document design
intent in code comments (`/* hero section — breathable */`) and commit
messages. These are gold for understanding the *why*.
- **Check for design-token libraries.** If the project uses `style-dictionary`,
`@tokens-studio`, or similar, these files are the most authoritative
source of design values.
- **Theme files are higher-signal than component styles.** A `theme.ts` that
defines a palette tells you the intended design system; scattered inline
styles in components tell you what actually shipped. Both matter, but
start from the theme.
- **Tailwind config is a design system.** If a project has a customized
`tailwind.config.js`, that *is* the design system — extract from it first,
then spot-check components for overrides.
- **CSS custom properties are intentional.** If a developer defined
`--brand-primary`, they're telling you this is a design token. Respect that.
@@ -0,0 +1,210 @@
---
name: Alpine Peak
colors:
surface: '#fcf8fa'
surface-dim: '#dcd9db'
surface-bright: '#fcf8fa'
surface-container-lowest: '#ffffff'
surface-container-low: '#f6f3f5'
surface-container: '#f0edef'
surface-container-high: '#eae7e9'
surface-container-highest: '#e4e2e4'
on-surface: '#1b1b1d'
on-surface-variant: '#45464d'
inverse-surface: '#303032'
inverse-on-surface: '#f3f0f2'
outline: '#76777d'
outline-variant: '#c6c6cd'
surface-tint: '#565e74'
primary: '#000000'
on-primary: '#ffffff'
primary-container: '#131b2e'
on-primary-container: '#7c839b'
inverse-primary: '#bec6e0'
secondary: '#5c5f61'
on-secondary: '#ffffff'
secondary-container: '#e0e3e5'
on-secondary-container: '#626567'
tertiary: '#000000'
on-tertiary: '#ffffff'
tertiary-container: '#161c22'
on-tertiary-container: '#7e848c'
error: '#ba1a1a'
on-error: '#ffffff'
error-container: '#ffdad6'
on-error-container: '#93000a'
primary-fixed: '#dae2fd'
primary-fixed-dim: '#bec6e0'
on-primary-fixed: '#131b2e'
on-primary-fixed-variant: '#3f465c'
secondary-fixed: '#e0e3e5'
secondary-fixed-dim: '#c4c7c9'
on-secondary-fixed: '#191c1e'
on-secondary-fixed-variant: '#444749'
tertiary-fixed: '#dde3eb'
tertiary-fixed-dim: '#c1c7cf'
on-tertiary-fixed: '#161c22'
on-tertiary-fixed-variant: '#41474e'
background: '#fcf8fa'
on-background: '#1b1b1d'
surface-variant: '#e4e2e4'
typography:
display-lg:
fontFamily: Inter
fontSize: 48px
fontWeight: '800'
lineHeight: 56px
letterSpacing: -0.02em
headline-md:
fontFamily: Inter
fontSize: 24px
fontWeight: '700'
lineHeight: 32px
letterSpacing: -0.01em
body-base:
fontFamily: Inter
fontSize: 16px
fontWeight: '400'
lineHeight: 24px
letterSpacing: '0'
body-bold:
fontFamily: Inter
fontSize: 16px
fontWeight: '600'
lineHeight: 24px
letterSpacing: '0'
label-caps:
fontFamily: Lexend
fontSize: 12px
fontWeight: '700'
lineHeight: 16px
letterSpacing: 0.05em
stat-lg:
fontFamily: Lexend
fontSize: 32px
fontWeight: '600'
lineHeight: 40px
letterSpacing: -0.02em
rounded:
sm: 0.25rem
DEFAULT: 0.5rem
md: 0.75rem
lg: 1rem
xl: 1.5rem
full: 9999px
spacing:
unit: 4px
xs: 4px
sm: 8px
md: 16px
lg: 24px
xl: 32px
gutter: 16px
margin-mobile: 20px
margin-desktop: 40px
---
## Brand & Style
The brand personality is high-performance, sophisticated, and dependable. It is
designed for the modern skier who demands clarity and precision in harsh
environments. The visual language evokes the crystalline beauty of a mountain
peak while prioritizing the rugged utility required for outdoor navigation.
The design system utilizes **Glassmorphism** to achieve a "frozen" aesthetic,
mimicking the properties of ice and packed snow. This is paired with a
**High-Contrast** philosophy to ensure that critical data—like trail status and
weather alerts—remains legible under intense mountain sunlight or the
low-visibility conditions of a snowstorm.
## Colors
The palette is anchored by **Deep Peak Blue**, a dark navy that provides a
grounding contrast for white text and maps. **Powder White** serves as the
primary canvas, ensuring the interface feels airy and cold.
**Safety Orange** is reserved strictly for primary calls to action, hazard
warnings, and emergency trail closures, ensuring immediate eye-tracking.
**Electric Blue** (the info status) is used for weather updates and general
interactivity. For trail difficulty levels, standard industry colors (Green,
Blue, Black) are used but rendered with high-saturation values to pop against
the white backgrounds.
## Typography
The typography system uses **Inter** for core functional text and body copy due
to its exceptional x-height and legibility at small sizes. **Lexend** is
introduced for labels and statistics; its hyper-readable, athletic character
suits the "active" nature of skiing data like speed and vertical drop.
To combat outdoor glare, font weights are generally heavier than standard web
applications. Display styles use tight tracking and heavy weights to create a
sense of strength. Labels always utilize high-contrast coloring against their
backgrounds.
## Layout & Spacing
This design system uses a **Fluid Grid** model with generous safe areas.
Elements are spaced using a strict 4px/8px baseline rhythm to maintain a
disciplined, professional appearance.
Touch targets are intentionally oversized (minimum 48x48px) to accommodate users
wearing gloves. Padding within cards and containers is kept spacious (`lg` or
`xl`) to prevent the interface from feeling cluttered when displaying complex
trail data.
## Elevation & Depth
Depth is conveyed through **Glassmorphism** and backdrop filters rather than
traditional heavy shadows. Surfaces use a hierarchy of transparency:
1. **Base Layer:** Solid 'Powder White' or 'Deep Peak Blue'.
2. **Middle Layer (Cards/Modals):** 70% opacity white with a 20px backdrop blur
and a thin 1px 'Ice' border (white at 40% opacity).
3. **Top Layer (Floating Actions):** 90% opacity with a subtle 4px ambient
shadow to separate the element from the blurred background.
This creates a "stacked ice" effect that maintains visual clarity while giving
the UI a premium, modern feel.
## Shapes
The shape language is defined by modern, organic **rounded corners**. This
softens the high-contrast color palette and makes the app feel approachable.
Interactive elements like buttons and chips utilize `rounded-lg` (1rem) or
`rounded-xl` (1.5rem) to suggest a tactile, "pebble" feel. Large containers like
map overlays use 1rem corners, while small status indicators for trail
difficulty may use pill shapes for instant recognition.
## Components
### Buttons
Primary buttons use a solid 'Safety Orange' or 'Deep Peak Blue' fill with white
text. High-contrast outlines are used for secondary actions. All buttons must
feature a minimum height of 52px for gloved-hand accessibility.
### Cards & Modals
Cards utilize the glassmorphism effect—semi-transparent backgrounds with a 1px
white border. This ensures that map imagery or photos underneath remain slightly
visible, maintaining the "frozen" aesthetic.
### Trail Status Chips
Pill-shaped indicators with high-saturation icons. Green (Easy), Blue
(Intermediate), Black (Expert), and Double Black (Extreme). These must include
text labels alongside icons to ensure accessibility for colorblind users.
### Input Fields
Fields feature a 'Cloud Gray' background with a thick bottom border that
transforms into 'Electric Blue' on focus. Labels are always visible above the
field to ensure the user doesn't lose context in bright environments.
### Weather Widgets
Bold, thick-stroke iconography (minimum 2pt stroke) to represent sun, snow, or
wind. These icons should be large and accompanied by 'Lexend' typography for
temperature and wind speed.
@@ -0,0 +1,114 @@
# Angular Extraction Patterns
Angular projects use a structured, convention-heavy approach to styling.
Design systems often live in SCSS/CSS files with clear separation between
global themes and component-scoped styles.
## File Discovery Order
1. **`angular.json`** — Lists global style files under
`projects.*.architect.build.options.styles`. These are the entry-point
CSS/SCSS files.
2. **`src/styles.scss` / `src/styles.css`** — Global stylesheet. CSS custom
properties, font imports, and base styles live here.
3. **`src/theme.scss` / `src/theme/`** — Explicit theme directory. Custom
Material/component palettes.
4. **`tailwind.config.js`** (if Tailwind) — Same extraction as React.
5. **`src/app/app.component.scss`** — Root component styles, reveals global
layout patterns.
6. **Component `.scss` / `.css` files** — Co-located styles (ViewEncapsulation
scoped by default).
## Angular Material Theme Extraction
Angular Material is the most common component library. Themes are SCSS-based:
```scss
// src/theme.scss
@use '@angular/material' as mat;
$primary-palette: mat.m2-define-palette(mat.$m2-teal-palette, 800);
$accent-palette: mat.m2-define-palette(mat.$m2-blue-grey-palette);
$warn-palette: mat.m2-define-palette(mat.$m2-red-palette);
$theme: mat.m2-define-light-theme((
color: (
primary: $primary-palette,
accent: $accent-palette,
warn: $warn-palette,
),
typography: mat.m2-define-typography-config(
$font-family: 'Manrope, sans-serif',
$headline-1: mat.m2-define-typography-level(3.5rem, 4rem, 600),
$headline-5: mat.m2-define-typography-level(1.5rem, 2rem, 500),
$body-1: mat.m2-define-typography-level(1rem, 1.7, 400),
),
));
@include mat.all-component-themes($theme);
```
**What to extract:**
- Palette choices → map to functional color roles
- Typography config → maps directly to the hierarchy section
- Light vs dark theme → atmosphere
For Angular Material 3 (MDC-based), look for `mat.define-theme()` using
the new token system with `--mat-*` CSS custom properties.
## SCSS Variable Patterns
Many Angular projects use SCSS variables for tokens:
```scss
// _variables.scss
$color-primary: #294056;
$color-background: #FCFAFA;
$color-surface: #F5F5F5;
$color-text: #2C2C2C;
$font-heading: 'Manrope', sans-serif;
$font-body: 'Inter', sans-serif;
$radius-button: 8px;
$radius-card: 12px;
$breakpoint-mobile: 768px;
$breakpoint-desktop: 1024px;
$spacing-section: 5rem;
$spacing-component: 2rem;
```
These are explicit design tokens. Map them directly.
## ViewEncapsulation and Scoped Styles
Angular scopes styles by default (similar to Vue's `scoped`). When scanning
component styles:
- Look for `:host` selectors — these style the component's root element
- `::ng-deep` (deprecated but still used) — styles that pierce encapsulation
- Repeated values across components indicate design system conventions
## PrimeNG / Nebular / NG-ZORRO
If component libraries are used:
- **PrimeNG**: Theme SCSS in `node_modules/primeng/resources/themes/`
look for custom theme or `styles.scss` overrides.
- **Nebular**: `nb-theme()` in `styles.scss` with custom theme object.
- **NG-ZORRO (Ant Design for Angular)**: `ng-zorro-antd.less` variables
or custom theme config in `angular.json`.
## Responsive Patterns
Check for:
- `@media` queries in `styles.scss` and component styles
- Angular CDK `BreakpointObserver` usage in components
- Tailwind responsive prefixes if Tailwind is configured
- Angular Flex-Layout directives (`fxLayout`, `fxFlex`) in templates
@@ -0,0 +1,161 @@
# Plain CSS / SASS / Less Extraction Patterns
For projects without a JavaScript framework — static sites, WordPress
themes, vanilla HTML/CSS, or CSS preprocessor-heavy projects.
## File Discovery Order
1. **`index.html` / `*.html`** — Check `<link>` tags and `<style>` blocks
for stylesheet references, inline styles, and font loading.
2. **Main stylesheet** (`style.css`, `main.css`, `app.css`) — The primary
CSS file. Look for custom properties, base styles, and typography.
3. **`_variables.scss` / `_tokens.scss` / `variables.less`** — Preprocessor
variable files containing design tokens.
4. **`_mixins.scss`** — Reusable style patterns reveal design conventions.
5. **Component/module stylesheets** — Individual CSS files for UI components.
## CSS Custom Properties (Modern CSS)
Modern vanilla CSS projects often define a design system via custom properties:
```css
:root {
/* Colors */
--color-primary: #294056;
--color-bg: #FCFAFA;
--color-surface: #F5F5F5;
--color-text: #2C2C2C;
--color-text-secondary: #6B6B6B;
--color-border: #E0E0E0;
--color-success: #10B981;
--color-error: #EF4444;
/* Typography */
--font-heading: 'Manrope', sans-serif;
--font-body: 'Inter', sans-serif;
--font-size-base: 1rem;
--line-height-body: 1.7;
/* Spacing */
--spacing-xs: 0.5rem;
--spacing-sm: 1rem;
--spacing-md: 2rem;
--spacing-lg: 4rem;
--spacing-xl: 6rem;
/* Shapes */
--radius-button: 8px;
--radius-card: 12px;
/* Shadows */
--shadow-card: 0 2px 8px rgba(0,0,0,0.06);
}
```
This is the cleanest source of truth. Extract directly and name each token.
## SASS/SCSS Token Patterns
```scss
// _variables.scss
$colors: (
'primary': #294056,
'background': #FCFAFA,
'surface': #F5F5F5,
'text': #2C2C2C,
'text-muted': #6B6B6B,
);
$font-stack-heading: 'Manrope', sans-serif;
$font-stack-body: 'Inter', sans-serif;
$breakpoints: (
'mobile': 768px,
'tablet': 1024px,
'desktop': 1280px,
);
$spacers: (
'section': 5rem,
'component': 2rem,
'element': 1rem,
);
```
SASS maps are essentially design token dictionaries. Extract all values.
## Less Variable Patterns
```less
@primary-color: #294056;
@bg-color: #FCFAFA;
@text-color: #2C2C2C;
@font-heading: 'Manrope', sans-serif;
@border-radius-base: 8px;
```
Same extraction approach — map each variable to a descriptive name and role.
## Static Sites and WordPress
For static sites or WordPress themes:
- **WordPress**: Check `style.css` header comment for theme metadata.
Look for `wp-content/themes/<name>/assets/css/` for stylesheets.
`functions.php` may enqueue Google Fonts.
- **Jekyll/Hugo**: Check `_sass/` or `assets/css/` directories.
- **Static HTML**: Everything is in the CSS files and `<style>` blocks.
## Inline Style Scanning
For projects heavy on inline styles (legacy codebases, email templates):
Search HTML files for `style="..."` attributes. Group unique values by
property type:
```
background-color: #FCFAFA, #F5F5F5, #294056
color: #2C2C2C, #6B6B6B, white
border-radius: 8px, 12px
font-family: 'Manrope', 'Inter'
```
Then deduplicate and assign roles.
## Color Extraction Strategy
When there's no explicit token system, you need to discover colors across
all stylesheets. Search for:
```
background-color:
background:
color:
border-color:
border:
outline-color:
box-shadow:
fill:
stroke:
```
Collect all unique hex values, `rgb()`, `rgba()`, and `hsl()` values.
Group by proximity (similar colors within a few shades) and assign roles
based on context (which selectors use them).
## Responsive Patterns
Look for `@media` queries in all stylesheets. Common patterns:
```css
@media (max-width: 768px) { ... } /* Mobile-first breakpoint */
@media (min-width: 1024px) { ... } /* Desktop enhancement */
@media (prefers-color-scheme: dark) { ... } /* Dark mode support */
```
Document all breakpoints and the content strategy at each (column
changes, padding adjustments, navigation transformations).
@@ -0,0 +1,157 @@
# React / Next.js / Tailwind Extraction Patterns
This reference covers the most common frontend stack: React components with
Tailwind CSS (and optionally CSS Modules, styled-components, or Emotion).
## File Discovery Order
Read these files in priority order — higher-priority files give you the
intended design system, lower-priority files show what actually shipped:
1. **`tailwind.config.js` / `tailwind.config.ts`** — The single most
important file. Custom `theme.extend.colors`, `fontFamily`, `spacing`,
`borderRadius`, and `screens` are the design system definition.
2. **`globals.css` / `global.css` / `index.css`** — CSS custom properties
(`--*`), `@layer` directives, `@font-face` declarations, and base styles.
3. **`theme.ts` / `theme.js` / `tokens.ts`** — Explicit design token files.
May export objects consumed by Tailwind config or CSS-in-JS providers.
4. **`src/app/layout.tsx` or `src/App.tsx`** — Root layout. Shows the global
font setup (via `next/font` or `<link>`), body background, and overall
structure.
5. **Component files (`*.tsx` / `*.jsx`)** — Look at 5-8 representative
components to understand usage patterns.
## Tailwind Config Extraction
The Tailwind config is structured and machine-readable. Extract directly:
```js
// tailwind.config.js
module.exports = {
theme: {
extend: {
colors: {
primary: '#294056', // → "Deep Muted Teal-Navy" — Primary CTA
background: '#FCFAFA', // → "Warm Barely-There Cream" — Page BG
},
fontFamily: {
sans: ['Manrope', 'sans-serif'],
},
borderRadius: {
card: '12px',
button: '8px',
},
spacing: {
section: '5rem',
}
}
}
}
```
Map each custom value to a descriptive name and role.
## CSS Custom Properties
Look for `:root` or `html` blocks in global CSS:
```css
:root {
--color-primary: #294056;
--color-bg: #FCFAFA;
--font-heading: 'Manrope', sans-serif;
--radius-card: 12px;
--spacing-section: 5rem;
}
```
These are explicitly declared tokens — use their names as clues for
their intended role.
## Next.js Font Patterns
Next.js uses `next/font` for optimized font loading:
```tsx
import { Inter, Playfair_Display } from 'next/font/google'
const inter = Inter({ subsets: ['latin'], variable: '--font-inter' })
const playfair = Playfair_Display({ subsets: ['latin'], variable: '--font-display' })
```
The `variable` names hint at usage: `--font-display` for headlines,
`--font-inter` for body.
## Component Scanning Strategy
Don't read every component. Focus on these archetypes:
| Component Type | What to Extract |
|:---|:---|
| Layout / Shell | Max-width, padding, grid structure |
| Button / CTA | Border radius, colors, hover states, padding |
| Card | Shadow, border, radius, internal spacing |
| Nav / Header | Typography treatment, active states |
| Form / Input | Border, focus state, padding |
| Hero / Landing section | Spacing, typography scale, alignment |
For each, look at the `className` prop for Tailwind classes or the
`styled()` / `css()` calls for CSS-in-JS values.
## CSS-in-JS Patterns (styled-components / Emotion)
If the project uses CSS-in-JS, look for theme providers:
```tsx
// ThemeProvider wrapping the app
const theme = {
colors: {
primary: '#294056',
background: '#FCFAFA',
},
fonts: {
heading: 'Manrope, sans-serif',
},
radii: {
card: '12px',
button: '8px',
}
}
```
This theme object *is* the design system. Extract directly.
## Component Library Integration
If the project uses Chakra UI, Material UI, Ant Design, or shadcn/ui:
- **Chakra**: Look for `extendTheme()` calls — these override defaults.
- **MUI**: Look for `createTheme()` — palette, typography, and spacing overrides.
- **Ant Design**: Look for `ConfigProvider` theme prop or `theme.ts` overrides.
- **shadcn/ui**: Colors are defined as CSS custom properties in `globals.css`.
Check `components.json` for the style configuration.
The overrides are the design system — default values are the library's generic
styling and should be noted but not emphasized.
## Responsive Patterns
Check Tailwind's `screens` config and look for responsive class prefixes
(`sm:`, `md:`, `lg:`, `xl:`) in components:
```js
screens: {
sm: '640px', // Mobile landscape
md: '768px', // Tablet
lg: '1024px', // Desktop
xl: '1280px', // Large desktop
'2xl': '1536px'
}
```
Look for `container` configuration and `max-width` patterns on layout
components to determine content width strategy.
@@ -0,0 +1,101 @@
# Svelte / SvelteKit Extraction Patterns
Svelte co-locates styles even more tightly than Vue. Every `.svelte` file
has a `<style>` block that is scoped by default. Design systems in Svelte
projects typically live in global CSS, CSS custom properties, or a shared
theme store.
## File Discovery Order
1. **`src/app.css` / `src/app.postcss`** — Global styles and CSS custom
properties. The most important file.
2. **`svelte.config.js`** — May reference CSS preprocessors, Tailwind, or
UnoCSS configuration.
3. **`tailwind.config.js`** (if Tailwind/UnoCSS) — Same extraction as React.
4. **`src/lib/theme.ts` / `src/lib/tokens.ts`** — Shared design tokens
exported as JS objects.
5. **`src/routes/+layout.svelte`** — Root layout. Shows global font loading,
background, and structural patterns.
6. **Component `<style>` blocks** — Scoped styles revealing component patterns.
## Svelte Component Style Patterns
```svelte
<script>
export let variant = 'primary'
</script>
<button class="btn btn-{variant}">
<slot />
</button>
<style>
.btn {
border-radius: 8px;
padding: 0.875rem 2rem;
font-weight: 500;
transition: all 250ms ease-in-out;
}
.btn-primary {
background-color: var(--color-primary);
color: white;
}
.btn-primary:hover {
filter: brightness(0.9);
}
</style>
```
**Extraction points:**
- Component props (like `variant`) reveal the intended variant system
- `var(--*)` references → trace to `app.css`
- Transition values reveal the interaction design philosophy
## SvelteKit Layout Patterns
- **`+layout.svelte`** at route root — Global header, footer, font loading
- **`+layout.ts/js`** — May load theme data or tokens
- **`$lib/`** directory — Reusable components and shared utilities
## CSS Custom Properties Strategy
Svelte projects heavily use CSS custom properties for theming:
```css
/* app.css */
:root {
--color-primary: #294056;
--color-bg: #FCFAFA;
--color-surface: #F5F5F5;
--color-text: #2C2C2C;
--color-text-muted: #6B6B6B;
--font-heading: 'Manrope', sans-serif;
--font-body: 'Inter', sans-serif;
--radius-sm: 8px;
--radius-md: 12px;
--radius-full: 9999px;
--shadow-hover: 0 2px 8px rgba(0,0,0,0.06);
--spacing-section: 5rem;
}
```
These variable names are highly intentional. Use them as the foundation
of your design system extraction.
## Skeleton UI / DaisyUI / Flowbite-Svelte
If component libraries are used:
- **Skeleton UI**: Theme defined in `tailwind.config.js` using Skeleton's
design token system. Look for custom theme config object.
- **DaisyUI**: Theme in `tailwind.config.js``daisyui.themes` array.
- **Flowbite-Svelte**: Standard Tailwind theming.
@@ -0,0 +1,107 @@
# Vue / Nuxt Extraction Patterns
Vue projects have a distinctive styling architecture. Styles are often
co-located with components inside `<style>` blocks, and Nuxt adds
convention-based directories.
## File Discovery Order
1. **`nuxt.config.ts` / `nuxt.config.js`** — May contain global CSS paths,
font configuration, and Tailwind/UnoCSS module config.
2. **`assets/css/main.css`** (or similar) — Global styles, CSS custom
properties, and font imports.
3. **`tailwind.config.js`** (if Tailwind is used) — Same as React; extract
custom theme values directly.
4. **`plugins/vuetify.ts`** (if Vuetify) — Theme definition with custom
palette and typography.
5. **Component `<style>` blocks** — Co-located styles (scoped or global).
## Single-File Component (SFC) Patterns
Vue components bundle template, script, and style together:
```vue
<template>
<div class="card">
<h2 class="card__title">{{ title }}</h2>
</div>
</template>
<style scoped>
.card {
background: var(--color-surface);
border-radius: 12px;
padding: 2rem;
box-shadow: 0 2px 8px rgba(0,0,0,0.06);
}
.card__title {
font-size: 1.5rem;
font-weight: 600;
color: var(--color-text-primary);
}
</style>
```
**Key extraction points:**
- `var(--*)` references → trace back to global CSS for the actual values
- `scoped` styles → component-specific, but reveal consistent patterns
- BEM naming (`.card__title`) → hints at component hierarchy
## Vuetify Theme Extraction
Vuetify projects define their design system explicitly:
```ts
// plugins/vuetify.ts
export default createVuetify({
theme: {
defaultTheme: 'light',
themes: {
light: {
colors: {
primary: '#294056',
secondary: '#6B6B6B',
background: '#FCFAFA',
surface: '#F5F5F5',
error: '#EF4444',
success: '#10B981',
}
}
}
}
})
```
This is the design system declaration. Map each key to a functional role
and descriptive name.
## Quasar / PrimeVue / Element Plus
These component libraries use their own theming systems:
- **Quasar**: `quasar.config.js``framework.config.brand` for colors
- **PrimeVue**: CSS themes in `assets/` or theme preset configuration
- **Element Plus**: SCSS variables in `element-variables.scss`
Look for the override file — that's where the project's unique values live.
## CSS Scoping Behavior
Vue's `scoped` attribute adds data attributes for CSS isolation. When
scanning for patterns, look at multiple components to find repeated values
(same `border-radius`, similar `padding`, consistent color references).
Repeated patterns across scoped styles = design system conventions.
## Nuxt-Specific Patterns
- **`app.vue`** or **`layouts/default.vue`** — Root layout, reveals
global background, font loading, and overall structure.
- **`assets/`** — Global CSS, fonts, and images.
- **`composables/`** — May contain `useTheme` or `useDesignTokens`.
- **`nuxt.config.ts`** `css` array — Lists global stylesheets automatically
injected into every page.
@@ -0,0 +1,182 @@
---
name: stitch::extract-static-html
description: >-
Extract self-contained static HTML from a built web application or React components by inlining CSS and images. Use this skill whenever you need to capture a specific UI state, share a static version of a page, or prepare assets for Stitch upload, even if the user just asks to 'save the HTML' or 'mock the view'.
allowed-tools:
- "stitch*:*"
- "Bash"
- "Read"
- "Write"
- "web_fetch"
---
# Extract Static HTML
Extract a self-contained static HTML file from any web application.
## Which Strategy to Use
You MUST ask the user to choose which strategy to use before proceeding. Present the options clearly, **recommend Strategy A** as the preferred default, and **provide a brief pros/cons summary** for each option to help them make an informed decision.
| | Strategy A (Puppeteer) | Strategy B (Browser Subagent) |
| :--- | :--- | :--- |
| **When** | App runs locally, no auth wall | Need to interact with page first (click, fill forms) |
| **Fidelity** | **Highest — computed styles resolved** | High — rendered DOM |
| **Setup** | **Zero — no mock needed** | Zero — no mock needed |
| **Framework** | **Any** | Any |
| **Output** | **Writes to file — no size limit** | May truncate in agent context |
> [!WARNING]
> **Checkpoint — User Confirmation Required.**
> You **MUST** ask the user which strategy they prefer before proceeding.
> Present the comparison table above, recommend Strategy A as the default, and
> wait for explicit approval. Do **NOT** make the decision yourself or proceed
> until the user confirms.
***
## Strategy A: Puppeteer Snapshot (Recommended)
Launches headless Chrome, captures the fully rendered DOM, and produces a self-contained HTML file with all CSS inlined and images as base64. Works with **any framework** — no MockPage.jsx needed.
### Prerequisites
- App running locally (e.g., `npm run dev`)
- Node.js with `puppeteer` available (check: `node -e "require('puppeteer')"`)
### Workflow
1. **Start the App** and note the port.
> [!WARNING]
> **Checkpoint — User Confirmation Required.**
> After starting the local server, you **MUST** pause and ask the user for
> confirmation before running the snapshot script or launching a browser
> subagent. Report the URL and port to the user so they can verify the app
> is running and rendering correctly. Do **NOT** proceed to the snapshot
> step until the user confirms.
2. **Run the Snapshot Script**:
```bash
npx tsx <SKILL_DIR>/scripts/snapshot.ts \
--url http://localhost:5173 \
--output .stitch/home.html \
--wait 2000
```
3. **Multiple pages** — run once per route:
```bash
npx tsx <SKILL_DIR>/scripts/snapshot.ts \
--url http://localhost:5173 --output .stitch/home.html --wait 2000
npx tsx <SKILL_DIR>/scripts/snapshot.ts \
--url http://localhost:5173/pricing --output .stitch/pricing.html --wait 2000
npx tsx <SKILL_DIR>/scripts/snapshot.ts \
--url http://localhost:5173/dashboard --output .stitch/dashboard.html --wait 2000 --html-class dark
```
### Script Flags
| Flag | Default | Description |
| :--- | :--- | :--- |
| `--url` | *(required)* | URL to capture |
| `--output` | *(required)* | Output file path |
| `--wait` | `1000` | Extra wait (ms) after network idle. Increase for lazy-loading apps. |
| `--viewport` | `1280x800` | Viewport size as `WIDTHxHEIGHT` |
| `--html-class` | — | Class(es) for `<html>` element (e.g., `dark`) |
| `--remove-fixed` | `false` | Remove fixed/sticky elements (cookie banners, chat widgets) |
| `--full-height` | `false` | Resize viewport to full scroll height |
| `--title` | — | Override page title |
### What It Does Automatically
- Inlines all `<link rel="stylesheet">` → `<style>` blocks
- Converts `<img>` `src` **and `srcset`** → base64 data URIs (skips fonts)
- Inlines `<source srcset>` URLs as base64
- Removes failed/dead `srcset` entries so the browser falls back to the inlined `src`
- Removes `<script>` tags, Vite overlay, Next.js dev indicators
- Resolves relative CSS `url()` paths before inlining
### Framework Notes
| Framework | Notes |
| :--- | :--- |
| **React + Vite** | Works out of the box. `--wait 1000`. |
| **Next.js** | `--wait 3000` for SSR hydration. URL: `http://localhost:3000`. `<img srcset>` from `/_next/image` is auto-inlined as base64. |
| **Vue / Nuxt** | Works out of the box. |
| **Svelte / SvelteKit** | Works out of the box. |
| **Storybook** | Use story URL: `--url http://localhost:6006/?path=/story/...` |
| **SSR (Webpack)** | May need longer `--wait`. |
### Troubleshooting
| Issue | Solution |
| :--- | :--- |
| Images missing | Increase `--wait` |
| Images show as broken after server stops | Verify `srcset` was inlined — check log for "Inlined N images". If `srcset` URLs failed, they are auto-removed so `src` (inlined) is used. |
| Next.js `/_next/image` not inlined | Ensure the dev server is running when snapshot runs — the script fetches optimized images from the running server. |
| Dark mode not applied | `--html-class dark` |
| Cookie banner in output | `--remove-fixed` |
| Page requires login | Use the Static Fallback (appendix below) |
| `Cannot find module 'puppeteer'` | `npm install -g puppeteer` |
***
## Strategy B: Browser Subagent Capture
Use when you need to **interact with the page** (click buttons, fill forms, navigate tabs) before capturing. The browser subagent gives you full control but output may truncate for large pages.
### Workflow
1. **Start the App** locally.
2. **Navigate** using a browser subagent.
3. **Interact** as needed (click, scroll, fill forms).
4. **Extract DOM**: `document.documentElement.outerHTML`
> [!WARNING]
> Large pages may truncate. To handle this:
> - Remove `<style>` tags before extraction: `document.querySelectorAll('style').forEach(el => el.remove())`
> - Re-add styles statically (Tailwind CDN link, source CSS)
5. **Save** to file.
***
## Appendix: Static Fallback (MockPage.jsx)
> [!NOTE]
> This method is a **last resort** for when the app cannot run locally (broken deps, missing backend, auth walls with no bypass). It requires manually flattening React components into a single JSX file. **Prefer Strategy A whenever possible.**
### When to Use
- App can't run locally at all
- Page requires auth with no mock/bypass
- You need a specific UI state that's impossible to reach by navigation (error screens, empty states)
### Quick Reference
```bash
npx tsx <SKILL_DIR>/scripts/extract_inline_html.ts \
--index-css src/css/App.css \
--extra-css index.html \
--outdir .stitch \
--page src/MockPage.jsx:Page.html:"Page Title"
```
**Key flags**: `--no-tailwind` (non-Tailwind apps), `--html-class dark` (dark mode), `--css-files` (extra CSS files).
**Auto-detection**: Tailwind config is auto-detected. `@apply` directives automatically use `<style type="text/tailwindcss">`.
### MockPage.jsx Rules
1. **Include the full layout** — header, sidebar, footer (read `App.js` first)
2. **Flatten all conditionals** — pick one state, remove all ternaries and `&&` guards
3. **Hardcode all data** — replace `{variable}` with concrete values, unroll `.map()` loops
4. **Preserve logos** — use `<img>` with local paths (post-process will inline them)
5. **Remove floating elements** — cookie banners, chat widgets, feedback buttons
### Post-Processing
Inline local images:
```bash
npx tsx <SKILL_DIR>/scripts/post_process.ts \
.stitch/Page.html --base-dir <app-directory>
```
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,498 @@
#!/usr/bin/env npx tsx
/**
* post_process.ts — Inline local images as base64 in extracted HTML files.
*
* Scans HTML files for local image references (src attributes and CSS url()
* values) and replaces them with inline base64 data URIs. Uses a robust
* character-by-character CSS url() parser instead of regex.
*
* Usage:
* npx tsx post_process.ts .stitch/home.html --base-dir my-app
* npx tsx post_process.ts .stitch/page1.html .stitch/page2.html --base-dir .
* npx tsx post_process.ts .stitch/*.html --base-dir . --json
*
* Flags:
* --base-dir Base directory for resolving relative paths
* --json Output machine-readable JSON stats
* --dry-run Report what would be inlined without modifying files
* --max-size Max file size to inline in bytes (default: 5242880 / 5MB)
*/
import fs from 'node:fs';
import path from 'node:path';
// ---------------------------------------------------------------------------
// MIME type mapping
// ---------------------------------------------------------------------------
const MIME_MAP: Record<string, string> = {
'.svg': 'image/svg+xml',
'.jpeg': 'image/jpeg',
'.jpg': 'image/jpeg',
'.png': 'image/png',
'.gif': 'image/gif',
'.webp': 'image/webp',
'.ico': 'image/x-icon',
'.bmp': 'image/bmp',
'.avif': 'image/avif',
'.tiff': 'image/tiff',
'.tif': 'image/tiff',
'.apng': 'image/apng',
'.cur': 'image/x-icon',
};
function getMime(filePath: string): string {
return MIME_MAP[path.extname(filePath).toLowerCase()] || 'application/octet-stream';
}
// ---------------------------------------------------------------------------
// Types
// ---------------------------------------------------------------------------
interface Opts {
files: string[];
baseDir: string;
json: boolean;
dryRun: boolean;
maxSize: number;
}
interface CssUrlRef {
url: string;
fullMatch: string;
start: number;
end: number;
}
interface InlineStats {
srcInlined: number;
urlInlined: number;
skippedTooLarge: Array<{ path: string; size: number }>;
skippedNotFound: string[];
}
interface FileStats {
file: string;
srcInlined: number;
urlInlined: number;
skippedNotFound: number;
skippedTooLarge: number;
sizeBytes: number;
}
interface AllStats {
files: FileStats[];
totalSrcInlined: number;
totalUrlInlined: number;
totalSkippedNotFound: number;
totalSkippedTooLarge: number;
}
// ---------------------------------------------------------------------------
// Argument parsing & validation
// ---------------------------------------------------------------------------
function parseArgs(): Opts {
const args = process.argv.slice(2);
const opts: Opts = {
files: [],
baseDir: '',
json: false,
dryRun: false,
maxSize: 5 * 1024 * 1024, // 5MB
};
for (let i = 0; i < args.length; i++) {
switch (args[i]) {
case '--base-dir':
opts.baseDir = args[++i];
break;
case '--json':
opts.json = true;
break;
case '--dry-run':
opts.dryRun = true;
break;
case '--max-size':
opts.maxSize = parseInt(args[++i], 10);
break;
case '--help':
console.log(`
Usage: npx tsx post_process.ts <html_file> [...] [options]
Options:
--base-dir Base directory for resolving relative paths
--json Output machine-readable JSON stats
--dry-run Report what would be inlined without modifying files
--max-size Max file size to inline in bytes (default: 5242880 / 5MB)
`);
process.exit(0);
default:
opts.files.push(args[i]);
}
}
return opts;
}
function validateOpts(opts: Opts): void {
const errors: string[] = [];
if (opts.files.length === 0) {
errors.push('No HTML files specified');
}
if (opts.baseDir && !fs.existsSync(opts.baseDir)) {
errors.push(`Base directory not found: ${opts.baseDir}`);
}
if (isNaN(opts.maxSize) || opts.maxSize < 1) {
errors.push('--max-size must be a positive integer');
}
if (errors.length > 0) {
console.error('❌ Validation errors:');
errors.forEach((e) => console.error(`${e}`));
process.exit(1);
}
}
// ---------------------------------------------------------------------------
// Robust CSS url() parser — character-by-character (no regex)
// ---------------------------------------------------------------------------
function extractCssUrls(text: string): CssUrlRef[] {
const results: CssUrlRef[] = [];
let i = 0;
const len = text.length;
while (i < len) {
if (
i + 3 < len &&
text[i].toLowerCase() === 'u' &&
text[i + 1].toLowerCase() === 'r' &&
text[i + 2].toLowerCase() === 'l' &&
text[i + 3] === '('
) {
const urlStart = i;
i += 4;
// Skip whitespace
while (i < len && (text[i] === ' ' || text[i] === '\t' || text[i] === '\n' || text[i] === '\r')) i++;
let quote: string | null = null;
if (i < len && (text[i] === '"' || text[i] === "'")) {
quote = text[i];
i++;
}
let url = '';
if (quote) {
while (i < len && text[i] !== quote) {
if (text[i] === '\\' && i + 1 < len) {
i++;
url += text[i];
} else {
url += text[i];
}
i++;
}
if (i < len) i++;
} else {
while (i < len && text[i] !== ')' && text[i] !== ' ' && text[i] !== '\t' && text[i] !== '\n') {
url += text[i];
i++;
}
}
while (i < len && (text[i] === ' ' || text[i] === '\t' || text[i] === '\n' || text[i] === '\r')) i++;
if (i < len && text[i] === ')') {
const fullMatch = text.substring(urlStart, i + 1);
results.push({ url: url.trim(), fullMatch, start: urlStart, end: i + 1 });
i++;
} else {
i = urlStart + 1;
}
} else {
i++;
}
}
return results;
}
// ---------------------------------------------------------------------------
// Local path resolution
// ---------------------------------------------------------------------------
function resolveLocalFile(localPath: string, baseDir: string): string | null {
const candidates = [localPath];
if (baseDir) {
candidates.push(path.join(baseDir, localPath.replace(/^\//, '')));
}
for (const candidate of candidates) {
try {
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) {
return candidate;
}
} catch {
// Permission errors, etc. — skip
}
}
return null;
}
/**
* Atomically open, stat, and read a file using a file descriptor.
* Eliminates TOCTOU race conditions by performing all operations on the
* same fd, ensuring the file cannot change between the size check and read.
* Returns null if the file cannot be opened (e.g., deleted between resolve and open).
*/
function readFileAtomic(
filePath: string,
maxSize: number,
): { size: number; mime: string; b64: string } | { size: number; tooLarge: true } | null {
let fd: number;
try {
fd = fs.openSync(filePath, 'r');
} catch {
// File was removed or became inaccessible between resolve and open
return null;
}
try {
const stat = fs.fstatSync(fd);
if (stat.size > maxSize) {
return { size: stat.size, tooLarge: true };
}
const mime = getMime(filePath);
const b64 = fs.readFileSync(fd).toString('base64');
return { size: stat.size, mime, b64 };
} finally {
fs.closeSync(fd);
}
}
/**
* Check if a path is a local (non-remote, non-data) reference.
*/
function isLocalPath(url: string): boolean {
return (
!!url &&
!url.startsWith('http://') &&
!url.startsWith('https://') &&
!url.startsWith('data:') &&
!url.startsWith('//')
);
}
// ---------------------------------------------------------------------------
// Inline images in HTML
// ---------------------------------------------------------------------------
function inlineImages(
html: string,
baseDir: string,
maxSize: number,
dryRun: boolean,
): { html: string; stats: InlineStats } {
const stats: InlineStats = {
srcInlined: 0,
urlInlined: 0,
skippedTooLarge: [],
skippedNotFound: [],
};
// --- Inline src="<local_path>" attributes ---
// Handle src, poster, data attributes
const srcAttrs = ['src', 'poster', 'data'];
for (const attr of srcAttrs) {
const regex = new RegExp(`${attr}="((?!https?:\\/\\/|data:|\\/\\/)[^"]+)"`, 'g');
html = html.replace(regex, (match: string, localPath: string) => {
const resolved = resolveLocalFile(localPath, baseDir);
if (!resolved) {
if (!localPath.endsWith('.js') && !localPath.endsWith('.css')) {
stats.skippedNotFound.push(localPath);
}
return match;
}
const result = readFileAtomic(resolved, maxSize);
if (!result) {
stats.skippedNotFound.push(localPath);
return match;
}
if ('tooLarge' in result) {
stats.skippedTooLarge.push({ path: localPath, size: result.size });
return match;
}
if (dryRun) {
stats.srcInlined++;
return match;
}
stats.srcInlined++;
return `${attr}="data:${result.mime};base64,${result.b64}"`;
});
}
// --- Inline CSS url() with local paths (using robust parser) ---
const urlRefs = extractCssUrls(html);
const localUrlRefs = urlRefs.filter((ref) => isLocalPath(ref.url));
// Process from end to preserve indices
const sorted = [...localUrlRefs].sort((a, b) => b.start - a.start);
for (const ref of sorted) {
const resolved = resolveLocalFile(ref.url, baseDir);
if (!resolved) {
stats.skippedNotFound.push(ref.url);
continue;
}
const result = readFileAtomic(resolved, maxSize);
if (!result) {
stats.skippedNotFound.push(ref.url);
continue;
}
if ('tooLarge' in result) {
stats.skippedTooLarge.push({ path: ref.url, size: result.size });
continue;
}
if (dryRun) {
stats.urlInlined++;
continue;
}
html =
html.substring(0, ref.start) +
`url('data:${result.mime};base64,${result.b64}')` +
html.substring(ref.end);
stats.urlInlined++;
}
// --- Inline SVG <image href="..."> and xlink:href ---
const svgHrefRegex = /(href|xlink:href)="((?!https?:\/\/|data:|\/\/)[^"]+)"/g;
html = html.replace(svgHrefRegex, (match: string, attrName: string, localPath: string) => {
// Skip non-image hrefs (like <a href>)
if (!localPath.match(/\.(svg|png|jpg|jpeg|gif|webp|avif|bmp|ico)$/i)) {
return match;
}
const resolved = resolveLocalFile(localPath, baseDir);
if (!resolved) {
stats.skippedNotFound.push(localPath);
return match;
}
const result = readFileAtomic(resolved, maxSize);
if (!result) {
stats.skippedNotFound.push(localPath);
return match;
}
if ('tooLarge' in result) {
stats.skippedTooLarge.push({ path: localPath, size: result.size });
return match;
}
if (dryRun) {
stats.srcInlined++;
return match;
}
stats.srcInlined++;
return `${attrName}="data:${result.mime};base64,${result.b64}"`;
});
return { html, stats };
}
// ---------------------------------------------------------------------------
// Main
// ---------------------------------------------------------------------------
function main(): void {
const opts = parseArgs();
validateOpts(opts);
const allStats: AllStats = {
files: [],
totalSrcInlined: 0,
totalUrlInlined: 0,
totalSkippedNotFound: 0,
totalSkippedTooLarge: 0,
};
if (opts.dryRun) {
console.log('🔍 DRY RUN — no files will be modified\n');
}
for (const file of opts.files) {
// Open file once with r+ to eliminate TOCTOU race between read and write.
// A single fd is used for both operations, so the file cannot be swapped
// between the read and write phases.
let fd: number;
try {
fd = fs.openSync(file, opts.dryRun ? 'r' : 'r+');
} catch {
console.warn(`⚠️ File not found, skipping: ${file}`);
continue;
}
let processed: string = '';
let stats: InlineStats = { srcInlined: 0, urlInlined: 0, skippedTooLarge: [], skippedNotFound: [] };
try {
const html = fs.readFileSync(fd, 'utf-8');
const result = inlineImages(html, opts.baseDir, opts.maxSize, opts.dryRun);
processed = result.html;
stats = result.stats;
if (!opts.dryRun) {
// Truncate and rewrite using the same fd — no second path-based open
fs.ftruncateSync(fd);
fs.writeSync(fd, processed, 0, 'utf-8');
}
} finally {
fs.closeSync(fd);
}
const totalInlined = stats.srcInlined + stats.urlInlined;
const label = opts.dryRun ? 'would inline' : 'inlined';
console.log(
`${file}: ${label} ${totalInlined} resources ` +
`(${stats.srcInlined} src, ${stats.urlInlined} url()) ` +
`${processed.length.toLocaleString()} bytes`,
);
if (stats.skippedTooLarge.length > 0) {
for (const s of stats.skippedTooLarge) {
console.log(
` ⚠️ Skipped (too large: ${(s.size / 1024).toFixed(1)} KB): ${s.path}`,
);
}
}
allStats.files.push({
file,
srcInlined: stats.srcInlined,
urlInlined: stats.urlInlined,
skippedNotFound: stats.skippedNotFound.length,
skippedTooLarge: stats.skippedTooLarge.length,
sizeBytes: processed.length,
});
allStats.totalSrcInlined += stats.srcInlined;
allStats.totalUrlInlined += stats.urlInlined;
allStats.totalSkippedNotFound += stats.skippedNotFound.length;
allStats.totalSkippedTooLarge += stats.skippedTooLarge.length;
}
const totalInlined = allStats.totalSrcInlined + allStats.totalUrlInlined;
console.log(`\n✅ Total: ${totalInlined} resources inlined across ${allStats.files.length} file(s)`);
if (allStats.totalSkippedTooLarge > 0) {
console.log(` ⚠️ ${allStats.totalSkippedTooLarge} skipped (exceeded ${(opts.maxSize / 1024 / 1024).toFixed(1)} MB limit)`);
}
if (opts.json) {
console.log('\n--- JSON Stats ---');
console.log(JSON.stringify(allStats, null, 2));
}
}
main();
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,339 @@
---
name: stitch::generate-design
description: >-
Generate new screens from text prompts or images, edit existing screens
with prompts and design system tokens, and generate design variants using
Stitch MCP. Includes prompt enhancement pipeline, design mappings, professional
UI/UX terminology, design tokens and theme system capabilities.
allowed-tools:
- "stitch*:*"
- "Bash"
- "Read"
- "Write"
- "web_fetch"
---
# Generate Design
Create new design screens from text descriptions, images, or mockups, edit
existing screens with prompts and design system tokens, and generate design
variants using Stitch MCP.
> [!NOTE]
> Refer to your system prompt for instruction on handling MCP tool prefixes for
> all tools mentioned in this skill (e.g., `list_projects`,
> `generate_screen_from_text`, `edit_screens`).
## 🎨 Prompt Enhancement Pipeline
Before calling any Stitch generation or editing tool, you MUST enhance the
user's prompt.
### 1. Analyze Context
- **Project**: Use `list_projects` to find the correct `projectId`. If no
suitable project exists, create one using `create_project`.
- **Design System**: Check if a design system exists for the project via
`list_design_systems`. If one exists, design tokens (colors, fonts, roundness)
are already applied at the project level — do NOT include any color, font, or
theme instructions in the generation prompt. If none exists, delegate to the
**manage-design-system** skill first before generating screens.
### 2. Refine UI/UX Terminology
Consult [Design Mappings](references/design-mappings.md) to replace vague terms.
- Vague: "Make a nice header"
- Professional: "Sticky navigation bar with glassmorphism effect and centered
logo"
Use [Prompting Keywords](references/prompt-keywords.md) for component names,
adjective palettes, color roles, and shape descriptions.
### 3. Structure the Final Prompt
Format the enhanced prompt for Stitch. Focus exclusively on **layout, content,
and structure** — never include colors, fonts, or theme instructions (these are
handled by the manage-design-system skill at the project level).
For **new screens**, use this template:
```markdown
[Overall purpose and user intent of the page]
**PLATFORM:** [Web/Mobile], [Desktop/Mobile]-first
**PAGE STRUCTURE:**
1. **Header:** [Description of navigation and branding]
2. **Hero Section:** [Headline, subtext, and primary CTA]
3. **Primary Content Area:** [Detailed component breakdown]
4. **Footer:** [Links and copyright information]
```
For **edits**, be specific about what to change:
- **Location**: "Change the [primary button] in the [hero section]..."
- **Visuals**: "...to a darker blue (#004080) and add a subtle shadow."
- **Structure**: "Add a secondary button next to the primary one with the text
'Learn More'."
> [!CAUTION]
> Do NOT include hex codes, font names, color palettes, roundness values, or
> any design system tokens in a **generation** prompt. These are applied at the
> project level by the manage-design-system skill and will conflict if
> duplicated. (For **edit** prompts, hex codes are acceptable for precise
> color adjustments.)
### 4. Present AI Insights
After any tool call, always surface the `outputComponents` (Text Description and
Suggestions) to the user.
See [examples/enhanced-prompt.md](examples/enhanced-prompt.md) for a full
before/after prompt enhancement example.
--------------------------------------------------------------------------------
## Steps
### Determine the Mode
Decide which flow to use based on the user's request:
- User wants to create from a text description → **Generate from Text** flow
- User provides an image, screenshot, or mockup → **Generate from Image** flow
- User wants to modify an existing screen → **Edit** flow
- User wants layout/color/content variations → **Generate Variants** flow
---
### Generate from Text Flow (New Screen)
#### 1. Enhance the User Prompt
Apply the Prompt Enhancement Pipeline above.
#### 2. Identify the Project
Use `list_projects` to find the correct `projectId` if it is not already known.
#### 3. Generate the Screen
Call the `generate_screen_from_text` tool with the enhanced prompt and the
`designSystem` ID (if found in Step 1).
```json
{
"projectId": "...",
"prompt": "[Your Enhanced Prompt]",
"designSystem": "assets/...", // Optional: Pass if found in Step 1
"deviceType": "DESKTOP" // Options: MOBILE, DESKTOP, TABLET
}
```
#### 4. Present AI Feedback
Always show the text description and suggestions from `outputComponents` to the
user.
#### 5. Download Design Assets
After generation, download the HTML and screenshot urls from `outputComponents`
to the `.stitch/designs` directory.
- **Naming**: Use the screen ID or a descriptive slug for the filename.
- **Tools**: Use `curl -o` via `run_command` or similar.
- **Directory**: Ensure `.stitch/designs` exists.
#### 6. Review and Refine
- If the result is not exactly as expected, continue with the **Edit** flow
to make targeted adjustments.
- Do NOT re-generate from scratch unless the fundamental layout is wrong.
---
### Generate from Image Flow (Image/Mockup → Design)
Use this flow when the user provides an image, screenshot, or design mockup to
recreate in Stitch.
#### 1. Identify the Project
Use `list_projects` to find the correct `projectId`. If no suitable project
exists, create one using `create_project`.
#### 2. Upload the Image
Delegate to the **upload-to-stitch** skill to upload the image to the project.
This creates a new screen with the image as its content.
#### 3. Refine with Edit
Once uploaded, use `list_screens` to find the newly created `screenId`, then
call `edit_screens` with a descriptive prompt to refine the design:
```json
{
"projectId": "...",
"selectedScreenIds": ["<uploaded-screen-id>"],
"prompt": "[Describe what to adjust, enhance, or recreate from this mockup]"
}
```
> [!TIP]
> For best results, describe the intent behind the image rather than just saying
> "make it look like this". For example: "This is a dashboard mockup — recreate
> it with a proper data table, sidebar navigation, and chart widgets."
#### 4. Present AI Feedback
Always show the text description and suggestions from `outputComponents` to the
user.
#### 5. Download Design Assets
Download the HTML and screenshot urls from `outputComponents` to the
`.stitch/designs` directory.
- **Naming**: Use the screen ID or a descriptive slug for the filename.
- **Tools**: Use `curl -o` via `run_command` or similar.
- **Directory**: Ensure `.stitch/designs` exists.
---
### Edit Flow (Modify Existing Screen)
#### 1. Identify the Screen
Use `list_screens` or `get_screen` to find the correct `projectId` and
`screenId`.
#### 2. Formulate the Edit Prompt
Apply the Prompt Enhancement Pipeline, focusing on specificity:
- **Location**: "Change the color of the [primary button] in the [hero
section]..."
- **Visuals**: "...to a darker blue (#004080) and add a subtle shadow."
- **Structure**: "Add a secondary button next to the primary one with the text
'Learn More'."
#### 3. Apply the Edit
Call the `edit_screens` tool.
```json
{
"projectId": "...",
"selectedScreenIds": ["..."],
"prompt": "[Your targeted edit prompt]"
}
```
#### 4. Present AI Feedback
Always show the text description and suggestions from `outputComponents` to the
user.
#### 5. Download Design Assets
After editing, download the updated HTML and screenshot urls from
`outputComponents` to the `.stitch/designs` directory, overwriting previous
versions to ensure the local files reflect the latest edits.
- **Naming**: Use the screen ID or a descriptive slug for the filename.
- **Tools**: Use `curl -o` via `run_command` or similar.
- **Directory**: Ensure `.stitch/designs` exists.
#### 6. Update Project Metadata
After downloading assets, update `.stitch/metadata.json` to reflect any changes
(e.g., updated screen titles or new screen IDs from the edit). The metadata
file tracks all screens, their device types, and design system info. See the
**manage-design-system** skill's `examples/metadata.json` for the format.
#### 7. Verify and Repeat
- Check the output screen to see if the changes were applied correctly.
- If more polish is needed, repeat the edit flow with a new specific prompt.
---
### Generate Variants Flow (Explore Variations)
Use this flow when the user wants to explore alternative layouts, color schemes,
or content variations of an existing screen.
#### 1. Identify the Screen
Use `list_screens` or `get_screen` to find the correct `projectId` and
`screenId`.
#### 2. Configure Variant Options
Call the `generate_variants` tool with the appropriate options:
```json
{
"projectId": "...",
"selectedScreenIds": ["..."],
"prompt": "[Describe the direction for variants]",
"variantOptions": {
"variantCount": 3,
"creativeRange": "EXPLORE",
"aspects": ["LAYOUT", "COLOR_SCHEME"]
}
}
```
**Variant Options:**
- **`variantCount`**: 15 variants (default: 3)
- **`creativeRange`**: `REFINE` (subtle), `EXPLORE` (balanced), or `REIMAGINE`
(radical)
- **`aspects`**: Focus on specific dimensions — `LAYOUT`, `COLOR_SCHEME`,
`IMAGES`, `TEXT_FONT`, `TEXT_CONTENT`, or leave empty for all
#### 3. Present AI Feedback
Always show the text description and suggestions from `outputComponents` to the
user.
#### 4. Download Design Assets
Download the variant HTML and screenshot urls from `outputComponents` to the
`.stitch/designs` directory.
- **Naming**: Use the screen ID or a descriptive slug for the filename.
- **Tools**: Use `curl -o` via `run_command` or similar.
- **Directory**: Ensure `.stitch/designs` exists.
--------------------------------------------------------------------------------
## 💡 Tips
- **Be structural**: Break the page down into header, hero, features, and
footer in your prompt.
- **Content first**: Describe what each section contains (text, images, CTAs)
rather than how it looks.
- **Iterative Polish**: Prefer editing for targeted adjustments over full
re-generation.
- **No theme leakage**: Never put hex codes, font names, or color roles in a
generation prompt — the design system handles all visual styling.
- **Specify interactions**: Mention hover states, animations, and click behavior
rather than visual styling.
- **Keep edits focused**: One edit at a time is often better than a long list of
changes.
- **Reference components**: Use professional terms like "navigation bar", "hero
section", "footer", "card grid".
- **Precise colors in edits**: Use hex codes for exact color matching when
editing existing screens.
## 📚 References
- [Design Mappings](references/design-mappings.md) — UI/UX keywords and
atmosphere descriptors.
- [Prompting Keywords](references/prompt-keywords.md) — Technical terms Stitch
understands best.
- [Enhanced Prompt Example](examples/enhanced-prompt.md) — Before/after prompt
enhancement.
@@ -0,0 +1,41 @@
# Example: Prompt Enhancement
## User Input (Vague)
> "Make a landing page for my fitness app called 'Pulse'. It should have a
> place for features and a hero section."
---
## Enhanced Prompt (Stitch-Optimized)
> [!NOTE]
> This prompt contains NO colors, fonts, or theme instructions — those are
> handled by the project's design system. The prompt focuses exclusively on
> layout, structure, and content.
**Overall Purpose**: A high-energy, modern landing page for 'Pulse', a fitness
tracking application. The page should feel powerful, motivating, and
high-performance.
**PLATFORM:** Web, Desktop-first
**PAGE STRUCTURE:**
1. **Header**: Minimalist navigation with Pulse logo (left) and "Start Training"
primary call-to-action button (right).
2. **Hero Section**: Large, emotive fitness photography background. Headline:
"Elevate Every Beat." Sub-headline: "Track, analyze, and crush your fitness
goals with Pulse." Primary CTA button: "Get Started".
3. **Feature Grid**: Three-column responsive card grid highlighting:
- **Real-time Tracking**: Live stats from your wearable.
- **AI Coaching**: Personalized workouts based on your performance.
- **Community Challenges**: Compete with friends and stay motivated.
4. **Social Proof Section**: Horizontal slider showing "Trusted by 500,000+
athletes" with partner logos.
5. **Footer**: Quick links (Training, Pricing, Support), social icons, and
legal text.
---
💡 **Tip**: Notice how the enhanced prompt describes **structure and content**
without specifying hex codes, font families, or color roles. The design system
(created via the manage-design-system skill) handles all visual theming at the project
level.
@@ -1,6 +1,7 @@
# Design Mappings & Descriptors
Use these mappings to transform vague user requests into precise, high-fidelity design instructions.
Use these mappings to transform vague user requests into precise, high-fidelity
design instructions.
## UI/UX Keyword Refinement
@@ -1,16 +1,19 @@
# UI/UX Keywords Reference
Progressive disclosure reference for common UI terminology and adjective palettes.
Progressive disclosure reference for common UI terminology and adjective
palettes.
## Component Keywords
### Navigation
- navigation bar, nav menu, header
- breadcrumbs, tabs, sidebar
- hamburger menu, dropdown menu
- back button, close button
### Content Containers
- hero section, hero banner
- card, card grid, tile
- modal, dialog, popup
@@ -18,6 +21,7 @@ Progressive disclosure reference for common UI terminology and adjective palette
- carousel, slider
### Forms
- input field, text input
- dropdown, select menu
- checkbox, radio button
@@ -27,18 +31,21 @@ Progressive disclosure reference for common UI terminology and adjective palette
- submit button, form actions
### Calls to Action
- primary button, secondary button
- ghost button, text link
- floating action button (FAB)
- icon button
### Feedback
- toast notification, snackbar
- alert banner, warning message
- loading spinner, skeleton loader
- progress bar, step indicator
### Layout
- grid layout, flexbox
- sidebar layout, split view
- sticky header, fixed footer
@@ -48,59 +55,69 @@ Progressive disclosure reference for common UI terminology and adjective palette
## Adjective Palettes
### Minimal / Clean
- minimal, clean, uncluttered
- generous whitespace, breathing room
- subtle, understated, refined
- simple, focused, distraction-free
### Professional / Corporate
- sophisticated, polished, trustworthy
- corporate, business-like, formal
- subtle shadows, clean lines
- structured, organized, hierarchical
### Playful / Fun
- vibrant, colorful, energetic
- rounded corners, soft edges
- bold, expressive, dynamic
- friendly, approachable, warm
### Premium / Luxury
- elegant, luxurious, high-end
- dramatic, bold contrasts
- sleek, modern, cutting-edge
- exclusive, boutique, curated
### Dark Mode
- dark theme, night mode
- high-contrast accents
- soft glows, subtle highlights
- deep backgrounds, muted surfaces
### Organic / Natural
- earthy tones, natural colors
- warm, inviting, cozy
- textured, tactile, handcrafted
- flowing, organic shapes
## Color Role Terminology
## Interaction & Behavior Keywords
### Backgrounds
- page background, canvas
- surface color, card background
- overlay, scrim
### Animations
### Text
- primary text, heading color
- secondary text, body copy
- muted text, placeholder
- inverse text (on dark backgrounds)
- smooth entry animation, slide-in
- fade transition, cross-fade
- micro-interaction, bounce effect
- skeleton loader, shimmer effect
### Accents
- primary accent, brand color
- secondary accent, highlight
- success, error, warning colors
- hover state, active state
### Responsiveness
- responsive layout, adaptive grid
- mobile-first, desktop-first
- breakpoint, viewport
- stacked layout, side-by-side
### User Flows
- progressive disclosure, step indicator
- expandable section, collapsible panel
- infinite scroll, pagination
- drag and drop, swipe gesture
## Shape Descriptions
@@ -0,0 +1,125 @@
---
name: stitch::manage-design-system
description: >-
Manage design systems in Stitch using MCP tools. Includes retrieval of assets,
creating/updating design systems in Stitch, and applying them to screens.
allowed-tools:
- "stitch*:*"
- "Bash"
- "Read"
- "Write"
- "web_fetch"
---
# Design-System
Create a "source of truth" for your project's design language to ensure
consistency across all future screens.
> [!NOTE]
> Refer to your system prompt for instruction on handling MCP tool prefixes for
> all tools mentioned in this skill (e.g., `get_screen`,
> `create_design_system_from_design_md`, `apply_design_system`).
## 📥 Retrieval
To analyze a Stitch project, you must retrieve metadata and assets using the
Stitch MCP tools:
1. **Project lookup**: Use `list_projects` to find the target `projectId`.
2. **Screen lookup**: Use `list_screens` for that `projectId` to find
representative screens (e.g., "Home", "Main Dashboard").
3. **Metadata fetch**: Call `get_screen` for the target screen to get
`screenshot.downloadUrl` and `htmlCode.downloadUrl`.
4. **Asset download**: Use `read_url_content` to fetch the HTML code.
## 🧠 Synthesis from Description
If you need to extract a design system from existing screens, use the `design-md` skill (in the `stitch-utilities` plugin).
If there are no existing screens (new project), or the user provides a direct description (e.g., "dark theme, blue and purple, rounded, Inter font"):
1. Map the user's vague terms to precise values using the design mappings (see `design-md` skill in `stitch-utilities` or `generate-design` skill).
2. Select concrete hex codes, font families, and roundness values.
3. Generate the `DESIGN.md` file (refer to the `design-md` skill in `stitch-utilities` for structure).
4. Proceed to the "Create or Update Design System in Stitch" step below.
## 📝 Output Structure
The `DESIGN.md` file should follow the structure defined in the `design-md` skill (in the `stitch-utilities` plugin).
## 🚀 Create or Update Design System in Stitch
After generating `.stitch/DESIGN.md`, make sure to also create or update the
design system in Stitch.
**Two-step design system creation:**
> [!WARNING]
> **Checkpoint — User Confirmation Required.**
> Before uploading, you **MUST** pause and ask the user for
> confirmation. Present a summary of the design system you are about to create
> (display name, key colors, fonts, and roundness) and wait for explicit approval
> before proceeding. Do **NOT** upload until the user confirms.
1. **Upload `DESIGN.md`**:
- **Option A (Recommended - Uploader Script)**: Use the modified `upload-to-stitch` Python script which natively handles `.md` files. It base64-encodes the markdown file in-process and sends it to the `/v1/projects/{projectId}/screens:batchCreate` endpoint, bypassing output token limits.
```bash
python3 stitch-skills/plugins/stitch-design/skills/upload-to-stitch/scripts/upload_to_stitch.py \
--project-id <PROJECT_ID> \
--file-path /path/to/DESIGN.md \
--api-key <API_KEY>
```
This returns the `sourceScreen` ID and the `screenInstance` ID.
- **Option B (Direct MCP Tool)**: If the `DESIGN.md` is small (under ~5KB), you can call the `upload_design_md` MCP tool directly, passing the base64-encoded design markdown content as `designMdBase64`.
2. **Create Design System**: Call the `create_design_system_from_design_md` tool immediately after the upload, passing the `projectId` and the `selectedScreenInstance` (containing the `id` and `sourceScreen` returned from the upload step).
Once the upload script and `create_design_system_from_design_md` have both completed,
Stitch holds the design tokens at the project level — you do NOT need to repeat
them in generation prompts.
## 🎨 Apply Design System to Screens
Use `apply_design_system` to apply a design system to existing screens.
> [!IMPORTANT]
> `selectedScreenInstances` must contain **only** `id` and `sourceScreen` — do
> NOT include position/dimension fields (`x`, `y`, `width`, `height`) or the
> request will fail with "invalid argument". Get the screen instance IDs from
> `get_project`.
```json
{
"projectId": "...",
"assetId": "...",
"selectedScreenInstances": [
{
"id": "...",
"sourceScreen": "projects/.../screens/..."
}
]
}
```
**How to get the required IDs:**
1. Call `get_project` to retrieve `screenInstances` — each has an `id` and
`sourceScreen`.
2. Call `list_design_systems` to retrieve the design system `name` (format:
`assets/{assetId}`) — use the part after `assets/` as the `assetId`.
3. Filter out any instances with `type: "DESIGN_SYSTEM_INSTANCE"` — only pass
real screens.
## 📋 Update Project Metadata
After writing `.stitch/DESIGN.md`, also create or update `.stitch/metadata.json`
to track the `projectId`, `title`, all known screens, and design system summary.
See [examples/metadata.json](examples/metadata.json) for the format.
## Schema Reference
See [reference/tool-schema.md](reference/tool-schema.md) for the full
`designSystem` object schema with all available options.
## 💡 Best Practices
Refer to the `design-md` skill (in the `stitch-utilities` plugin) for best practices on describing design elements.
@@ -14,9 +14,10 @@
}
],
"designSystem": {
"assetId": "15996705518239280238",
"primaryColor": "#1a365d",
"secondaryColor": "#718096",
"backgroundColor": "#f7fafc",
"fontFamily": "Inter, sans-serif"
"fontFamily": "INTER"
}
}
@@ -0,0 +1,162 @@
# Design System Tool Schemas
Use these examples to format your Stitch MCP design system tool calls correctly.
---
## Upload `DESIGN.md` (via `upload_to_stitch.py` script)
Uploads a `DESIGN.md` file to a project via the `BatchCreateScreens` endpoint.
This is the first step in creating a design system from a markdown file.
> [!NOTE]
> Use the `upload-to-stitch` skill's script instead of the `upload_design_md`
> MCP tool. The script handles base64 encoding in-process, avoiding the model's
> output token limit.
```bash
python3 <SKILL_DIR>/scripts/upload_to_stitch.py \
--project-id <PROJECT_ID> \
--file-path /path/to/DESIGN.md \
--api-key <API_KEY>
```
---
## `create_design_system_from_design_md`
Creates a design system for a project using the uploaded `DESIGN.md` file.
```json
{
"projectId": "4044680601076201931",
"selectedScreenInstance": {
"id": "98b50e2ddc9943efb387052637738f61",
"sourceScreen": "projects/4044680601076201931/screens/98b50e2ddc9943efb387052637738f61"
},
"deviceType": "DESKTOP"
}
```
> [!NOTE]
> You must upload `DESIGN.md` via the script first to get the source screen ID, and then fetch the project details with `get_project` to find the corresponding screen instance ID to pass as `id` in `selectedScreenInstance`.
---
## `update_design_system`
Updates an existing design system for a project. This is **required** immediately after calling `create_design_system` to set the theme and display the design system in the UI.
> [!NOTE]
> While `update_design_system` is mandatory after the basic `create_design_system` call, you do **not** need to call it after `create_design_system_from_design_md`. The latter automatically populates and updates all theme tokens directly from the parsed YAML frontmatter of the uploaded `DESIGN.md`.
```json
{
"name": "assets/15996705518239280238",
"projectId": "4044680601076201931",
"designSystem": {
"displayName": "My Design System", // OPTIONAL. Display name of the design system
"theme": { // REQUIRED. The design theme object
"colorMode": "LIGHT", // REQUIRED. Options: LIGHT, DARK
"headlineFont": "INTER", // REQUIRED. Options: INTER, ROBOTO, OPEN_SANS, LATO, MONTSERRAT, NOTO_SANS, NOTO_SERIF, etc.
"bodyFont": "INTER", // REQUIRED. Same font options as headlineFont
"labelFont": "INTER", // OPTIONAL. Same font options as headlineFont
"roundness": "ROUND_EIGHT", // REQUIRED. Options: ROUND_FOUR, ROUND_EIGHT, ROUND_TWELVE, ROUND_FULL
"customColor": "#0EA5E9", // REQUIRED. Primary brand color / seed color for dynamic color system (hex)
"colorVariant": "FIDELITY", // OPTIONAL. Options: FIDELITY, TONAL, VIBRANT, EXPRESSIVE, CONTENT, MONOCHROME, FRUIT_SALAD, RAINBOW
"overridePrimaryColor": "#996e47", // OPTIONAL. Override primary color (hex)
"overrideSecondaryColor": "#0EA5E9", // OPTIONAL. Override secondary color (hex)
"overrideTertiaryColor": "#c4956a", // OPTIONAL. Override tertiary color (hex)
"overrideNeutralColor": "#0D0D0D", // OPTIONAL. Override neutral color (hex)
"designMd": "# Design System..." // OPTIONAL. Markdown string with detailed design system spec
}
}
}
```
### Field Reference
#### Required Fields
| Field | Type | Description |
|:------|:-----|:------------|
| `colorMode` | enum | `LIGHT` or `DARK` |
| `headlineFont` | enum | Font for headlines and display text. See font options below. |
| `bodyFont` | enum | Font for body text. See font options below. |
| `roundness` | enum | `ROUND_FOUR`, `ROUND_EIGHT`, `ROUND_TWELVE`, `ROUND_FULL` |
| `customColor` | hex | Primary brand / seed color for the dynamic color system (e.g., `#E8732A`) |
#### Optional Fields
| Field | Type | Description |
|:------|:-----|:------------|
| `displayName` | string | Human-readable name for the design system |
| `labelFont` | enum | Font for labels and captions. Defaults to `bodyFont` if omitted. |
| `colorVariant` | enum | `FIDELITY`, `TONAL`, `VIBRANT`, `EXPRESSIVE`, `CONTENT`, `MONOCHROME`, `FRUIT_SALAD`, `RAINBOW` |
| `overridePrimaryColor` | hex | Override primary color (e.g., `#E8732A`) |
| `overrideSecondaryColor` | hex | Override secondary color (e.g., `#1B6B93`) |
| `overrideTertiaryColor` | hex | Override tertiary color (e.g., `#F2A541`) |
| `overrideNeutralColor` | hex | Override neutral color (e.g., `#FAF7F2`) |
| `spacingScale` | integer | Spacing scale factor (observed value: `3`) |
| `designMd` | string | Markdown string with detailed design system specifications |
#### Font Options
The following font enum values are confirmed to work (server-validated):
| Value | Font Name |
|:------|:----------|
| `INTER` | Inter |
| `ROBOTO` | Roboto |
| `OPEN_SANS` | Open Sans |
| `LATO` | Lato |
| `MONTSERRAT` | Montserrat |
| `NOTO_SANS` | Noto Sans |
| `NOTO_SERIF` | Noto Serif |
| `PLUS_JAKARTA_SANS` | Plus Jakarta Sans |
| `BE_VIETNAM_PRO` | Be Vietnam Pro |
> [!WARNING]
> Omit the legacy `font` field when updating the design system to avoid "invalid argument" errors.
> [!NOTE]
> The `namedColors` object above is abbreviated. The full response contains 50+
> Material 3 color tokens including all container, fixed, and inverse variants.
---
## `apply_design_system`
Applies a design system to one or more screens in a project.
> [!IMPORTANT]
> `selectedScreenInstances` must contain **only** `id` and `sourceScreen` — do NOT
> include position/dimension fields (`x`, `y`, `width`, `height`) or the request
> will fail with "invalid argument". Get the screen instance IDs from
> `get_project`.
```json
{
"projectId": "4044680601076201931",
"assetId": "c277fcdfc1e04baf91b92d975ff4c54a",
"selectedScreenInstances": [
{
"id": "98b50e2ddc9943efb387052637738f61",
"sourceScreen": "projects/4044680601076201931/screens/98b50e2ddc9943efb387052637738f61"
},
{
"id": "ab12cd34ef56789012345678abcdef01",
"sourceScreen": "projects/4044680601076201931/screens/ab12cd34ef56789012345678abcdef01"
}
]
}
```
**How to get the required IDs:**
1. Call `get_project` to retrieve `screenInstances` — each has an `id` and
`sourceScreen`.
2. Call `list_design_systems` to retrieve the design system `name` (format:
`assets/{assetId}`) — use the part after `assets/` as the `assetId`.
3. Filter out any instances with `type: "DESIGN_SYSTEM_INSTANCE"` — only pass
real screens.
@@ -0,0 +1,93 @@
---
name: stitch::upload-to-stitch
description: >-
Upload local assets (images, mockups, extracted HTML) to a Stitch project.
ALWAYS use this skill when you need to upload visual assets or full HTML pages
to Stitch, particularly when direct MCP tool calls fail or truncate due to
base64 token limits.
allowed-tools:
- "stitch*:*"
- "Bash"
- "Read"
- "Write"
- "web_fetch"
---
# Upload-to-Stitch
Upload local assets (images, mockups, HTML files) to a Stitch project using the
provided upload script, which bypasses the MCP tool's base64 output token limits.
> [!NOTE]
> The AI model cannot upload files via MCP tools directly because the base64
> encoding of even a small file exceeds the model's output token limit (~16K
> tokens). This script reads the file and sends it directly over HTTP.
## Steps
### 1. Identify Target Project
Use `list_projects` to find the correct `projectId`.
### 2. Get the API Key
Locate your active MCP server configuration file and extract the API key:
- **Antigravity**: `.gemini/antigravity/mcp_config.json` or `.gemini/jetski/mcp_config.json`
- **Gemini CLI**: `~/.gemini/settings.json` or `~/.gemini/extensions/Stitch/gemini-extension.json`
- **Claude Code**: `~/.claude.json`
Extract:
- **API Key**: From the `X-Goog-Api-Key` header or auth argument
- **MCP URL** (optional): From the `httpUrl` or endpoint argument (defaults to
`https://stitch.googleapis.com`)
> [!IMPORTANT]
> If you cannot find the API key in any of these locations, or if you cannot access these files, you MUST ask the user to provide the Stitch API key. Do not proceed without a valid API key.
### 3. Run Upload Script
> [!WARNING]
> **Checkpoint — User Confirmation Required.**
> Before running the upload script, you **MUST** pause and present the file(s)
> to be uploaded (paths, sizes, and types) to the user and wait for explicit
> approval. Do **NOT** execute the upload script until the user confirms.
Use `run_command` to execute the Python script:
```bash
python3 <SKILL_DIR>/scripts/upload_to_stitch.py \
--project-id <PROJECT_ID> \
--file-path <PATH_TO_FILE> \
--api-key <API_KEY> \
[--api-url <STITCH_API_URL>] \
[--title <SCREEN_TITLE>]
```
> [!TIP]
> **macOS / SSL Certificate Troubleshooting:**
> If the upload fails with `ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] unable to get local issuer certificate`, this means your Python installation does not have root certificate authorities configured.
> Fix it by prepending `SSL_CERT_FILE` using the `certifi` bundle:
> ```bash
> SSL_CERT_FILE=$(python3 -c "import certifi; print(certifi.where())") python3 <SKILL_DIR>/scripts/upload_to_stitch.py \
> --project-id <PROJECT_ID> \
> --file-path <PATH_TO_FILE> \
> --api-key <API_KEY>
> ```
### Supported File Types
| Extension | MIME Type |
|:---|:---|
| `.png` | `image/png` |
| `.jpg`, `.jpeg` | `image/jpeg` |
| `.webp` | `image/webp` |
| `.html`, `.htm` | `text/html` |
The script auto-detects MIME type from the file extension.
### Script Defaults
- `--api-url` defaults to `https://stitch.googleapis.com`
- `--api-key` is **required**
- Screen instances are automatically created for display
- For HTML files, `screenType` is set to `DOCUMENT`; for images, `IMAGE`
@@ -0,0 +1,234 @@
#!/usr/bin/env python3
r"""Upload an image or HTML to a Stitch project via BatchCreateScreens.
WHY THIS SCRIPT EXISTS:
The AI model cannot upload files via the MCP tool directly because MCP tool
call arguments are part of the model's *output*. The model must re-emit the
entire base64-encoded file as generated text, but its output token limit
(~16K tokens) is far smaller than a typical file's base64 encoding (e.g.
a 53KB PNG becomes ~71K chars of base64). The output gets truncated
mid-string, producing a corrupted payload that the API rejects.
This script bypasses the model entirely — it reads the file, encodes it
in-process, and sends the full payload directly over HTTP with no token
limits.
SUPPORTED FILE TYPES:
- Images: .png, .jpg, .jpeg, .webp
- HTML: .html, .htm
Usage:
python3 upload_to_stitch.py \
--project-id <PROJECT_ID> \
--file-path <PATH_TO_FILE> \
[--api-url <STITCH_API_BASE_URL>] \
[--api-key <API_KEY>] \
[--title <SCREEN_TITLE>] \
[--create-screen-instances]
"""
import argparse
import base64
import json
import pathlib
import sys
from typing import Any
import urllib.request
# Maps file extensions to MIME types.
_MIME_TYPES = {
".png": "image/png",
".jpg": "image/jpeg",
".jpeg": "image/jpeg",
".webp": "image/webp",
".html": "text/html",
".htm": "text/html",
".md": "text/markdown",
}
def encode_file(path: pathlib.Path) -> str:
"""Read and base64-encode a file."""
with open(path, "rb") as f:
return base64.b64encode(f.read()).decode("utf-8")
def call_batch_create_screens(
api_url: str,
api_key: str,
project_id: str,
requests: list[dict[str, Any]],
create_screen_instances: bool = False,
urlopen: Any = urllib.request.urlopen,
) -> dict[str, Any]:
"""Call BatchCreateScreens REST API directly.
Endpoint: POST /v1/{parent=projects/*}/screens:batchCreate
Args:
api_url: Base URL of the Stitch API (e.g. https://stitch.googleapis.com).
api_key: API key for authentication.
project_id: The Stitch project ID.
requests: List of CreateScreenRequest dicts, each containing a screen.
create_screen_instances: Whether to create screen instances for display.
urlopen: The urlopen function to use (for testing).
Returns:
Parsed JSON response dict.
"""
url = f"{api_url.rstrip('/')}/v1/projects/{project_id}/screens:batchCreate"
payload = {
"parent": f"projects/{project_id}",
"requests": requests,
"createScreenInstances": create_screen_instances,
}
data = json.dumps(payload).encode("utf-8")
req = urllib.request.Request(
url,
data=data,
headers={
"Content-Type": "application/json",
"X-Goog-Api-Key": api_key,
},
method="POST",
)
try:
print("Calling urlopen...")
with urlopen(req, timeout=120) as resp:
print(f"urlopen returned. Status: {resp.getcode()}")
body = resp.read().decode("utf-8")
print(f"Response status: {resp.getcode()}")
print(f"Response body (first 1000 chars): {body[:1000]}")
if not body:
print("Error: Empty response body")
sys.exit(1)
return json.loads(body)
except urllib.error.HTTPError as e:
error_body = e.read().decode("utf-8")
print(f"HTTP Error {e.code}: {e.reason}")
print(f"Response: {error_body}")
sys.exit(1)
def build_screen_request(
mime_type: str,
b64_data: str,
title: str | None = None,
) -> dict[str, Any]:
"""Build a CreateScreenRequest dict from a file.
For images, the file is set as the screenshot.
For HTML, the file is set as the html_code.
Args:
mime_type: The MIME type of the file.
b64_data: Base64-encoded file content.
title: Optional title for the screen.
Returns:
A CreateScreenRequest-shaped dict.
"""
file_obj = {
"fileContentBase64": b64_data,
"mimeType": mime_type,
}
if mime_type in ("text/html", "text/markdown"):
screen = {
"htmlCode": file_obj,
"screenType": "DOCUMENT",
"isCreatedByClient": True,
}
else:
screen = {
"screenshot": file_obj,
"screenType": "IMAGE",
"isCreatedByClient": True,
}
if title:
screen["title"] = title
return {"screen": screen}
def parse_args():
"""Parse command-line arguments."""
parser = argparse.ArgumentParser(
description="Upload a file to a Stitch project via BatchCreateScreens."
)
parser.add_argument("--project-id", required=True, help="Stitch project ID")
parser.add_argument(
"--file-path",
required=True,
type=pathlib.Path,
help=(
"Path to the file to upload. Supported types:"
f" {', '.join(sorted(_MIME_TYPES.keys()))}"
),
)
parser.add_argument(
"--api-url",
default="https://stitch.googleapis.com",
help="Stitch API base URL. Defaults to https://stitch.googleapis.com.",
)
parser.add_argument(
"--api-key",
required=True,
help="API key for the Stitch API.",
)
parser.add_argument(
"--title",
default=None,
help="Optional title for the created screen",
)
return parser.parse_args()
def main():
args = parse_args()
file_path = args.file_path
file_suffix = file_path.suffix.lower()
mime_type = _MIME_TYPES.get(file_suffix)
if mime_type is None:
print(
f"Error: Unsupported file type '{file_suffix}'. Supported types:"
f" {', '.join(sorted(_MIME_TYPES.keys()))}"
)
sys.exit(1)
if not file_path.exists():
print(f"Error: File not found: {file_path}")
sys.exit(1)
print(f"File: {file_path}")
print(f"MIME type: {mime_type}")
b64_data = encode_file(file_path)
print(f"Base64: {len(b64_data)} chars")
screen_request = build_screen_request(mime_type, b64_data, title=args.title)
print(f"\nUploading to project: {args.project_id}")
print(f"API URL: {args.api_url}")
result = call_batch_create_screens(
api_url=args.api_url,
api_key=args.api_key,
project_id=args.project_id,
requests=[screen_request],
create_screen_instances=True,
)
print("\nResponse:")
print(json.dumps(result, indent=2))
if __name__ == "__main__":
main()
+19
View File
@@ -0,0 +1,19 @@
{
"name": "stitch-utilities",
"description": "Design utilities and assistants for Google Stitch — generate DESIGN.md specs, enhance prompts, build multi-page sites with stitch-loop, and enforce premium design standards.",
"version": "1.0.0",
"author": {
"name": "google-labs-code"
},
"homepage": "https://github.com/google-labs-code/stitch-skills",
"repository": "https://github.com/google-labs-code/stitch-skills",
"license": "Apache-2.0",
"keywords": [
"stitch",
"design-system",
"prompt-engineering",
"design-md",
"website-generation",
"ui-standards"
]
}
-50
View File
@@ -1,50 +0,0 @@
# Stitch Design Skill
Teaches agents to generate high-fidelity, consistent UI designs and maintain project-level design systems using Stitch.
## Install
```bash
npx skills add google-labs-code/stitch-skills --skill stitch-design --global
```
## What It Does
Enables professional-grade UI/UX design workflows through Stitch MCP:
1. **Prompt Enhancement**: Transforms rough intent into structured, high-fidelity prompts with professional terminology and design system context.
2. **Design System Synthesis**: Analyzes existing Stitch projects to create and maintain a `.stitch/DESIGN.md` "source of truth".
3. **Iterative Generation**: Selects the best generation or editing workflow (`edit_screens`, `generate_variants`) based on user intent.
4. **Asset Management**: Synchronizes remote designs by downloading HTML and screenshots to the project's `.stitch/designs` directory.
## Prerequisites
- Stitch MCP Server access
- A project `projectId` (can be discovered via `list_projects`)
## Example Prompt
```text
Design a premium landing page for a mountain resort with a focus on serene luxury and glassmorphism.
```
## Skill Structure
```
stitch-design/
├── SKILL.md — Core instructions & Prompt Pipeline
├── README.md — This file
├── workflows/ — Specialized pipelines (Text-to-UI, Edit, MD)
├── references/ — UI/UX keywords & Technical Mappings
└── examples/ — Gold-standard references (Solace Mindfulness)
```
## Works With
- **`react:components` skill**: Hand-off generated designs for frontend implementation.
- **`stitch-loop` skill**: Provides the `DESIGN.md` context for autonomous building loops.
- **Multi-agent workflows**: Refines prompts before passing design tasks to specialized agents.
## Learn More
See [SKILL.md](./SKILL.md) for complete instructions.
-84
View File
@@ -1,84 +0,0 @@
---
name: stitch-design
description: Unified entry point for Stitch design work. Handles prompt enhancement (UI/UX keywords, atmosphere), design system synthesis (.stitch/DESIGN.md), and high-fidelity screen generation/editing via Stitch MCP.
allowed-tools:
- "StitchMCP"
- "Read"
- "Write"
---
# Stitch Design Expert
You are an expert Design Systems Lead and Prompt Engineer specializing in the **Stitch MCP server**. Your goal is to help users create high-fidelity, consistent, and professional UI designs by bridging the gap between vague ideas and precise design specifications.
## Core Responsibilities
1. **Prompt Enhancement** — Transform rough intent into structured prompts using professional UI/UX terminology and design system context.
2. **Design System Synthesis** — Analyze existing Stitch projects to create `.stitch/DESIGN.md` "source of truth" documents.
3. **Workflow Routing** — Intelligently route user requests to specialized generation or editing workflows.
4. **Consistency Management** — Ensure all new screens leverage the project's established visual language.
5. **Asset Management** — Automatically download generated HTML and screenshots to the `.stitch/designs` directory.
---
## 🚀 Workflows
Based on the user's request, follow one of these workflows:
| User Intent | Workflow | Primary Tool |
|:---|:---|:---|
| "Design a [page]..." | [text-to-design](workflows/text-to-design.md) | `generate_screen_from_text` + `Download` |
| "Edit this [screen]..." | [edit-design](workflows/edit-design.md) | `edit_screens` + `Download` |
| "Create/Update .stitch/DESIGN.md" | [generate-design-md](workflows/generate-design-md.md) | `get_screen` + `Write` |
---
## 🎨 Prompt Enhancement Pipeline
Before calling any Stitch generation or editing tool, you MUST enhance the user's prompt.
### 1. Analyze Context
- **Project Scope**: Maintain the current `projectId`. Use `list_projects` if unknown.
- **Design System**: Check for `.stitch/DESIGN.md`. If it exists, incorporate its tokens (colors, typography). If not, suggest the `generate-design-md` workflow.
### 2. Refine UI/UX Terminology
Consult [Design Mappings](references/design-mappings.md) to replace vague terms.
- Vague: "Make a nice header"
- Professional: "Sticky navigation bar with glassmorphism effect and centered logo"
### 3. Structure the Final Prompt
Format the enhanced prompt for Stitch like this:
```markdown
[Overall vibe, mood, and purpose of the page]
**DESIGN SYSTEM (REQUIRED):**
- Platform: [Web/Mobile], [Desktop/Mobile]-first
- Palette: [Primary Name] (#hex for role), [Secondary Name] (#hex for role)
- Styles: [Roundness description], [Shadow/Elevation style]
**PAGE STRUCTURE:**
1. **Header:** [Description of navigation and branding]
2. **Hero Section:** [Headline, subtext, and primary CTA]
3. **Primary Content Area:** [Detailed component breakdown]
4. **Footer:** [Links and copyright information]
```
### 4. Present AI Insights
After any tool call, always surface the `outputComponents` (Text Description and Suggestions) to the user.
---
## 📚 References
- [Tool Schemas](references/tool-schemas.md) — How to call Stitch MCP tools.
- [Design Mappings](references/design-mappings.md) — UI/UX keywords and atmosphere descriptors.
- [Prompting Keywords](references/prompt-keywords.md) — Technical terms Stitch understands best.
---
## 💡 Best Practices
- **Iterative Polish**: Prefere `edit_screens` for targeted adjustments over full re-generation.
- **Semantic First**: Name colors by their role (e.g., "Primary Action") as well as their appearance.
- **Atmosphere Matters**: Explicitly set the "vibe" (Minimalist, Vibrant, Brutalist) to guide the generator.
-22
View File
@@ -1,22 +0,0 @@
---
# The "Solace" Design System
This is a comprehensive design language for a mindfulness and wellness application.
## 🎨 Color Palette
- **Primary**: Deep Ocean Blue (#1a365d) - for critical navigation and CTAs.
- **Secondary**: Calm Slate (#718096) - for subtexts and secondary buttons.
- **Background**: Soft Mist (#f7fafc) - for main page content.
- **Accent**: Serene Emerald (#38a169) - for positive feedback and completion states.
## 🔡 Typography
- **Heading**: Montserrat, Bold - for titles and hero section headlines.
- **Body**: Inter, Regular - for descriptions and general content.
- **Size**: 16px as base, 48px for H1.
## 📐 Components
- **Buttons**: Rounded (12px), subtle hover shadow (4px blur).
- **Cards**: Minimal border (1px, #e2e8f0), soft shadow (8px elevation).
- **Navigation**: Clean, top-aligned, centered menu items.
---
💡 **Tip**: When calling `generate_screen_from_text`, include the tokens above to ensure the new screen matches this design system.
@@ -1,28 +0,0 @@
# Example: Prompt Enhancement
## User Input (Vague)
> "Make a landing page for my fitness app called 'Pulse'. Use red and black. It should have a place for features and a hero section."
---
## Enhanced Prompt (Stitch-Optimized)
**Overall Purpose**: A high-energy, modern landing page for 'Pulse', a fitness tracking application. The vibe is powerful, motivating, and high-performance.
**DESIGN SYSTEM (REQUIRED):**
- **Primary Color**: Racing Red (#e11d48) for CTA buttons and active states.
- **Secondary Color**: Deep Obsidian (#0f172a) for background and text containers.
- **Typography**: Bold, condensed sans-serif headings (e.g., Impact or Inter Tight) to convey speed and strength.
- **Style**: Hard edges with sharp, minimal borders; high contrast; dark mode by default.
**PAGE STRUCTURE:**
1. **Header**: Minimalist navigation with Pulse logo (left) and "Start Training" primary button (right).
2. **Hero Section**: Large, emotive fitness photography background. Headline: "Elevate Every Beat." Sub-headline: "Track, analyze, and crush your fitness goals with Pulse." Primary red CTA: "Get Started".
3. **Feature Grid**: Three-column layout highlighting:
- **Real-time Tracking**: Live stats from your wearable.
- **AI Coaching**: Personalized workouts based on your performance.
- **Community Challenges**: Compete with friends and stay motivated.
4. **Social Proof Section**: Subtle slider showing "Trusted by 500,000+ athletes".
5. **Footer**: Quick links (Training, Pricing, Support), social icons, and legal.
---
💡 **Tip**: Notice how the enhanced prompt adds specific hex codes, defines the typography "vibe", and breaks the page into a logical numbered structure. This gives Stitch much clearer instructions.
@@ -1,76 +0,0 @@
# Stitch MCP Tool Schemas
Use these examples to format your tool calls to the Stitch MCP server correctly.
---
## 🏗️ Project Management
### `list_projects`
Lists all Stitch projects accessible to you.
```json
// No parameters needed
{}
```
### `get_project`
Retrieves details of a specific project.
```json
{
"name": "projects/4044680601076201931"
}
```
### `create_project`
Creates a new Stitch project.
```json
{
"title": "My New App"
}
```
---
## 🎨 Design Generation
### `generate_screen_from_text`
Generates a new screen from a text description.
```json
{
"projectId": "4044680601076201931",
"prompt": "A modern landing page for a coffee shop with a hero section, menu, and contact form. Use warm brown tones (#4b2c20) and a clean sans-serif font.",
"deviceType": "DESKTOP" // Options: MOBILE, DESKTOP, TABLET
}
```
### `edit_screens`
Edits existing screens with a text prompt.
```json
{
"projectId": "4044680601076201931",
"selectedScreenIds": ["98b50e2ddc9943efb387052637738f61"],
"prompt": "Change the background color to white (#ffffff) and make the call-to-action button larger."
}
```
---
## 🖼️ Screen Management
### `list_screens`
Lists all screens within a project.
```json
{
"projectId": "4044680601076201931"
}
```
### `get_screen`
Retrieves details of a specific screen.
```json
{
"projectId": "4044680601076201931",
"screenId": "98b50e2ddc9943efb387052637738f61",
"name": "projects/4044680601076201931/screens/98b50e2ddc9943efb387052637738f61"
}
```
@@ -1,44 +0,0 @@
---
description: Edit an existing design screen using Stitch MCP.
---
# Workflow: Edit-Design
Make targeted changes to an already generated design.
## Steps
### 1. Identify the Screen
Use `list_screens` or `get_screen` to find the correct `projectId` and `screenId`.
### 2. Formulate the Edit Prompt
Be specific about the changes you want to make. Do not just say "fix it".
- **Location**: "Change the color of the [primary button] in the [hero section]..."
- **Visuals**: "...to a darker blue (#004080) and add a subtle shadow."
- **Structure**: "Add a secondary button next to the primary one with the text 'Learn More'."
### 3. Apply the Edit
Call the `mcp_StitchMCP_edit_screens` tool.
```json
{
"projectId": "...",
"selectedScreenIds": ["..."],
"prompt": "[Your target edit prompt]"
}
```
### 4. Present AI Feedback
Always show the text description and suggestions from `outputComponents` to the user.
### 5. Download Design Assets
After editing, download the updated HTML and screenshot urls from `outputComponents` to the `.stitch/designs` directory, overwriting previous versions to ensure the local files reflect the latest edits.
### 6. Verify and Repeat
- Check the output screen to see if the changes were applied correctly.
- If more polish is needed, repeat the process with a new specific prompt.
## Tips
- **Keep it focused**: One edit at a time is often better than a long list of changes.
- **Reference components**: Use professional terms like "navigation bar", "hero section", "footer", "card grid".
- **Mention colors**: Use hex codes for precise color matching.
@@ -1,63 +0,0 @@
---
description: Analyze a Stitch project and synthesize its design system into a .stitch/DESIGN.md file.
---
# Workflow: Generate .stitch/DESIGN.md
Create a "source of truth" for your project's design language to ensure consistency across all future screens.
## 📥 Retrieval
To analyze a Stitch project, you must retrieve metadata and assets using the Stitch MCP tools:
1. **Project lookup**: Use `list_projects` to find the target `projectId`.
2. **Screen lookup**: Use `list_screens` for that `projectId` to find representative screens (e.g., "Home", "Main Dashboard").
3. **Metadata fetch**: Call `get_screen` for the target screen to get `screenshot.downloadUrl` and `htmlCode.downloadUrl`.
4. **Asset download**: Use `read_url_content` to fetch the HTML code.
## 🧠 Analysis & Synthesis
### 1. Identify Identity
- Capture Project Title and Project ID.
### 2. Define Atmosphere
- Analyze the HTML and screenshot to capture the "vibe" (e.g., "Airy," "Professional," "Vibrant").
### 3. Map Color Palette
- Extract exact hex codes and assign functional roles (e.g., "Primary Action: #2563eb").
### 4. Translate Geometry
- Convert Tailwind/CSS values into descriptive language (e.g., `rounded-full` → "Pill-shaped").
### 5. Document Depth
- Describe shadow styles and layering (e.g., "Soft, diffused elevation").
## 📝 Output Structure
Create a `.stitch/DESIGN.md` file in the project directory with this structure:
```markdown
# Design System: [Project Title]
**Project ID:** [Insert Project ID Here]
## 1. Visual Theme & Atmosphere
(Description of mood and aesthetic philosophy)
## 2. Color Palette & Roles
(Descriptive Name + Hex Code + Role)
## 3. Typography Rules
(Font families, weights, and usage)
## 4. Component Stylings
* **Buttons:** Shape, color, behavior
* **Containers:** Roundness, elevation
## 5. Layout Principles
(Whitespace strategy and grid alignment)
```
## 💡 Best Practices
- **Be Precise**: Always include hex codes in parentheses.
- **Be Descriptive**: Use natural language like "Deep Ocean Blue" instead of just "Blue".
- **Be Functional**: Explain *why* an element is used.
@@ -1,47 +0,0 @@
---
description: Generate new screens from a text prompt using Stitch MCP.
---
# Workflow: Text-to-Design
Transform a text description into a high-fidelity design screen.
## Steps
### 1. Enhance the User Prompt
Before calling the Stitch MCP tool, apply the [Prompt Enhancement Pipeline](../SKILL.md#prompt-enhancement-pipeline).
- Identify the platform (Web/Mobile) and page type.
- Incorporate any existing project design system from `.stitch/DESIGN.md`.
- Use specific [Design Mappings](../references/design-mappings.md) and [Prompting Keywords](../references/prompt-keywords.md).
### 2. Identify the Project
Use `list_projects` to find the correct `projectId` if it is not already known.
### 3. Generate the Screen
Call the `mcp_StitchMCP_generate_screen_from_text` tool with the enhanced prompt.
```json
{
"projectId": "...",
"prompt": "[Your Enhanced Prompt]",
"deviceType": "DESKTOP" // or MOBILE
}
```
### 4. Present AI Feedback
Always show the text description and suggestions from `outputComponents` to the user.
### 5. Download Design Assets
After generation, download the HTML and screenshot urls from `outputComponents` to the `.stitch/designs` directory.
- **Naming**: Use the screen ID or a descriptive slug for the filename.
- **Tools**: Use `curl -o` via `run_command` or similar.
- **Directory**: Ensure `.stitch/designs` exists.
### 6. Review and Refine
- If the result is not exactly as expected, use the [edit-design](edit-design.md) workflow to make targeted adjustments.
- Do NOT re-generate from scratch unless the fundamental layout is wrong.
## Tips
- **Be structural**: Break the page down into header, hero, features, and footer in your prompt.
- **Specify colors**: Use hex codes for precision.
- **Set the tone**: Explicitly mention if the design should be minimal, professional, or vibrant.