Rn add screen
A filesystem contract (.workflow/meta.json) + 37 agent skills that take a product from idea to production: web (Next.js 16) & mobile (Expo/RN), plus an eve agent engine and Linear/scrum. Runs on Claude Code, Codex, Copilot, Gemini, Cursor.
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.
One thing 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.
What its author says it does
Copied from the file, not written here
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).
SKILL.md
9.8 KB, 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).