
Stitch To React
- 5 installs
- 21 repo stars
- Updated August 5, 2026
- joaquimscosta/arkhe-claude-plugins
Converts Google Stitch HTML/PNG exports into React components while integrating the project's design system.
About
Verifies Stitch exports, loads project context, and decomposes screens into composable React components respecting established patterns. A developer uses it to turn Stitch output into React code.
- Mandatory export verification with graceful fallback to design docs
- Decomposes Stitch screens into design-system-aligned React components
Stitch To React by the numbers
- 5 all-time installs (skills.sh)
- Ranked #1,791 of 2,245 Frontend Development skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/joaquimscosta/arkhe-claude-plugins --skill stitch-to-reactAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 5 |
|---|---|
| repo stars | ★ 21 |
| Last updated | August 5, 2026 |
| Repository | joaquimscosta/arkhe-claude-plugins ↗ |
What it does
Converts Google Stitch HTML/PNG exports into React components while integrating the project's design system.
Files
Stitch to React
Convert Google Stitch exports (Tailwind HTML + PNG) into React components with full design system integration.
Core Philosophy: Decompose Stitch screens into composable React components while respecting established patterns.
Quick Start
0. Verify Exports Exist (Mandatory)
Before any conversion, verify Stitch exports are available:
# Check for HTML/PNG pairs in the expected location
Glob: design-intent/google-stitch/{feature}/exports/*.html
Glob: design-intent/google-stitch/{feature}/exports/*.pngIf exports found: Proceed to Step 1.
If exports NOT found: 1. Check if user specified wrong path - ask for correct location 2. Suggest running /stitch-generate first to create exports 3. Fall back to design docs: Check /design-intent/patterns/ for established patterns or project directories for screenshots 4. If no design assets exist, inform user and offer to help create them
Report findings:
Export Check: [PASSED/MISSING]
- HTML files: [count] found
- PNG files: [count] found
- Location: design-intent/google-stitch/{feature}/exports/1. Load Project Context (Mandatory)
Before any conversion:
1. Read /design-intent/memory/constitution.md for project principles 2. Read /design-intent/patterns/ for established patterns 3. Detect project design system (Fluent UI, Material UI, custom, etc.) 4. Report: "Existing patterns to consider: [list]"
2. Scan Stitch Exports
Stitch exports are located at:
design-intent/google-stitch/{feature}/exports/
├── 01-layout-{name}.html # Tailwind CSS + HTML
├── 01-layout-{name}.png # Visual reference
├── 02-component-{name}.html
├── 02-component-{name}.png
└── ...From each HTML file, extract:
- Inline
tailwind.config(colors, fonts, spacing) - Custom
<style>blocks (animations, keyframes) - DOM structure for component hierarchy
- Material Symbols icons usage
3. Map to Project Design System
For each Stitch element:
1. Check existing patterns - Can we reuse established components? 2. Map Tailwind tokens - Convert to project design tokens 3. Decompose into composable parts - Break screens into smaller, reusable components 4. Flag conflicts - Note when Stitch output differs from patterns
4. Generate React Components
Output structure:
src/components/{feature}/
├── {ComponentName}.tsx # Main component
├── {SubComponent}.tsx # Decomposed smaller components
├── tokens.ts # Design tokens from Stitch config
├── types.ts # TypeScript interfaces
└── index.ts # Re-exportsComponent Selection Priority
Per constitution principles:
1. Existing project components from /design-intent/patterns/ 2. Framework components (Fluent UI, project design system) 3. Custom components (document with header comment)
Conflict Resolution
When Stitch output conflicts with patterns:
## Design Conflict Detected
**Element**: Button border-radius
**Stitch Output**: 4px
**Existing Pattern**: 8px (button-styling.md)
### Options
1. Follow Stitch output - Use 4px
2. Use existing pattern - Use 8px
3. Update pattern - Make 4px the new standard
Which approach?Custom Component Documentation
/**
* CUSTOM COMPONENT: ComponentName
* Source: Stitch screen name
* Base: @fluentui/react-components/ComponentType (if applicable)
* Reason: Why custom implementation was needed
* Created: YYYY-MM-DD
*
* Original Reference: design-intent/google-stitch/{feature}/exports/{screen}.png
*/Reference Documentation
- Detailed workflow: See WORKFLOW.md
- Usage examples: See EXAMPLES.md
- Common issues: See TROUBLESHOOTING.md
Invocation
Triggered by:
- User references
design-intent/google-stitch/exports - "Convert Stitch output to React"
- "Stitch to React" requests
- Processing directories with HTML + PNG pairs from Stitch
Examples
Real-world examples of converting Google Stitch exports to React components.
---
Example 1: Basic Component Conversion
Input: Stitch Export
design-intent/google-stitch/dashboard/exports/
├── 01-metric-card.html
└── 01-metric-card.pngStitch HTML (simplified):
<script>
tailwind.config = {
theme: {
extend: {
colors: {
brand: '#3B82F6',
},
},
},
};
</script>
<div class="bg-white rounded-lg shadow-md p-6">
<div class="flex items-center justify-between">
<span class="text-gray-500 text-sm">Total Revenue</span>
<span class="material-symbols-outlined text-brand">trending_up</span>
</div>
<div class="mt-2">
<span class="text-3xl font-bold text-gray-900">$45,231</span>
<span class="ml-2 text-sm text-green-500">+12.5%</span>
</div>
</div>Context Check
Project Context:
- Design System: Fluent UI v9
- Existing patterns:
- card-layout.md: 16px padding, tokens.shadow4
- typography-scale.md: size 800 for headlinesConflict Detected
## Design Conflict
**Element**: Card shadow
**Stitch**: shadow-md (0 4px 6px rgba)
**Pattern**: tokens.shadow4
**Recommendation**: Use pattern - Fluent shadow tokensGenerated Output
tokens.ts:
/**
* Design tokens from Stitch metric-card export
* Mapped to Fluent UI tokens where available
*/
import { tokens } from '@fluentui/react-components';
export const metricCardTokens = {
// Colors - mapped to Fluent
brand: tokens.colorBrandBackground,
textPrimary: tokens.colorNeutralForeground1,
textSecondary: tokens.colorNeutralForeground3,
positive: tokens.colorPaletteGreenForeground1,
// Spacing - from Stitch p-6 (24px)
padding: tokens.spacingHorizontalXL,
// Using pattern shadow instead of Stitch shadow-md
shadow: tokens.shadow4,
} as const;types.ts:
export interface MetricCardProps {
label: string;
value: string;
trend?: {
direction: 'up' | 'down' | 'neutral';
percentage: string;
};
icon?: string;
}MetricCard.tsx:
/**
* CUSTOM COMPONENT: MetricCard
* Source: 01-metric-card.html
* Base: @fluentui/react-components/Card
* Reason: Custom metric display layout with trend indicator
* Created: YYYY-MM-DD
*
* Original Reference: design-intent/google-stitch/dashboard/exports/01-metric-card.png
*/
import React from 'react';
import { Card, Text, tokens } from '@fluentui/react-components';
import { ArrowTrendingUp24Regular } from '@fluentui/react-icons';
import { metricCardTokens } from './tokens';
import type { MetricCardProps } from './types';
export const MetricCard: React.FC<MetricCardProps> = ({
label,
value,
trend,
icon,
}) => {
return (
<Card
style={{
padding: metricCardTokens.padding,
boxShadow: metricCardTokens.shadow,
}}
>
<div style={{
display: 'flex',
alignItems: 'center',
justifyContent: 'space-between',
}}>
<Text
size={200}
style={{ color: metricCardTokens.textSecondary }}
>
{label}
</Text>
<ArrowTrendingUp24Regular
style={{ color: metricCardTokens.brand }}
/>
</div>
<div style={{ marginTop: tokens.spacingVerticalS }}>
<Text size={800} weight="bold">
{value}
</Text>
{trend && (
<Text
size={200}
style={{
marginLeft: tokens.spacingHorizontalS,
color: trend.direction === 'up'
? metricCardTokens.positive
: tokens.colorNeutralForeground3,
}}
>
{trend.percentage}
</Text>
)}
</div>
</Card>
);
};---
Example 2: Multi-State Button from Stitch
Input: Stitch Export with Multiple States
design-intent/google-stitch/recording/exports/
├── 02-record-button.html
└── 02-record-button.pngThe HTML shows a button with 6 visual states encoded in the markup.
State Analysis
From Stitch HTML, identified states: 1. Idle - Default state, ready to record 2. Hover - Subtle highlight 3. Recording - Active, pulsing animation 4. Paused - Recording paused 5. Processing - Converting audio 6. Error - Recording failed
Generated Output
types.ts:
export type RecordButtonState =
| 'idle'
| 'hover'
| 'recording'
| 'paused'
| 'processing'
| 'error';
export interface RecordButtonProps {
state: RecordButtonState;
onRecord: () => void;
onPause: () => void;
onStop: () => void;
disabled?: boolean;
}RecordButton.styles.ts:
/**
* Styles extracted from Stitch 02-record-button.html
* Custom keyframe animations preserved from source
*/
import { makeStyles, tokens } from '@fluentui/react-components';
export const useRecordButtonStyles = makeStyles({
button: {
width: '64px',
height: '64px',
borderRadius: '50%',
border: 'none',
cursor: 'pointer',
transition: 'all 200ms ease-out',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
idle: {
backgroundColor: tokens.colorBrandBackground,
':hover': {
backgroundColor: tokens.colorBrandBackgroundHover,
transform: 'scale(1.05)',
},
},
recording: {
backgroundColor: tokens.colorPaletteRedBackground3,
animationName: {
'0%': { transform: 'scale(1)', opacity: 1 },
'50%': { transform: 'scale(1.1)', opacity: 0.8 },
'100%': { transform: 'scale(1)', opacity: 1 },
},
animationDuration: '1.5s',
animationIterationCount: 'infinite',
},
paused: {
backgroundColor: tokens.colorNeutralBackground4,
},
processing: {
backgroundColor: tokens.colorNeutralBackground3,
cursor: 'wait',
},
error: {
backgroundColor: tokens.colorPaletteRedBackground1,
},
});RecordButton.tsx:
/**
* CUSTOM COMPONENT: RecordButton
* Source: 02-record-button.html
* Base: @fluentui/react-components/Button
* Reason: Multi-state recording button with pulse animation
* Created: YYYY-MM-DD
*
* Original Reference: design-intent/google-stitch/recording/exports/02-record-button.png
*/
import React from 'react';
import { mergeClasses } from '@fluentui/react-components';
import {
Mic24Regular,
Pause24Regular,
Stop24Regular,
Spinner24Regular,
Warning24Regular,
} from '@fluentui/react-icons';
import { useRecordButtonStyles } from './RecordButton.styles';
import type { RecordButtonProps, RecordButtonState } from './types';
const stateIcons: Record<RecordButtonState, React.ReactNode> = {
idle: <Mic24Regular />,
hover: <Mic24Regular />,
recording: <Stop24Regular />,
paused: <Mic24Regular />,
processing: <Spinner24Regular />,
error: <Warning24Regular />,
};
export const RecordButton: React.FC<RecordButtonProps> = ({
state,
onRecord,
onPause,
onStop,
disabled,
}) => {
const styles = useRecordButtonStyles();
const handleClick = () => {
switch (state) {
case 'idle':
case 'paused':
onRecord();
break;
case 'recording':
onStop();
break;
default:
break;
}
};
return (
<button
className={mergeClasses(
styles.button,
styles[state]
)}
onClick={handleClick}
disabled={disabled || state === 'processing'}
aria-label={`Recording ${state}`}
>
{stateIcons[state]}
</button>
);
};---
Example 3: Full Layout Decomposition
Input: Complex Layout Screen
design-intent/google-stitch/asr-interface/exports/
├── 01-layout-papia-asr.html
├── 01-layout-papia-asr.png
├── 02-header-nav.html
├── 02-header-nav.png
├── 03-recording-panel.html
└── 03-recording-panel.pngDecomposition Strategy
01-layout-papia-asr.html (Full Screen)
├── Header (extract from 02-header-nav.html)
│ ├── Logo (atomic)
│ ├── Navigation (composite)
│ └── UserMenu (composite)
├── Main Content
│ ├── RecordingPanel (from 03-recording-panel.html)
│ │ ├── RecordButton (atomic, multi-state)
│ │ ├── WaveformDisplay (atomic)
│ │ └── TranscriptPreview (composite)
│ └── TranscriptionResults (composite)
└── Footer (atomic)Pattern Check Output
Project Context:
- Design System: Fluent UI v9
- Existing patterns:
- header-layout.md: 64px height, horizontal nav
- sidebar-layout.md: 240px width, collapsible
- (No recording-related patterns exist)
New patterns to establish:
1. recording-panel-layout - Recording interface structure
2. waveform-display - Audio visualization styling
3. transcript-card - Transcription result displayGenerated File Structure
src/components/asr-interface/
├── index.ts
├── types.ts
├── tokens.ts
├── ASRLayout.tsx # Main layout
├── Header/
│ ├── Header.tsx
│ ├── Logo.tsx
│ ├── Navigation.tsx
│ └── UserMenu.tsx
├── RecordingPanel/
│ ├── RecordingPanel.tsx
│ ├── RecordButton.tsx
│ ├── WaveformDisplay.tsx
│ └── TranscriptPreview.tsx
└── TranscriptionResults/
├── TranscriptionResults.tsx
└── TranscriptCard.tsxMain Layout Component
/**
* ASR Interface Layout
* Source: 01-layout-papia-asr.html
* Composed from multiple Stitch screens
*
* Original Reference: design-intent/google-stitch/asr-interface/exports/01-layout-papia-asr.png
*/
import React from 'react';
import { tokens } from '@fluentui/react-components';
import { Header } from './Header/Header';
import { RecordingPanel } from './RecordingPanel/RecordingPanel';
import { TranscriptionResults } from './TranscriptionResults/TranscriptionResults';
import type { ASRLayoutProps } from './types';
export const ASRLayout: React.FC<ASRLayoutProps> = ({
user,
recordings,
onRecord,
onTranscribe,
}) => {
return (
<div style={{
display: 'flex',
flexDirection: 'column',
minHeight: '100vh',
backgroundColor: tokens.colorNeutralBackground2,
}}>
<Header user={user} />
<main style={{
flex: 1,
display: 'grid',
gridTemplateColumns: '1fr 2fr',
gap: tokens.spacingHorizontalXL,
padding: tokens.spacingHorizontalXL,
}}>
<RecordingPanel
onRecord={onRecord}
onTranscribe={onTranscribe}
/>
<TranscriptionResults recordings={recordings} />
</main>
</div>
);
};---
Example 4: Handling Stitch Animations
Input: Animated Component
Stitch HTML contains custom keyframe animation:
<style>
@keyframes slideIn {
from {
transform: translateX(-100%);
opacity: 0;
}
to {
transform: translateX(0);
opacity: 1;
}
}
.animate-slideIn {
animation: slideIn 0.3s ease-out forwards;
}
</style>Conversion to Fluent UI Styles
import { makeStyles, shorthands } from '@fluentui/react-components';
export const useAnimatedPanelStyles = makeStyles({
panel: {
// Converted from Stitch @keyframes slideIn
animationName: {
from: {
transform: 'translateX(-100%)',
opacity: 0,
},
to: {
transform: 'translateX(0)',
opacity: 1,
},
},
animationDuration: '0.3s',
animationTimingFunction: 'ease-out',
animationFillMode: 'forwards',
},
});---
Example 5: Conflict Resolution Flow
Scenario: Multiple Conflicts
## Design Conflicts Detected
### 1. Border Radius
**Stitch**: 4px (rounded)
**Pattern**: 8px (button-styling.md)
**Elements**: Buttons, cards, inputs
### 2. Primary Color
**Stitch**: #3B82F6 (Tailwind blue-500)
**Pattern**: #0078D4 (Fluent brand)
**Elements**: CTAs, links, focus rings
### 3. Shadow Depth
**Stitch**: shadow-lg (heavy)
**Pattern**: tokens.shadow4 (subtle)
**Elements**: Cards, modalsUser Response
1. Border Radius: Use pattern (8px) - maintain consistency
2. Primary Color: Use pattern (Fluent brand) - brand guidelines
3. Shadow Depth: Follow Stitch (shadow-lg) - want more depthResulting tokens.ts
/**
* Tokens resolved from Stitch export + pattern conflicts
* Conflict resolutions documented inline
*/
import { tokens } from '@fluentui/react-components';
export const resolvedTokens = {
// CONFLICT RESOLVED: Using pattern value
// Stitch: 4px, Pattern: 8px
// Decision: Pattern - maintain consistency
borderRadius: tokens.borderRadiusMedium, // 8px
// CONFLICT RESOLVED: Using pattern value
// Stitch: #3B82F6, Pattern: #0078D4
// Decision: Pattern - brand guidelines
primaryColor: tokens.colorBrandBackground,
// CONFLICT RESOLVED: Using Stitch value
// Stitch: shadow-lg, Pattern: shadow4
// Decision: Stitch - want more depth for this feature
cardShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05)',
} as const;---
Example 6: Pattern Suggestion Output
After successful conversion, suggest new patterns:
## Patterns to Document
Based on this Stitch conversion, consider documenting:
### 1. recording-interface-layout.md
**Decision**: Two-column layout with recording controls left, results right
**Elements**: RecordingPanel, TranscriptionResults
**Breakpoint**: Stack vertically below 768px
### 2. multi-state-button.md
**Decision**: Circular buttons with state-based colors and animations
**Elements**: RecordButton, ProcessingIndicator
**States**: idle, active, processing, error
### 3. waveform-display.md
**Decision**: SVG-based waveform with gradient fill
**Elements**: WaveformDisplay
**Colors**: Brand gradient for active, neutral for inactive
Run `/save-patterns` to capture these patterns.Troubleshooting
Common issues and solutions when converting Google Stitch exports to React components.
---
Issue: Stitch Export Directory Not Found
Symptoms
Error: Cannot find design-intent/google-stitch/{feature}/exports/Cause
Stitch exports haven't been generated or are in unexpected location.
Solution
1. Verify export location
design-intent/google-stitch/{feature}/exports/2. Check for alternative structures
- Some projects use
stitch-exports/instead - Exports might be at project root
3. Generate exports if missing Use /stitch-generate to create exports from prompts.
Workaround
Provide the explicit path to Stitch HTML files:
"Convert the Stitch export at /path/to/screen.html"---
Issue: No Pattern Directory Found
Symptoms
Cannot find /design-intent/patterns/ directoryCause
Project hasn't been initialized with design intent structure.
Solution
Run setup to create structure:
/setupWorkaround
Proceed without patterns - the skill will note:
No existing patterns found. Will generate components without pattern constraints.---
Issue: Tailwind Config Not Extractable
Symptoms
- Colors show as raw Tailwind classes (e.g.,
bg-blue-500) - Custom theme values missing
- Tokens not properly mapped
Cause
Stitch HTML uses inline Tailwind CDN without custom config, or config is malformed.
Solution
1. Check HTML for tailwind.config
<script>
tailwind.config = {
theme: {
extend: {
// Should have custom values here
},
},
};
</script>2. If missing, use Tailwind defaults Map standard Tailwind values to project tokens:
| Tailwind | Fluent UI |
|---|---|
| blue-500 | colorBrandBackground |
| gray-900 | colorNeutralForeground1 |
| rounded-lg | borderRadiusMedium |
3. Check design-dna.md The MCP may have extracted tokens to design-dna.md file.
---
Issue: Custom Animations Not Working
Symptoms
- Animations from Stitch don't play in React
- Keyframes not applied
- Timing feels different
Cause
CSS keyframes need to be converted to CSS-in-JS format.
Solution
Stitch CSS:
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.animate-fadeIn {
animation: fadeIn 0.3s ease-out;
}Fluent UI makeStyles:
const useStyles = makeStyles({
fadeIn: {
animationName: {
from: { opacity: 0 },
to: { opacity: 1 },
},
animationDuration: '0.3s',
animationTimingFunction: 'ease-out',
},
});Alternative - Global CSS:
Create a stitch-animations.css file:
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}Import in component:
import './stitch-animations.css';
// Use in JSX
<div style={{ animation: 'fadeIn 0.3s ease-out' }}>---
Issue: Material Symbols Icons Not Mapping
Symptoms
- Stitch uses Material Symbols:
<span class="material-symbols-outlined">home</span> - No equivalent Fluent UI icon found
Cause
Material Symbols icon names don't match Fluent UI icon names.
Solution
1. Use icon mapping table
| Material Symbol | Fluent Icon |
|---|---|
| home | Home24Regular |
| settings | Settings24Regular |
| person | Person24Regular |
| trending_up | ArrowTrending24Regular |
| search | Search24Regular |
| menu | Navigation24Regular |
2. For unmapped icons, keep Material Symbols
// Install: npm install material-symbols
import 'material-symbols';
<span className="material-symbols-outlined">
specific_icon_name
</span>3. Consider custom SVG icons Export from Material Symbols and create React components.
---
Issue: Responsive Behavior Not Matching
Symptoms
- Desktop layout works
- Mobile view broken or doesn't match PNG
Cause
Stitch uses Tailwind responsive prefixes (md:, lg:) that need conversion.
Solution
Stitch Tailwind:
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3">React with CSS:
<div style={{
display: 'grid',
gridTemplateColumns: '1fr', // Mobile default
'@media (min-width: 768px)': {
gridTemplateColumns: 'repeat(2, 1fr)',
},
'@media (min-width: 1024px)': {
gridTemplateColumns: 'repeat(3, 1fr)',
},
}}>React with Fluent UI makeStyles:
const useStyles = makeStyles({
grid: {
display: 'grid',
gridTemplateColumns: '1fr',
'@media (min-width: 768px)': {
gridTemplateColumns: 'repeat(2, 1fr)',
},
'@media (min-width: 1024px)': {
gridTemplateColumns: 'repeat(3, 1fr)',
},
},
});---
Issue: PNG Reference and Code Don't Match
Symptoms
- Generated React looks different from reference PNG
- Layout or spacing seems off
Cause
1. Stitch may have generated different variants 2. Browser rendering differences 3. Font not loaded in React
Solution
1. Verify HTML matches PNG
- Open Stitch HTML in browser
- Compare to PNG side-by-side
- Note any differences
2. Check font loading
// Ensure fonts match Stitch
import '@fontsource/inter/400.css';
import '@fontsource/inter/500.css';
import '@fontsource/inter/700.css';3. Compare at same viewport
- Stitch PNG might be at specific resolution
- Match browser window to PNG dimensions
4. Use browser dev tools
- Inspect Stitch HTML element sizes
- Match in React output
---
Issue: Conflict Resolution Unclear
Symptoms
- Multiple conflicts detected
- Unsure which takes precedence
- User hasn't provided guidance
Cause
Skill requires explicit user decision for conflicts.
Solution
1. Present conflicts clearly
## Conflicts Requiring Decision
1. Border Radius: Stitch 4px vs Pattern 8px
2. Primary Color: Stitch #3B82F6 vs Pattern #0078D4
Please choose for each: [Stitch] or [Pattern] or [Hybrid]2. Provide recommendations
Recommended: Use Pattern values for consistency
Exception: Use Stitch if this is a new design direction3. Wait for explicit decision Do not proceed with conversion until conflicts are resolved.
---
Issue: Component Hierarchy Too Flat
Symptoms
- Single large component file
- Hard to maintain or reuse parts
- Doesn't follow project structure
Cause
Skill generated monolithic component instead of decomposing.
Solution
1. Request decomposition
"Break this component into smaller, reusable parts"2. Follow project patterns
- Check existing component structure
- Match naming conventions
- Use same folder organization
3. Decomposition guidelines
- Atomic: Single-purpose (Button, Icon, Input)
- Composite: Combined atomics (FormField, Card, ListItem)
- Layout: Structure (Header, Sidebar, PageLayout)
- Screen: Full pages (Dashboard, Settings)
---
Issue: TypeScript Types Missing or Wrong
Symptoms
anytypes used- Props not properly typed
- Type errors in IDE
Cause
Type generation skipped or incorrect inference.
Solution
1. Request explicit types
"Generate full TypeScript interfaces for all components"2. Check types.ts file
- Should exist in component directory
- Should export all interfaces
3. Verify prop types match usage
// types.ts
export interface CardProps {
title: string;
description?: string;
onClick?: () => void;
}
// Card.tsx
export const Card: React.FC<CardProps> = ({
title,
description,
onClick,
}) => {
// Implementation
};---
Issue: Stitch Skill Not Auto-Invoking
Symptoms
- Mentioned Stitch exports but skill didn't activate
- Got generic response instead of conversion
Cause
Context didn't trigger skill detection.
Solution
Use explicit trigger phrases:
- "Convert the Stitch export to React"
- "Process design-intent/google-stitch/{feature}/"
- "Stitch to React: {feature name}"
- "Generate React components from Stitch HTML"
Or reference files directly:
"Convert design-intent/google-stitch/dashboard/exports/01-layout.html to React"---
Getting Help
If issues persist:
1. Check project setup
/design-intent/directory exists- Design system detected correctly
- Patterns documented
2. Verify Stitch exports
- HTML files are valid
- PNG references exist
- tailwind.config present
3. Review constitution
/design-intent/memory/constitution.md- Check for project-specific guidelines
4. Create diary entry
- Document the issue
- Run
/diaryto capture context
Detailed Workflow
Complete conversion process for transforming Google Stitch exports into React components.
Table of Contents
- Phase 1: Load Project Context
- Phase 2: Scan Stitch Exports
- Phase 3: Map to Project Design System
- Phase 4: Conflict Detection
- Phase 5: Component Generation
- Stitch Code Format Reference
- Output Structure
---
Phase 1: Load Project Context
This step is mandatory before any conversion.
Steps
1. Read constitution
/design-intent/memory/constitution.mdExtract: simplicity principles, framework-first mandate, responsive requirements
2. Scan patterns directory
/design-intent/patterns/List all .md files and extract key decisions
3. Detect design system
- Check
package.jsonfor UI libraries - Common systems: Fluent UI, Material UI, Chakra, Tailwind
- Note: Stitch outputs Tailwind - may need conversion
4. Report findings
Project Context:
- Design System: Fluent UI v9
- Existing patterns: 5 found
- button-styling.md: 8px radius, primary/secondary variants
- card-layout.md: 16px padding, subtle shadow
- spacing-scale.md: 8px base unit
- typography-scale.md: Inter font, 14px base
- animation-timing.md: 200ms ease-out transitions
- Constitution: Framework-first, mobile-first responsive---
Phase 2: Scan Stitch Exports
Export Structure
Stitch generates paired HTML + PNG files:
design-intent/google-stitch/{feature}/
├── exports/ # Core output
│ ├── 01-layout-{name}.html
│ ├── 01-layout-{name}.png
│ ├── 02-component-{name}.html
│ ├── 02-component-{name}.png
│ └── ...
├── prompt-v{N}.md # Source prompts (context)
├── wireframes/ # Input mockups (optional)
└── design-dna.md # Design context (optional, from MCP)Extraction Checklist
For each HTML file:
- [ ] Tailwind config - Custom theme extensions
- [ ] Color palette - Extract from config
colorssection - [ ] Typography - Font families, sizes from config
- [ ] Spacing - Custom spacing values
- [ ] Custom CSS - Animations, keyframes from
<style>tags - [ ] DOM structure - Component hierarchy
- [ ] Icons - Material Symbols usage
- [ ] Interactive states - Hover, focus, active classes
Processing Order
1. Start with layout files (01-layout-*) 2. Process component files in numbered order 3. Cross-reference PNG files for visual verification
---
Phase 3: Map to Project Design System
Component Decomposition
Break Stitch screens into smaller, reusable parts:
Stitch Screen: Dashboard Layout
├── Header (reuse existing if available)
├── Sidebar Navigation (reuse or create)
├── Content Area
│ ├── Page Title (atomic)
│ ├── Filter Bar (composite)
│ └── Data Grid (reuse existing)
└── Footer (optional)Token Mapping
Convert Stitch Tailwind tokens to project tokens:
| Stitch (Tailwind) | Fluent UI | CSS Variables |
|---|---|---|
bg-blue-500 | colorBrandBackground | --color-primary |
text-gray-900 | colorNeutralForeground1 | --text-primary |
rounded-lg | borderRadiusMedium | --radius-md |
p-4 | spacingHorizontalM | --space-4 |
shadow-md | shadow8 | --shadow-md |
Component Mapping
Check each Stitch element against existing patterns:
Stitch Element: Card with gradient header
├── Check: card-layout.md pattern exists?
│ └── Yes: Reuse, extend for gradient
├── Check: Fluent UI Card component?
│ └── Yes: Use as base
└── Result: Extend Fluent Card with custom headerGap Analysis
Identify elements needing custom components:
Custom Components Needed:
1. GradientHeader - No pattern match, requires custom CSS
2. AnimatedCounter - Uses Stitch keyframe animation
3. MultiStateButton - 6 visual states beyond standard---
Phase 4: Conflict Detection
Detection Points
Compare at each layer:
1. Spacing - Stitch padding/margins vs pattern spacing 2. Colors - Stitch palette vs design tokens 3. Typography - Font sizes/weights vs type scale 4. Borders - Radius values vs pattern standards 5. Animations - Timing/easing vs motion guidelines
Conflict Report Format
## Design Conflicts Detected
### 1. Border Radius
**Stitch**: 4px (`rounded`)
**Pattern**: 8px (button-styling.md)
**Elements affected**: All buttons, cards
### 2. Primary Color
**Stitch**: #3B82F6 (blue-500)
**Pattern**: #0078D4 (Fluent brand)
**Elements affected**: CTAs, links, focus states
### Options for Each
1. Follow Stitch - Use exported values
2. Use pattern - Adapt to existing standard
3. Hybrid - Use Stitch for new components, pattern for existing
**Please select approach for each conflict.**Resolution Recording
After user decision:
// CONFLICT RESOLUTION: Border radius
// Decision: Use pattern (8px)
// Reason: Maintain consistency with existing components
// Date: YYYY-MM-DD---
Phase 5: Component Generation
File Structure
src/components/{feature}/
├── index.ts # Re-exports
├── types.ts # Shared interfaces
├── tokens.ts # Extracted design tokens
├── {MainComponent}.tsx # Screen-level component
├── {SubComponent1}.tsx # Decomposed parts
├── {SubComponent2}.tsx
└── {SubComponent}.styles.ts # If using CSS-in-JSComponent Template
/**
* CUSTOM COMPONENT: ComponentName
* Source: {stitch-screen-name}.html
* Base: @fluentui/react-components/Card (if applicable)
* Reason: Required gradient background not available in base
* Created: YYYY-MM-DD
*
* Original Reference: design-intent/google-stitch/{feature}/exports/{screen}.png
*/
import React from 'react';
import { tokens } from './tokens';
import type { ComponentNameProps } from './types';
export const ComponentName: React.FC<ComponentNameProps> = ({
// props
}) => {
return (
// JSX
);
};Tokens File Template
/**
* Design tokens extracted from Stitch export
* Source: design-intent/google-stitch/{feature}/exports/
*
* These tokens bridge Stitch output to project design system.
* Map to existing design tokens where possible.
*/
// Colors from Stitch tailwind.config
export const stitchColors = {
primary: '#3B82F6', // blue-500 -> maps to colorBrandBackground
secondary: '#6B7280', // gray-500 -> maps to colorNeutralForeground2
background: '#F9FAFB', // gray-50 -> maps to colorNeutralBackground2
} as const;
// Spacing (convert from Tailwind to px)
export const stitchSpacing = {
xs: '4px', // p-1
sm: '8px', // p-2
md: '16px', // p-4
lg: '24px', // p-6
xl: '32px', // p-8
} as const;
// Typography
export const stitchTypography = {
fontFamily: 'Inter, system-ui, sans-serif',
sizes: {
xs: '12px',
sm: '14px',
base: '16px',
lg: '18px',
xl: '20px',
'2xl': '24px',
},
} as const;Types File Template
/**
* TypeScript interfaces for {Feature} components
* Generated from Stitch export analysis
*/
export interface ComponentNameProps {
/** Primary content */
title: string;
/** Optional description */
description?: string;
/** Click handler */
onClick?: () => void;
}
export interface SubComponentProps {
// ...
}---
Stitch Code Format Reference
Typical Stitch HTML Structure
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Screen Name</title>
<script src="https://cdn.tailwindcss.com?plugins=forms,container-queries"></script>
<script>
tailwind.config = {
theme: {
extend: {
colors: {
primary: '#3B82F6',
// Custom colors
},
fontFamily: {
sans: ['Inter', 'system-ui', 'sans-serif'],
},
},
},
};
</script>
<link href="https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined" rel="stylesheet">
<style>
/* Custom animations */
@keyframes fadeIn {
from { opacity: 0; }
to { opacity: 1; }
}
.animate-fadeIn {
animation: fadeIn 0.3s ease-out;
}
</style>
</head>
<body class="bg-gray-50">
<!-- Component markup -->
</body>
</html>Key Elements to Extract
1. `tailwind.config` - Theme customizations 2. `<style>` blocks - Custom CSS, animations 3. `<body>` content - Component markup 4. Material Symbols - Icon usage patterns
---
Output Structure
Final Deliverables
1. React components - TypeScript, properly typed 2. Design tokens - Bridging Stitch to project 3. Type definitions - Full TypeScript coverage 4. Conflict log - Documented resolutions 5. Pattern suggestions - New patterns to document
Quality Checklist
- [ ] All components use project design system where possible
- [ ] Custom components have documentation headers
- [ ] Tokens map to existing design tokens
- [ ] Responsive behavior implemented (mobile-first)
- [ ] Conflicts documented and resolved
- [ ] Visual fidelity verified against PNG references