Expo From Claude Design
This skill converts visual UI input (Claude Design handoff, HTML/CSS, screenshots, Figma) into production-ready Expo React Native code using NativeWind for styling and Expo Router for navigation.
When this skill triggers
- User pastes a Claude Design bundle ID or claude.ai/design link
- User uploads or pastes a screenshot of a UI mockup
- User provides HTML/CSS code that needs to be ported to React Native
- User references a Figma frame URL with intent to implement in Expo
- User asks to "code this design", "implement this mockup", "make this screen", and the project is Expo
Workflow overview
1. Detect input format (Claude Design bundle | image | HTML | Figma | text description)
2. Validate Expo project context (check package.json, app/ directory, NativeWind config)
3. Trigger Superpowers brainstorm to clarify intent and scope
4. Generate spec with acceptance criteria
5. Decompose into 2-5 minute tasks
6. Apply conversion rules (HTML → RN, CSS → NativeWind, events → onPress)
7. Extract reusable components when pattern repeats 3+ times
8. Place files according to Expo Router conventions
9. Apply quality gates (accessibility, tests, types)
10. Trigger code-review before completion
Source format detection
Auto-detect based on input:
| Input type |
Detection |
| Claude Design bundle |
URL contains claude.ai/design or starts with cd_ prefix |
| Image upload |
File attachment with extension .png .jpg .webp |
| HTML/CSS snippet |
Code block starting with <html>, <div>, or <style> |
| Figma URL |
URL contains figma.com/design |
| Text description |
Plain natural language UI description |
HTML → React Native element mapping
| HTML |
React Native |
Import from |
<div> |
<View> |
react-native |
<p>, <span>, <h1>-<h6> |
<Text> |
react-native |
<button> |
<Pressable> |
react-native |
<a href> |
<Link href> |
expo-router |
<a onClick> |
<Pressable onPress> |
react-native |
<img> |
<Image> |
expo-image (preferred) |
<input type="text"> |
<TextInput> |
react-native |
<input type="checkbox"> |
<Switch> |
react-native |
<input type="radio"> |
Custom Pressable group |
react-native |
<textarea> |
<TextInput multiline numberOfLines={4}> |
react-native |
<select> |
<Picker> |
@react-native-picker/picker |
<ul>, <ol>, <li> |
<FlatList> or <View> + .map() |
react-native |
<svg> |
Component from react-native-svg |
react-native-svg |
<form> |
<View> + state management |
react-native |
Event handler mapping
| Web event |
React Native event |
onClick |
onPress |
onDoubleClick |
onLongPress (closest equivalent) |
onMouseEnter / onMouseOver |
onPressIn |
onMouseLeave / onMouseOut |
onPressOut |
onFocus |
onFocus (same) |
onBlur |
onBlur (same) |
onChange (input) |
onChangeText (TextInput) |
onSubmit (form) |
Manual handler triggered by Pressable |
onScroll |
onScroll (same, on ScrollView/FlatList) |
CSS → NativeWind classes
Most Tailwind utility classes work directly in NativeWind. Key differences:
Use freely (most utilities work)
- Sizing:
w-*, h-*, min-w-*, max-h-*
- Spacing:
p-*, m-*, gap-*
- Flex:
flex, flex-row, flex-col, items-*, justify-*
- Background:
bg-*
- Text:
text-*, font-*, leading-*, tracking-*
- Borders:
border-*, rounded-*
- Shadow:
shadow-* (limited support, test on device)
Skip these (web-only, won't work)
cursor-* (no cursor on mobile)
select-* (no text selection control)
pointer-events-* (different mobile model)
hover:* (no hover, use Pressable states instead)
divide-* (no equivalent, use borders manually)
space-x-*, space-y-* (use gap-* instead)
prose (no Typography plugin in NativeWind)
Replace these patterns
- Fixed pixel values (
width: 200px) → Tailwind classes (w-52)
- Hover states → Pressable states via
({pressed}) => className={...}
- Media queries →
Platform.OS checks or NativeWind responsive prefixes
position: fixed → No equivalent, use absolute positioning + safe areas
- CSS variables → Theme tokens via NativeWind config
Component extraction rules
When converting a design, ALWAYS scan for repeated patterns and extract:
| Pattern |
Extract as |
Place in |
| Same Text style 3+ occurrences |
Typography component (e.g. <Heading>, <Body>) |
components/typography.tsx |
| Same button style 3+ |
<Button variant="primary|secondary|ghost"> |
components/button.tsx |
| Same card layout 3+ |
<Card> with props |
components/card.tsx |
| Same icon wrapper pattern |
<Icon name="..." /> |
components/icon.tsx |
| Same input style |
<Input label="..." /> |
components/input.tsx |
| Same list item structure |
<ListItem> |
components/list-item.tsx |
Don't over-extract. Less than 3 occurrences = leave inline.
File placement (Expo Router conventions)
app/ # Routes (file-based)
├── (tabs)/ # Tab navigator group
│ ├── _layout.tsx
│ ├── index.tsx # Home tab
│ └── profile.tsx
├── (auth)/ # Auth group (modal/stack)
│ ├── sign-in.tsx
│ └── sign-up.tsx
├── _layout.tsx # Root layout
└── +not-found.tsx
components/ # Reusable UI components
├── ui/ # Atomic UI primitives
│ ├── button.tsx
│ ├── card.tsx
│ └── input.tsx
└── feature/ # Feature-specific components
hooks/ # Custom hooks
lib/ # Utilities, API clients
types/ # TypeScript types
constants/ # Tokens, colors, sizes
Mandatory top-level wrapping
Every full screen MUST include:
import { SafeAreaView } from 'react-native-safe-area-context';
import { ScrollView } from 'react-native';
export default function Screen() {
return (
<SafeAreaView className="flex-1 bg-background">
<ScrollView className="flex-1" contentContainerClassName="p-4">
{/* Screen content */}
</ScrollView>
</SafeAreaView>
);
}
Exceptions:
- Use
FlatList instead of ScrollView when rendering >20 items
- Skip ScrollView if screen is genuinely non-scrollable (e.g. splash)
- Modal screens: use
<View> with presentation: 'modal' in Expo Router
Quality gates (MUST apply)
Before completing the conversion, verify:
Patterns to AVOID
- Inline styles via
style={{...}} (use NativeWind className)
StyleSheet.create() (we use NativeWind exclusively)
- Hardcoded colors (use theme tokens:
bg-primary, text-foreground)
- Pixel values in JSX (use Tailwind:
w-12, not width: 48)
- Web-only APIs (
window, document, localStorage)
- Web-only libraries (use RN equivalents)
- Margin to create gaps (use
gap-* on parent flex container)
position: 'absolute' for layout (use flex, except for overlays)
- Tight coupling: avoid hardcoding navigation routes in components
Integration with project conventions
ALWAYS read CLAUDE.md at the project root first to detect:
- The stack version (Expo SDK, React Native, React)
- Style conventions (which Tailwind plugins, custom classes)
- State management library (Zustand, Jotai, Redux, Context)
- Data fetching (TanStack Query, SWR, raw fetch)
- Forms library (React Hook Form, Formik, native)
- Navigation structure (tabs, drawer, stack patterns)
- Existing components (don't duplicate, reuse)
If CLAUDE.md is missing, ASK the user before generating code that imposes opinions.
Orchestration with Superpowers
This skill is designed to compose with the Superpowers harness. When invoked:
Brainstorm phase: BEFORE generating any code, trigger Superpowers' brainstorming skill to clarify:
- Which screens are in scope vs out of scope
- Data sources (mock vs real backend)
- Navigation flow (where does this screen connect to)
- Edge cases (loading, error, empty, offline)
- Platform-specific concerns (iOS vs Android differences)
Spec phase: Generate acceptance criteria using Superpowers' writing-spec.
Plan phase: Decompose into 2-5min tasks using Superpowers' writing-plans.
TDD phase: For non-trivial logic (data fetching, form validation), write tests first using Superpowers' tdd.
Review phase: Trigger Superpowers' code-review before declaring done.
Output formatting
- Always provide a brief implementation summary
- List files created/modified with paths
- Note any TODOs or assumptions made
- Suggest next steps (test, refine, add backend wiring)
Failure modes to handle
- Ambiguous design: Ask clarifying questions before guessing
- Missing context: Detect and request CLAUDE.md or project info
- Out-of-scope element: Stub it and add a TODO, don't fabricate behavior
- Complex animation requested: Use Reanimated 3, or note as future work
- Native module needed: Note that EAS Build will be required (vs Expo Go)
1---2name: expo-from-claude-design3description: Convert a Claude Design handoff bundle, HTML/CSS mockup, or design screenshot into production-ready Expo React Native code with NativeWind. ALWAYS use this skill when the user provides any of the following for an Expo/React Native project — a Claude Design link or bundle ID, a design screenshot/image, an HTML/CSS snippet, a Figma export, or any visual UI reference they want implemented as a mobile screen or component. Use even when the user does not explicitly mention Expo if the project context (CLAUDE.md, package.json with expo dependencies, app/ directory) indicates Expo Router. Use also when converting web UI code to React Native, or when the user mentions "transformer ce design", "implémente cette maquette", "code cet écran", "make this mobile".4---56# Expo From Claude Design78This skill converts visual UI input (Claude Design handoff, HTML/CSS, screenshots, Figma) into production-ready Expo React Native code using NativeWind for styling and Expo Router for navigation.910## When this skill triggers1112- User pastes a Claude Design bundle ID or claude.ai/design link13- User uploads or pastes a screenshot of a UI mockup14- User provides HTML/CSS code that needs to be ported to React Native15- User references a Figma frame URL with intent to implement in Expo16- User asks to "code this design", "implement this mockup", "make this screen", and the project is Expo1718## Workflow overview1920```211. Detect input format (Claude Design bundle | image | HTML | Figma | text description)222. Validate Expo project context (check package.json, app/ directory, NativeWind config)233. Trigger Superpowers brainstorm to clarify intent and scope244. Generate spec with acceptance criteria255. Decompose into 2-5 minute tasks266. Apply conversion rules (HTML → RN, CSS → NativeWind, events → onPress)277. Extract reusable components when pattern repeats 3+ times288. Place files according to Expo Router conventions299. Apply quality gates (accessibility, tests, types)3010. Trigger code-review before completion31```3233## Source format detection3435Auto-detect based on input:3637| Input type | Detection |38|---|---|39| Claude Design bundle | URL contains `claude.ai/design` or starts with `cd_` prefix |40| Image upload | File attachment with extension `.png .jpg .webp` |41| HTML/CSS snippet | Code block starting with `<html>`, `<div>`, or `<style>` |42| Figma URL | URL contains `figma.com/design` |43| Text description | Plain natural language UI description |4445## HTML → React Native element mapping4647| HTML | React Native | Import from |48|---|---|---|49| `<div>` | `<View>` | react-native |50| `<p>`, `<span>`, `<h1>`-`<h6>` | `<Text>` | react-native |51| `<button>` | `<Pressable>` | react-native |52| `<a href>` | `<Link href>` | expo-router |53| `<a onClick>` | `<Pressable onPress>` | react-native |54| `<img>` | `<Image>` | expo-image (preferred) |55| `<input type="text">` | `<TextInput>` | react-native |56| `<input type="checkbox">` | `<Switch>` | react-native |57| `<input type="radio">` | Custom Pressable group | react-native |58| `<textarea>` | `<TextInput multiline numberOfLines={4}>` | react-native |59| `<select>` | `<Picker>` | @react-native-picker/picker |60| `<ul>`, `<ol>`, `<li>` | `<FlatList>` or `<View>` + `.map()` | react-native |61| `<svg>` | Component from react-native-svg | react-native-svg |62| `<form>` | `<View>` + state management | react-native |6364## Event handler mapping6566| Web event | React Native event |67|---|---|68| `onClick` | `onPress` |69| `onDoubleClick` | `onLongPress` (closest equivalent) |70| `onMouseEnter` / `onMouseOver` | `onPressIn` |71| `onMouseLeave` / `onMouseOut` | `onPressOut` |72| `onFocus` | `onFocus` (same) |73| `onBlur` | `onBlur` (same) |74| `onChange` (input) | `onChangeText` (TextInput) |75| `onSubmit` (form) | Manual handler triggered by Pressable |76| `onScroll` | `onScroll` (same, on ScrollView/FlatList) |7778## CSS → NativeWind classes7980Most Tailwind utility classes work directly in NativeWind. Key differences:8182### Use freely (most utilities work)83- Sizing: `w-*`, `h-*`, `min-w-*`, `max-h-*`84- Spacing: `p-*`, `m-*`, `gap-*`85- Flex: `flex`, `flex-row`, `flex-col`, `items-*`, `justify-*`86- Background: `bg-*`87- Text: `text-*`, `font-*`, `leading-*`, `tracking-*`88- Borders: `border-*`, `rounded-*`89- Shadow: `shadow-*` (limited support, test on device)9091### Skip these (web-only, won't work)92- `cursor-*` (no cursor on mobile)93- `select-*` (no text selection control)94- `pointer-events-*` (different mobile model)95- `hover:*` (no hover, use Pressable states instead)96- `divide-*` (no equivalent, use borders manually)97- `space-x-*`, `space-y-*` (use `gap-*` instead)98- `prose` (no Typography plugin in NativeWind)99100### Replace these patterns101- Fixed pixel values (`width: 200px`) → Tailwind classes (`w-52`)102- Hover states → Pressable states via `({pressed}) => className={...}`103- Media queries → `Platform.OS` checks or NativeWind responsive prefixes104- `position: fixed` → No equivalent, use absolute positioning + safe areas105- CSS variables → Theme tokens via NativeWind config106107## Component extraction rules108109When converting a design, ALWAYS scan for repeated patterns and extract:110111| Pattern | Extract as | Place in |112|---|---|---|113| Same Text style 3+ occurrences | Typography component (e.g. `<Heading>`, `<Body>`) | `components/typography.tsx` |114| Same button style 3+ | `<Button variant="primary\|secondary\|ghost">` | `components/button.tsx` |115| Same card layout 3+ | `<Card>` with props | `components/card.tsx` |116| Same icon wrapper pattern | `<Icon name="..." />` | `components/icon.tsx` |117| Same input style | `<Input label="..." />` | `components/input.tsx` |118| Same list item structure | `<ListItem>` | `components/list-item.tsx` |119120Don't over-extract. Less than 3 occurrences = leave inline.121122## File placement (Expo Router conventions)123124```125app/ # Routes (file-based)126├── (tabs)/ # Tab navigator group127│ ├── _layout.tsx128│ ├── index.tsx # Home tab129│ └── profile.tsx130├── (auth)/ # Auth group (modal/stack)131│ ├── sign-in.tsx132│ └── sign-up.tsx133├── _layout.tsx # Root layout134└── +not-found.tsx135components/ # Reusable UI components136├── ui/ # Atomic UI primitives137│ ├── button.tsx138│ ├── card.tsx139│ └── input.tsx140└── feature/ # Feature-specific components141hooks/ # Custom hooks142lib/ # Utilities, API clients143types/ # TypeScript types144constants/ # Tokens, colors, sizes145```146147## Mandatory top-level wrapping148149Every full screen MUST include:150151```tsx152import { SafeAreaView } from 'react-native-safe-area-context';153import { ScrollView } from 'react-native';154155export default function Screen() {156 return (157 <SafeAreaView className="flex-1 bg-background">158 <ScrollView className="flex-1" contentContainerClassName="p-4">159 {/* Screen content */}160 </ScrollView>161 </SafeAreaView>162 );163}164```165166Exceptions:167- Use `FlatList` instead of `ScrollView` when rendering >20 items168- Skip ScrollView if screen is genuinely non-scrollable (e.g. splash)169- Modal screens: use `<View>` with `presentation: 'modal'` in Expo Router170171## Quality gates (MUST apply)172173Before completing the conversion, verify:174175- [ ] Every `<Pressable>` has `accessibilityLabel`176- [ ] Every interactive element has `accessibilityRole` ("button", "link", etc.)177- [ ] Every interactive element has a stable `testID` prop178- [ ] Loading states implemented (skeleton or spinner) for async data179- [ ] Empty states implemented for lists180- [ ] Error states with retry CTA for fetch operations181- [ ] No `console.log` in production code182- [ ] No `any` type — use proper types or `unknown` with type guards183- [ ] All images have `accessibilityLabel` and `contentFit` prop184- [ ] FlatList has `keyExtractor` (never use index as key)185- [ ] All text supports dynamic sizing (no fixed `fontSize` in pixels)186187## Patterns to AVOID188189- Inline styles via `style={{...}}` (use NativeWind className)190- `StyleSheet.create()` (we use NativeWind exclusively)191- Hardcoded colors (use theme tokens: `bg-primary`, `text-foreground`)192- Pixel values in JSX (use Tailwind: `w-12`, not `width: 48`)193- Web-only APIs (`window`, `document`, `localStorage`)194- Web-only libraries (use RN equivalents)195- Margin to create gaps (use `gap-*` on parent flex container)196- `position: 'absolute'` for layout (use flex, except for overlays)197- Tight coupling: avoid hardcoding navigation routes in components198199## Integration with project conventions200201ALWAYS read `CLAUDE.md` at the project root first to detect:2022031. The stack version (Expo SDK, React Native, React)2042. Style conventions (which Tailwind plugins, custom classes)2053. State management library (Zustand, Jotai, Redux, Context)2064. Data fetching (TanStack Query, SWR, raw fetch)2075. Forms library (React Hook Form, Formik, native)2086. Navigation structure (tabs, drawer, stack patterns)2097. Existing components (don't duplicate, reuse)210211If `CLAUDE.md` is missing, ASK the user before generating code that imposes opinions.212213## Orchestration with Superpowers214215This skill is designed to compose with the Superpowers harness. When invoked:2162171. **Brainstorm phase**: BEFORE generating any code, trigger Superpowers' brainstorming skill to clarify:218 - Which screens are in scope vs out of scope219 - Data sources (mock vs real backend)220 - Navigation flow (where does this screen connect to)221 - Edge cases (loading, error, empty, offline)222 - Platform-specific concerns (iOS vs Android differences)2232242. **Spec phase**: Generate acceptance criteria using Superpowers' writing-spec.2252263. **Plan phase**: Decompose into 2-5min tasks using Superpowers' writing-plans.2272284. **TDD phase**: For non-trivial logic (data fetching, form validation), write tests first using Superpowers' tdd.2292305. **Review phase**: Trigger Superpowers' code-review before declaring done.231232## Output formatting233234- Always provide a brief implementation summary235- List files created/modified with paths236- Note any TODOs or assumptions made237- Suggest next steps (test, refine, add backend wiring)238239## Failure modes to handle240241- **Ambiguous design**: Ask clarifying questions before guessing242- **Missing context**: Detect and request CLAUDE.md or project info243- **Out-of-scope element**: Stub it and add a TODO, don't fabricate behavior244- **Complex animation requested**: Use Reanimated 3, or note as future work245- **Native module needed**: Note that EAS Build will be required (vs Expo Go)