skills/golem-powers/stitch-design/SKILL.md
Design-to-code using Google Stitch MCP. Read admin designs, craft prompts for Stitch to generate new screens within the existing design system, grill user about behavior, implement in React Native. Claude = prompt engineer for Stitch. Stitch = design generator. Use when: implementing from Stitch, generating screen prototypes, extracting design tokens.
npx skillsauth add etanhey/golems stitch-designInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Claude = prompt engineer for Stitch. Stitch = design generator. Claude understands the flow, the design system, the user's intent — then writes a detailed prompt that Stitch executes. Claude does NOT design. Stitch does.
SYNC → Push app's theme (colors.ts, typography.ts) into Stitch's designMd field
READ → Pull existing admin designs (get_screen → screenshot URL + htmlCode, list_design_systems)
PROMPT → Craft detailed prompts for Stitch to generate new screens WITHIN the design system
GRILL → Ask user about behavior, flow, states, edge cases (Stitch = static, app = dynamic)
IMPLEMENT → Build in React Native, matching Stitch visuals + wired behavior
Always use the existing design system. Yuval's project has established colors (#8B5CF6 purple), fonts (Inter/DM Sans), theme (DARK, ROUND_TWELVE, EXPRESSIVE). When generating new screens:
extract_design_context from a reference screen FIRSTgenerate_screen_from_textThe designMd field is the bridge. This free-text field in the design system tells Stitch HOW to generate. Claude writes designMd from the MeHayom codebase (existing colors, fonts, components, RTL patterns) and pushes it to Stitch via update_design_system. This makes ALL Stitch generations match the app automatically.
13909929656240674656 — source of truth, READ from here8212157323460658039 — experiment/generate hereAlready in ~/Gits/Mehayom-app/.mcp.json. Run /mcp to connect. Tools appear as mcp__stitch__*.
READ tools:
| Tool | What | When |
|------|------|------|
| list_projects | List all Stitch projects | Boot — find project ID |
| get_project | Get project metadata | Verify project details |
| list_screens | List screens in a project | See what designs exist |
| get_screen | Get screen details + screenshot URL + htmlCode | THE main read tool — returns title, dimensions, downloadUrl, htmlCode |
| list_design_systems | Read current design system | Verify theme tokens |
GENERATE tools (Claude = prompt engineer, Stitch = renderer):
| Tool | What | When |
|------|------|------|
| generate_screen_from_text | Generate screen from Claude's prompt | New screens — always use design system context |
| edit_screens | Modify a screen with instructions | Iterate on a generated prototype |
| generate_variants | Produce design variations | Explore options within the design system |
SYNC tools (bridge code ↔ design):
| Tool | What | When |
|------|------|------|
| create_design_system | Create design system with designMd | First-time setup |
| update_design_system | Push updated designMd to Stitch | After app theme changes |
| apply_design_system | Apply design system to screens | Propagate style changes |
Other:
| Tool | What | When |
|------|------|------|
| create_project | Create a new Stitch project | Only if starting from scratch |
These were listed in community wrapper docs but are NOT in Google's official MCP:
get_screen~~ → use get_screen (returns screenshot.downloadUrl)get_screen_code~~ → use get_screen (returns htmlCode)extract_design_context~~ → NOT available upstream. Read colors manually from get_screen htmlCode.build_site~~ → NOT in official MCPRun this FIRST in any new project or after theme changes. This writes the app's design reality into Stitch's designMd field so all generations match the app.
1. Read app theme files:
- app/theme/colors.ts → extract all color constants
- app/theme/typography.ts → extract font families, sizes, weights
- Scan components/ for common patterns (border radius, spacing, shadows)
2. Read RTL patterns:
- Check I18nManager usage, writingDirection props
- Note which components handle RTL explicitly
3. Craft designMd string from the ACTUAL app theme:
"MeHayom — Hebrew RTL anti-addiction app. Dark cosmic purple theme.
Colors: primary #8B5CF6, secondary #6366F1, accent #A855F7.
Backgrounds: #0A0A1A deepSpace (main), #150B2E midnight (secondary), #2A1B4E cosmic (cards).
Text: #FFFFFF white, #94A3B8 gray secondary. Gradients: #8B5CF6→#6366F1→#4F46E5.
Status: #10B981 green, #EF4444 red, #F59E0B amber. Blue borders #4F46E5.
Layout: RTL-first, bottom-anchored CTAs, shield icon for protection states.
Typography: sizes 12/14/16/20/28px, weights 400-700. Rank colors: green→blue progression."
4. Push to Stitch:
update_design_system(projectId, { designSystem: { theme: { designMd: "..." } } })
5. Verify: list_design_systems → confirm designMd is set
designMd is the single most important field. It's free-text that Stitch reads before every generation. A good designMd = every generated screen matches the app without manual adjustment.
When Yuval shares a new design or points to a Stitch screen:
READ from shared (Yuval's originals). GENERATE in ours (experiments).
1. list_screens(projectId: "projects/13909929656240674656") → Yuval's designs (source of truth)
2. get_screen(screenName) → returns:
- title, width, height
- screenshot.downloadUrl (Google CDN link to PNG)
- htmlCode (the design's HTML/CSS)
3. Download the screenshot URL with WebFetch or save for visual reference
4. Parse htmlCode for colors, fonts, layout structure
5. list_design_systems → read current theme tokens (colorMode, fonts, roundness)
Output: You now know WHAT it looks like. You do NOT know HOW it behaves.
If Yuval shared a WhatsApp screenshot instead of a Stitch link:
list_screens → scan screen names for a matchget_screen for each candidate → compare title/dimensionsClaude = prompt engineer. Stitch = design generator. Claude crafts detailed, context-rich prompts. Stitch renders them.
1. extract_design_context(referenceScreenId) → capture existing "design DNA"
2. Understand what the user wants: "I need a settings screen" or "add a premium paywall"
3. Craft a detailed prompt for Stitch:
GOOD PROMPT:
"Settings screen for Hebrew RTL anti-addiction app. Dark purple (#8B5CF6) background
with subtle gradient. Inter font throughout. Cards for each setting group:
'הגדרות חשבון' (account), 'התראות' (notifications), 'פרטיות' (privacy).
Toggle switches with purple active state. Bottom navigation bar visible.
Shield icon in header. 12px border radius on all cards. Match the visual style
of the existing warning screens."
BAD PROMPT:
"Make a settings page"
4. generate_screen_from_text(prompt) → Stitch renders the design
5. get_screen(generatedScreenName) → review screenshot.downloadUrl
6. If not right: edit_screens with specific corrections, or re-prompt
7. If exploring options: generate_variants for alternatives
Prompt engineering tips for MeHayom:
Stitch shows STATIC designs. The app has DYNAMIC behavior. You MUST ask:
For every screen, ask these questions:
FLOW QUESTIONS:
- "What happens when the user taps [button]?"
- "Where does this screen appear in the navigation flow?"
- "What screen comes before this? What comes after?"
- "Is there a countdown/timer? What happens when it ends?"
STATE QUESTIONS:
- "What does this screen look like in [other state]?" (loading, error, empty)
- "Can the user go back from here?"
- "What if the user is not premium?"
- "Does this need to work offline?"
DATA QUESTIONS:
- "Where does [this text/number] come from?" (hardcoded, API, local state)
- "Is this text translated or always Hebrew?"
- "Does this update in real-time?"
EDGE CASES:
- "What if the user rotates the phone?"
- "What if the text is longer than expected?"
- "What about accessibility — VoiceOver labels?"
Yuval's Stitch design shows the warning screen. GRILL uncovered the BEHAVIOR:
startDate)countRelapse, longestStreak, milestone badges)The Stitch design showed NONE of this — just a static screen. The GRILL workflow extracted the flow.
Ask 2-3 at a time. Don't dump all questions at once. Drill based on answers.
Store answers: brain_store the flow decisions with tags ["mehayom", "design-flow", screenName]. These persist across sessions — next time someone implements from this screen, the flow answers are already in BrainLayer.
Once you have the visual (from READ) and the behavior (from GRILL):
1. get_screen(screenName) → HTML/CSS reference
2. Map HTML structure to React Native:
- div → View
- p/span → Text
- img → Image (or Expo Image)
- button → Pressable/TouchableOpacity
- CSS flexbox → RN flexbox (same API)
- CSS colors → theme/colors.ts constants
- CSS fonts → theme/typography.ts
- px values → responsive units
3. RTL handling (CRITICAL for Hebrew):
- flexDirection: 'row' is REVERSED in RTL
- textAlign: 'right' for Hebrew content
- writingDirection: 'rtl' on Text components
- Mirror directional icons (arrows, chevrons)
- I18nManager.isRTL for conditional logic
4. Wire behavior from GRILL answers:
- Navigation (router.push/replace/back)
- State management (useState, Convex queries)
- Timers (useEffect + cleanup)
- Animations (Reanimated or LayoutAnimation)
5. Screenshot implementation → compare side-by-side with Stitch
STITCH HTML/CSS → REACT NATIVE
──────────────────────────────────────────────────────
<div class="flex flex-col"> → <View style={{ flexDirection: 'column' }}>
background: #8B5CF6 → backgroundColor: colors.primary
font-family: Inter → fontFamily: typography.heading.fontFamily
border-radius: 12px → borderRadius: 12
padding: 16px → padding: 16
box-shadow: ... → elevation: 4 (Android) / shadowColor (iOS)
background: linear-gradient(...) → <LinearGradient> (expo-linear-gradient)
position: fixed → position: 'absolute' (RN has no fixed)
overflow: scroll → <ScrollView>
STITCH DESIGN SYSTEM → APP CONSTANTS (constants/)
──────────────────────────────────────────────────────
customColor: "#8B5CF6" → colors.primary (#8B5CF6)
colorMode: "DARK" → colors.background (#0A0A1A)
headlineFont: "INTER" → system default (no custom fonts in RN yet)
bodyFont: "INTER" → system default
labelFont: "DM_SANS" → system default
roundness: "ROUND_TWELVE" → borderRadius: 12 (per component)
colorVariant: "EXPRESSIVE" → colors.gradient (#8B5CF6→#6366F1→#4F46E5)
designMd: (our crafted text) → THE BRIDGE — describes all of the above to Stitch
Discrepancy: Stitch uses Inter/DM Sans but the RN app uses system fonts.
Either install custom fonts in Expo (expo-font) or accept the difference.
When extract_design_context returns new values that differ from the app theme files, flag it:
"Stitch shows [X] but app/theme/colors.ts has [Y]. Should I update the app to match?"
| Trigger | Action |
|---------|--------|
| Yuval sends WhatsApp screenshot | READ workflow → match in Stitch → GRILL about flow → IMPLEMENT |
| New Stitch screen appears | list_screens detects it → notify user → wait for implementation request |
| Theme change in Stitch | extract_design_context → diff with app theme → flag discrepancies |
| PR review for UI changes | get_screen → compare with implementation screenshot |
| User says "does this match?" | get_screen + app screenshot → side-by-side comparison |
ALL text is i18n. Never hardcode Hebrew or English strings in components.
t('warning.countdown') not "רוצה לחזור אחורה?"textAlign: 'right', alignItems: 'flex-end'I18nManager.isRTL ? 'flip' : undefinedpaddingStart/paddingEnd instead of paddingLeft/paddingRightRead-only tools we'd benefit from:
compare_designs — diff two Stitch screens (useful when Yuval iterates)extract_components — isolate reusable UI patterns from screensanalyze_accessibility — WCAG 2.1 check on Stitch designs before implementing| Gap | Impact | Fix |
|-----|--------|-----|
| screen_to_react_native | HIGH — manual HTML→RN every time | Fork oogleyskr's screen_to_react, add RN output |
| Theme.ts sync | MEDIUM — manual token copy | Build codegen: extract_design_context → theme.ts |
| Stitch↔implementation diff | MEDIUM — manual screenshot comparison | Build: overlay Stitch PNG on app screenshot, highlight differences |
~/Gits/Mehayom-app/
├── .mcp.json # Stitch MCP config (connected)
├── app/theme/colors.ts # App colors (sync target)
├── app/theme/typography.ts # Font definitions (sync target)
├── app/components/ # Existing RN components
├── docs.local/stitch-mcp-reference.md # MCP reference notes
└── ~/Desktop/Stitch screens/ # Local screenshots (5 files, Apr 6)
tools
The human-eval UX contract for Phoenix views: turn-by-turn scrollable replay (not a scorecard), hide-but-copyable IDs, collapsed thinking, identity chips, tool filters, tiny frozen starter datasets, mark-wrong-in-thread, mobile-first. Use when: building or reviewing ANY Phoenix/eval view, annotation UI, session replay, or human-grading surface. Triggers: phoenix view, eval UI, annotation view, session replay, human eval UX, grading interface. NOT for: Phoenix data pipelines/ingest (capture scripts have their own specs).
tools
macOS systems specialist — AppKit NSPanel architecture, launchd services, socket activation, MCP bridge resilience, syspolicyd, and high-frequency SwiftUI dashboards. Use when building menu-bar apps, LaunchAgents, debugging syspolicyd/Gatekeeper/TCC, resilient UDS/MCP bridges, or SwiftUI dashboards at 10Hz+.
development
Bulk LLM-judging protocol for fleet-dispatched verdict runs (KG cluster, eval harness). Use when: dispatching or running judge workers (J1/J2/RT), planning bulk-apply from verdict JSONL, or triaging evidence_degraded outputs. Triggers: judge fleet, bulk judge, R3 verdicts, kg-judge, RT gate, evidence_degraded. NOT for: single-item code review, Phoenix view UX (use phoenix-human-view), or non-judge eval pipelines.
development
Quiet-down protocol for sprint close: when the fleet wraps, delete ALL polling crons and monitors, send ONE final dashboard + ONE message, then go SILENT. Use when: fleet wraps, all workers done, overnight queue exhausted, sprint close, Etan asleep/away with nothing approved left. Triggers: fleet wrap, wrap the fleet, stand down, going quiet, sprint close. NOT for: mid-sprint monitoring (keep your loops), spawning a successor (use /session-handoff first).