--- name: stitch-react-native-components description: Converts a Stitch mobile screen, a local HTML file, or a URL into React Native / Expo components — TypeScript, StyleSheet, Expo Router, dark mode via useColorScheme, and proper touch targets. Cross-platform iOS and Android. Only the Stitch route needs an API key. allowed-tools: - "stitch*:*" - "Bash" - "Read" - "Write" --- # Stitch → React Native / Expo Components You are a React Native engineer. You convert mobile UI layouts — a Stitch screen generated with `deviceType: MOBILE`, a local HTML file, or a URL — into cross-platform React Native components using Expo. You work in TypeScript, use `StyleSheet.create` for styles, and follow Expo Router conventions for navigation. ## When to use this skill Use this skill when: - The user wants a **native mobile app** (iOS + Android) from an existing design - The user mentions "React Native", "Expo", "mobile app", "iOS", "Android" - The source is a **mobile layout** — narrow, vertical, touch-sized targets (a Stitch screen with `deviceType: MOBILE`, or a local file/URL that reads as mobile) **Note:** For a mobile WebView app (Capacitor, Ionic, PWA), use `stitch-html-components` instead. React Native outputs actual native UI — not web views. ## Prerequisites A mobile-layout source, read as structural and visual reference only — nothing here ships, RN components get written from scratch. Any one of these works: - A **Stitch screen** — needs Stitch MCP access and a screen generated with `deviceType: MOBILE` - A **local HTML file** of a mobile layout — no Stitch account required - A **URL** rendering a mobile layout — no Stitch account required Desktop layouts don't translate well to RN, regardless of which route you took — verify the source is narrow and vertical before converting. Also: - Target project uses **Expo** (SDK 50+) — not bare React Native - `expo-router` for file-based navigation ## Step 1: Resolve the source Everything downstream reads one file: `temp/source.html`. Get the HTML there by whichever route matches what the user gave you, then continue at Step 2 — the rest of this skill is identical regardless of where the markup came from. This skill only works on a **mobile layout** — narrow, vertical, touch-sized targets. Desktop layouts don't translate to RN regardless of source. How you confirm mobile-ness depends on where the HTML came from: - **Stitch screen** — check it was generated with `deviceType: MOBILE`. If the screenshot shows a desktop layout, stop and tell the user to regenerate with `deviceType: MOBILE` first. - **Local HTML file or URL** — inspect the markup: a `` tag, mobile-first media queries, a narrow `max-width` on the root container, touch-sized tap targets. If it's clearly a desktop layout (wide multi-column grid, hover-only interactions, no viewport meta), stop and tell the user the source isn't a mobile layout — don't tell them to "regenerate with deviceType: MOBILE," that instruction is meaningless outside Stitch. **From a Stitch screen:** 1. **Namespace discovery** — `list_tools` to find the Stitch MCP prefix 2. **Fetch metadata** — `[prefix]:get_screen` for the design JSON 3. **Download HTML** — GCS URLs need the reliable downloader: ```bash bash scripts/fetch-stitch.sh "[htmlCode.downloadUrl]" "temp/source.html" ``` 4. **Visual audit** — check `screenshot.downloadUrl` before converting. Append `=s0` to that URL for full resolution; the bare URL serves a 512px thumbnail regardless of the `width`/`height` the API reports. Confirm it's a mobile layout, per the check above. **From a local HTML file:** ```bash mkdir -p temp && cp "path/to/design.html" temp/source.html ``` Open it and confirm it's a mobile layout, per the check above. **From a URL:** ```bash bash scripts/fetch-stitch.sh "https://example.com/page" "temp/source.html" ``` Despite the name, that script is a generic hardened downloader — follows redirects, retries transient failures, handles gzip, and fails loudly on an empty result. It does not care whether the URL points at Stitch. Confirm the page is a mobile layout, per the check above. **From a screenshot:** there's no upload route — the Stitch MCP API has no image-upload tool. Either recreate the design from a text prompt via `stitch-mcp-generate-screen-from-text`, or hand-write the HTML and use the local-file route above. > Only the Stitch route needs an API key. Converting a local file or a URL works with no Google account at all. ## Step 2: Project structure ``` app/ ├── (tabs)/ │ ├── _layout.tsx ← Tab navigator │ ├── index.tsx ← Home tab │ └── [other-tabs].tsx ├── _layout.tsx ← Root layout (ThemeProvider, SafeAreaProvider) └── modal.tsx ← Modal routes src/ ├── components/ ← Reusable components │ └── [Name].tsx ├── data/ │ └── mockData.ts ← Static content — never hardcoded in components ├── theme/ │ ├── tokens.ts ← Design tokens as TypeScript constants │ └── useTheme.ts ← Hook to access current theme tokens └── types/ └── index.ts ``` ## Step 3: The HTML → React Native mapping This is the core of the conversion. Apply these rules systematically: ### Layout mapping | HTML/CSS | → React Native | |---|---| | `
` | `` | | `
` | `` | | `
` | `` with `width:'50%'` children | | `overflow-y: scroll` container | `` | | Long lists | `` | | `position: fixed` bottom nav | `` | | `position: absolute` overlay | `` inside a parent with `position:'relative'` | ### Content mapping | HTML | → React Native | |---|---| | `

`, ``, text nodes | `` | | `

` → `

` | `` with large font size + fontWeight: 'bold' | | `` | `` | | `