Rn module add
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-module-addAssembled 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 wire a backend/infra module (auth, db, storage, realtime, push, payments) into a scaffolded Expo + RN app. Reads .workflow/meta.json with stack.framework="expo-rn" and the user-chosen provider for each module (Supabase, Firebase, custom REST, tRPC, RevenueCat). Installs deps, generates the wiring code (lib/auth.ts, lib/supabase.ts, etc.), updates meta.json#stack to record the choice. Always idempotent. Triggers on: "add auth", "wire up db", "set up Supabase", "set up Firebase", "add payments", "add push" (the server-side part), "aggiungi modulo X". Not for: building UI for the module (rn-add-screen does the login screen, etc.), client-side knowledge only (rn-backend, rn-push-notifications), scaffolding (rn-bootstrap).
SKILL.md
10.9 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it
rn-module-add — wire a backend/infra module into a scaffolded RN 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". - Each module updates a specific key in
meta.json#stack:authmodule →meta.json#stack.authdbmodule →meta.json#stack.dbstoragemodule →meta.json#stack.storage(new sub-key)realtimemodule →meta.json#stack.realtime(new sub-key)pushmodule →meta.json#stack.push(new sub-key)paymentsmodule →meta.json#stack.payments
- Sets
meta.json#phase = "module_added"after the first module, then leaves it. - Always idempotent: re-running with same provider detects existing wiring and exits 0.
When this skill applies
- Phase is
scaffoldedorpage_generatedormodule_added. - User asks to add ONE module by name. (To add multiple, run the skill multiple times.)
- Orchestrator routes here from
dev-flow.
Knowledge dependencies (read these first)
rn-fundamentals/SKILL.md— TypeScript strict, modern primitives.rn-backend/SKILL.md— provider-agnostic client-auth architecture.rn-backend/references/<provider>.md— provider-specific wiring (supabase.md / firebase.md / custom-rest.md / trpc.md).rn-push-notifications/references/setup.md— for the push module.rn-publishing-payments/references/revenuecat.md— for the payments module.
Monorepo awareness
Before Step 1: check meta.json#stack.framework.
- If
"expo-rn"(mobile-only project): proceed normally, operate at project root. - If
"monorepo": this skill operates insideapps/mobile/for mobile-specific modules (push, RevenueCat, expo-image-picker), AND insidepackages/api/for modules shared with web (auth, db, storage, realtime). For shared modules, do NOT re-install the SDK ifpackages/api/already has it from a priormodule-add(web side) call. Runmonorepo-sync-typesafterdbandauthare wired. - If anything else: refuse — use
module-add(web stacks) ormonorepo-bootstrap(greenfield monorepo).
For the monorepo case, "install + generate" means: install npm packages into the appropriate workspace (pnpm add --filter @<slug>/mobile for mobile-specific, pnpm add --filter @<slug>/api for shared backend client), and generate code into the right sub-folder. The reference paths below all reference apps/mobile/ instead of project root.
Workflow
Step 1 — Verify preconditions
Read .workflow/meta.json. Abort if stack.framework ∉ {"expo-rn", "monorepo"} or phase < "scaffolded".
If stack.framework == "monorepo", all subsequent file paths are relative to apps/mobile/ (e.g. apps/mobile/lib/auth.ts) or packages/api/src/ (e.g. packages/api/src/auth.ts). Honor the workspace conventions.
Step 2 — Identify the module + provider
Module the user requested: one of auth | db | storage | realtime | push | payments.
If the user didn't specify a provider, default to:
auth,db,storage,realtime→ Supabase (the default inrn-backend/references/decision-tree.md).push→ expo-notifications + Expo push service (the default).payments→ RevenueCat (the default).
If the user specifies a non-default provider, accept it: Firebase / custom-rest / tRPC for backend; Stripe for non-digital payments.
Step 3 — Idempotency check
Read meta.json#stack.<module-key>. If non-null:
- Same provider as requested → "Already wired with X, exiting." Phase stays.
- Different provider → REFUSE unless user passed an explicit "swap" intent. Removing one provider's code + installing another's is a multi-file change that needs explicit user confirmation. Report and stop.
Step 4 — Install deps
Use npx expo install ... -- --legacy-peer-deps for any package that touches native (auth, db SDKs, payments). Use npm install --legacy-peer-deps for JS-only packages.
Provider matrix:
| Module | Supabase | Firebase | Custom REST | tRPC |
|---|---|---|---|---|
| auth | @supabase/supabase-js, react-native-url-polyfill, expo-secure-store | @react-native-firebase/{app,auth}, expo-build-properties | (uses existing lib/api.ts) + expo-secure-store | @trpc/client, @trpc/react-query, superjson |
| db | (same as auth) | @react-native-firebase/firestore | (uses lib/api.ts) | (uses tRPC) |
| storage | (uses @supabase/supabase-js) | @react-native-firebase/storage | expo-file-system + custom upload | (uses tRPC or REST) |
| realtime | (uses @supabase/supabase-js) | (uses @react-native-firebase/firestore) | (WebSocket of your choice) | (tRPC subscriptions) |
| push | expo-notifications, expo-device | (same + @react-native-firebase/messaging) | (same; server-side uses your backend) | (same) |
| payments | react-native-purchases (RevenueCat) | (same) | (same) | (same) |
Step 5 — Generate the wiring
For each (module, provider) combination, write to <project-root>/lib/:
auth/Supabase→lib/supabase.ts(client) +lib/auth.ts(sign-in/out hooks). Seern-backend/references/supabase.md.auth/Firebase→lib/firebase.ts+lib/auth.ts. Seern-backend/references/firebase.md.auth/custom-rest→lib/api.ts(already exists from rn-bootstrap, extend with refresh-on-401) +lib/auth.ts. Seern-backend/references/custom-rest.md.auth/tRPC→lib/trpc.ts+lib/auth.ts. Seern-backend/references/trpc.md.payments/RevenueCat→lib/purchases.ts+hooks/usePro.ts. Seern-publishing-payments/references/revenuecat.md.push/expo-notifications→lib/push.ts+ edits toapp/_layout.tsx(handlers + permissions). Seern-push-notifications/references/patterns.md.
ALWAYS also create store/auth.ts (Zustand) and ensure app/(app)/_layout.tsx redirects when unauthenticated — see rn-backend/references/patterns.md.
Step 6 — Update .env.example + app.json
Per provider, add the env vars to .env.example:
- Supabase:
EXPO_PUBLIC_SUPABASE_URL=,EXPO_PUBLIC_SUPABASE_ANON_KEY= - Firebase: requires
GoogleService-Info.plist+google-services.jsonat root (manual download from Firebase console). - Custom REST:
EXPO_PUBLIC_API_URL= - tRPC:
EXPO_PUBLIC_API_URL= - RevenueCat:
EXPO_PUBLIC_REVENUECAT_IOS_KEY=,EXPO_PUBLIC_REVENUECAT_ANDROID_KEY=
For Firebase or RevenueCat or push notifications, add the relevant app.json config plugin entries (see provider-specific reference).
Step 7 — Verify
Run npx tsc --noEmit. Must pass. If not, fix the wiring before reporting.
For modules with native config plugin changes (Firebase, push), the next build will require a new eas build --profile development. Print a reminder.
Step 8 — Update meta.json + commit
Update meta.json:
stack.<module>: set to the provider name (e.g."supabase","firebase","custom-rest","trpc","revenuecat","stripe","expo-notifications").phase: if currently"scaffolded"or"page_generated", set to"module_added". Otherwise leave.history: append{ skill: "rn-module-add", ran_at: <iso>, inputs: { module, provider }, outputs: [<files>], phase_before, phase_after }.
If git repo: git add the new files + git commit -m "feat(<module>): wire <provider>".
Common anti-patterns (NEVER do)
- ❌ Wire two providers for the same module simultaneously (e.g. Supabase + Firebase auth) — pick one.
- ❌ Skip the
stack.<module>update in meta.json — future re-runs will re-install. - ❌ Hardcode secrets in
lib/*.ts— read fromprocess.env.EXPO_PUBLIC_*. - ❌ Generate wiring without running
tsc --noEmit— broken project shipped to user. - ❌ Add a module that requires a new dev build without printing the "rebuild required" reminder.
- ❌ Use
npm installwithout--legacy-peer-deps— fails on unsupported/older Expo SDK versions due to peer-range mismatches (seern-bootstraplessons-learned).
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)
When wiring a module for RN/Expo, respect the canonical structure (spec: docs/superpowers/specs/2026-06-06-folder-structure-refactor.md):
authmodule: client (supabase.ts/firebase.ts) →lib/. Secure-store wrapper →lib/secure-store.ts. Auth store →store/auth-store.ts. UI (SignInForm, SignUpForm) →app/(auth)/_components/.dbmodule: client wiring co-located with auth (lib/). Query hooks →app/<route>/_components/use<X>.tsinitially, promoted tocomponents/shared/<dominio>/hooks/as they spread.storagemodule: client inlib/storage.ts. Image-picker UI co-located with the screen.realtimemodule: subscriptions wired in screens or instore/if cross-feature.pushmodule:lib/push.ts+ handlers inapp/_layout.tsx.paymentsmodule: client inlib/purchases.ts. Paywall UI inapp/(app)/paywall/_components/. Pro gating hook →hooks/use-pro.ts.
For monorepo (stack.framework="monorepo"): backend client (auth/db/storage/realtime) goes in packages/api/ and is consumed via @<slug>/api/* workspace import.
Sources
- Course: codewithbeto.dev/rnCourse — Backend Basics + Supabase + Publishing/Payments modules (paid).
- Knowledge skills consumed (see above).
What ships with it: 4 files
36.9 KB alongside SKILL.md
references/
- contracts.md28.9 KB
- decision-tree.md3.8 KB
- .gitkeep0 B
- module-matrix.md4.2 KB