Rn add screen
Use to add a new screen to an existing Expo + RN app: from a description, a wireframe, or a screenshot, generate the route file in app/ (Expo Router file-based), wire up data fetching via TanStack Query if needed, apply NativeWind classes from the project DESIGN.md tokens, and respect the scaffolded folder layout. Reads .workflow/meta.json with stack.framework="expo-rn" and phase ≥ "scaffolded". Use when dev-flow routes here from scaffolded+expo-rn, or the user says "add a login screen", "create a profile screen from this screenshot", "aggiungi una schermata X". Not for: scaffolding the app (rn-bootstrap), adding backend modules (rn-module-add Wave 3), pure styling changes to an existing screen (rn-styling).From its SKILL.md
npx -y skills add lukedj78/dev-flow --skill rn-add-screenAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
2 things to look at
- 4 stars4 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
- runs commandsInstructs the agent to run 7 commands, including `npx tsc --noEmit` and 6 more.
SKILL.md
9.8 KB, ~2.3k tokens by cl100k_base, as published. Nobody here has run it
rn-add-screen — add a new screen to a scaffolded RN/Expo app
Contract
See references/contracts.md (vendored from dev-flow). Key facts:
- Reads
<project-root>/.workflow/meta.json#stack.framework— must be"expo-rn". - Requires
meta.json#phase ≥ "scaffolded"(runrn-bootstrapfirst). - Reads
DESIGN.mdfrom project root for the design tokens. - Writes ONE new file under
<project-root>/app/...per call — routes only: Expo Router treats every file underapp/as a route, so nothing else may live there. Optional: screen-private components under<project-root>/components/<feature>/(L0, OUTSIDEapp/— see Folder structure rules below), hooks under<project-root>/lib/queries/. - Sets
meta.json#phase = "page_generated"after the first screen, then leaves it (subsequent screens are stillpage_generated). - Always idempotent: re-adding the same route detects the existing file and reports.
When this skill applies
- Phase is
scaffoldedorpage_generated. - The user describes a screen: name, content, behavior. Or provides a screenshot/wireframe to translate.
- Orchestrator routes here from
dev-flow.
Knowledge dependencies (read these first)
rn-fundamentals/SKILL.md— file layout, modern primitives.rn-styling/references/patterns.md— root screen pattern, dark mode, FlashList.rn-expo-router/references/concepts.md— file-based routing rules.rn-expo-router/references/patterns.md— modal vs push, search params, auth gates.rn-data-fetching/references/patterns.md— if the screen fetches data, use the patterns there.rn-components-apis/references/decision-tree.md— which primitive (FlashList vs ScrollView, Pressable, etc.).
Workflow
Step 1 — Verify preconditions
Read .workflow/meta.json. Abort with clear message if:
stack.framework != "expo-rn"→ "Wrong stack."phase < "scaffolded"→ "Run rn-bootstrap first."
Step 2 — Understand the screen
Gather from user (one round-trip max — collect everything at once):
- Route path in Expo Router convention:
/profile/[id]→app/profile/[id].tsx. Group?(auth)/sign-in? Modal? Seereferences/screen-patterns.mdfor the mapping. - Top-level layout: scroll vs FlashList vs form. Modal or full-screen.
- Data: does it need a query? A mutation? Static?
- Navigation in: how does the user reach it (link from another screen, push, modal, deep link)?
- Navigation out: what does it do on success / back?
If a screenshot is provided, infer the above and confirm with the user before generating.
Step 3 — Pick the right scaffold template
See references/screen-patterns.md for canonical templates:
- List screen (FlashList + TanStack Query)
- Detail screen (typed search params + query)
- Form screen (KeyboardAvoidingView + controlled inputs + mutation)
- Modal screen (presentation: "modal", dismiss button)
- Auth-gated screen (inside
(app)/group)
Pick ONE template; do not mix unless the screen is genuinely hybrid.
Step 4 — Generate the file
Write to <project-root>/app/<route>.tsx. The file MUST:
- Use
SafeAreaViewfromreact-native-safe-area-contextat root. - Use NativeWind classes from existing
tailwind.config.jstokens (no magic colors). - Use
Pressable,expo-image,FlashListas appropriate. - If using data, use TanStack Query with a centralized query key (add to
lib/query-keys.tsif it doesn't exist). - If using a form, use controlled state + a
useMutationhook for submit.
Step 5 — Update related files (only if necessary)
- If the screen uses a NEW component, write it under
components/<feature>/(L0, e.g.components/posts/PostCard.tsxfor a/postsroute) — NEVER underapp/<route>/_components/(Expo Router has no private-folder convention; every file underapp/becomes a route — see the Folder structure rules below). Promote tocomponents/shared/<dominio>/(L2) only per the Rule of Three. - If the screen uses a NEW query/mutation, write the hook under
<project-root>/lib/queries/orlib/mutations/. - If the screen is reachable from another screen, add a
<Link>there ONLY IF the user explicitly asks.
Step 6 — Verify
Run:
npx tsc --noEmitfrom project root → must pass.npx expo-router-typegen(if available) so typed routes refresh.
If typing fails, fix and re-verify before reporting done.
Step 7 — Update meta.json + commit
meta.json#phase: if currently"scaffolded", set to"page_generated". Otherwise leave.meta.json#history: append{ skill: "rn-add-screen", ran_at: <iso>, outputs: [<file paths>], phase_before: <prev>, phase_after: <current> }.- If git repo:
git addthe new files +git commit -m "feat(<route>): add <screen-name> screen".
Common anti-patterns (NEVER do)
- ❌ Add layout configuration (
<Tabs.Screen>,<Stack.Screen>) inside the screen file. Layout lives in_layout.tsx. - ❌ Rewrite an existing screen unless the user explicitly says "rewrite".
- ❌ Hardcode colors or spacing in the new file — use Tailwind tokens.
- ❌ Use
Imagefromreact-native—expo-image. - ❌ Use
FlatListfor a long list —FlashList. - ❌ Use
fetch + useEffectfor production data — TanStack Query. - ❌ Touch unrelated files (
tailwind.config.js,app.json, other routes).
Updating meta.json (recommended pattern)
When this skill modifies state (artifact written, phase advanced, history appended), use the canonical script when available:
# Wherever dev-flow is installed (e.g. ~/.claude/skills/dev-flow/), invoke:
python3 .../dev-flow/scripts/update_meta.py <project-root> record-artifact \
--path <relative-path> --produced-by '<this-skill-name>' [--derived-from <p1> <p2> ...]
python3 .../dev-flow/scripts/update_meta.py <project-root> set-phase <new_phase>
python3 .../dev-flow/scripts/update_meta.py <project-root> append-history \
--skill '<this-skill-name>' --inputs '{...}' --outputs '{...}' --phase-after <new_phase>
The script enforces phase monotonicity, normalizes legacy kebab-case aliases (e.g. module-added → module_added), and writes the canonical sha256 + timestamp into meta.json#artifacts. Fall back to direct JSON editing only if the script is not on PATH (and warn the user).
Folder structure rules (canonical — Expo Router hybrid)
Non-negotiable Expo Router constraint: app/ is file-based routing only. Unlike Next.js App Router, Expo Router has no convention for "private", non-routable folders — there is no _-prefix skip rule. Every .tsx/.ts file placed under app/ (aside from a few reserved names like _layout.tsx, +not-found.tsx) is registered as a real route. Putting a component at app/<route>/_components/PostCard.tsx creates a ghost route at that path, not a private folder.
[VERIFY] this against the expo-router version actually installed in the project before relying on it: there's an open upstream feature request for an underscore-skip convention (matching Next.js). If it ships, this rule may relax — until then, assume no private folders exist inside app/.
Given that constraint, the rule for this skill is:
-
app/= routes only. No components, no hooks, no utils — ever. -
Components go OUTSIDE
app/, incomponents/<feature>/<Component>.tsx(kebab-case feature folder named after the screen/domain, e.g.components/posts/PostCard.tsx; complex/compound components get their own subfolder). This is the mobile equivalent of what_components/does on web. -
No
src/prefix: keepapp/,components/,lib/at the project root — consistent withrn-bootstrap's scaffold and the defaultcreate-expo-apptemplates (which don't usesrc/). -
The model (Rule of Three, L0 → L1 → L2 promotion ladder) is unchanged from the general dev-flow contract — only the mobile target paths differ from the web ones documented in
references/contracts.md:Level Web target ( _components/valid)Mobile target (this skill) L0 (page-private) app/<route>/_components/<Component>.tsxcomponents/<feature>/<Component>.tsxL1 (route-group shared) app/(group)/_components/<Component>.tsxcomponents/<feature>/<Component>.tsx(same physical folder as L0 — Expo has no route-group-scoped component folder; the 2nd use is a tolerated duplicate copy inside the second feature's folder)L2 (globally shared) components/shared/<dominio>/<Component>.tsxcomponents/shared/<dominio>/<Component>.tsx(same as web) -
Never
app/<route>/_components/on mobile. A previous revision of this skill pointed there by mistake (copied from the Next.js convention) — that guidance is corrected here. -
Promotion via
promote-component: when the same component pattern appears 3+ times (i.e., copies exist across 3+components/<feature>/folders), call the dedicated skill to lift to L2 with import rewriting. -
components/shared/<dominio>/for L2: domain-based naming only (no "shared", "common", "misc").
Sources
- Course: codewithbeto.dev/rnCourse — modules "Components and APIs" + "Style and Design" (paid, distilled).
- Knowledge skills consumed (see above).
What ships with it: 4 files
40.6 KB alongside SKILL.md
references/
- contracts.md28.9 KB
- decision-tree.md2.9 KB
- .gitkeep0 B
- screen-patterns.md8.7 KB