Skip to content
Back to skills

Rn Module Add

BSecurity

Use to wire a backend/infra module (auth, db, storage, realtime, push, payments, cms, analytics, observability) 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, Sanity for cms). 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"...

  • 6 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added October 19, 2026
developmenttypescriptpythongobashreactnextjsgitapibackend

Works with

  • cli
  • api

Security analysis

B84/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 7 files and shows the line behind each finding

Scanned October 19, 2026

npx -y skills add lukedj78/dev-flow --skill rn-module-add --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Rn Module Add?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Rn Module Add
[![Security: B — Skills Directory](https://www.skillsdirectory.com/api/skills/lukedj78-rn-module-add/badge)](https://www.skillsdirectory.com/skills/lukedj78-rn-module-add)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: rn-module-add
description: 'Use to wire a backend/infra module (auth, db, storage, realtime, push, payments, cms, analytics, observability) 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, Sanity for cms). 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), "add a CMS", "set up Sanity", "admin panel for content", "aggiungi un CMS", "misura l''uso dell''app", "crash reporting", "aggiungi sentry", "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), or a Next.js web app (module-add).'
---

# 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`:
  - `auth` module → `meta.json#stack.auth`
  - `db` module → `meta.json#stack.db`
  - `storage` module → `meta.json#stack.storage` (new sub-key)
  - `realtime` module → `meta.json#stack.realtime` (new sub-key)
  - `push` module → `meta.json#stack.push` (new sub-key)
  - `payments` module → `meta.json#stack.payments`
  - `cms` module → `meta.json#stack.cms` (new sub-key — content the app only reads)
  - `analytics` module → `meta.json#stack.analytics` (a list of levels; opt-in) and `stack.analytics_provider` with `advanced` — `references/module-analytics.md`
  - `observability` module → `meta.json#stack.observability` (`["errors"]`) and `stack.observability_provider` — crash and error reporting with `@sentry/react-native`, region by `stack.data_residency`, proven against the local fake ingest — `references/module-observability.md`
- 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 `scaffolded` or `page_generated` or `module_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.
- `references/module-cms-sanity.md` — for the cms module (Sanity Studio as the admin panel, HTTP Query API in the app).

## 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 inside `apps/mobile/` for mobile-specific modules (push, RevenueCat, expo-image-picker), AND inside `packages/api/` for modules shared with web (auth, db, storage, realtime). For shared modules, do NOT re-install the SDK if `packages/api/` already has it from a prior `module-add` (web side) call. Run `monorepo-sync-types` after `db` and `auth` are wired.
- If anything else: refuse — use `module-add` (web stacks) or `monorepo-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 | cms | analytics | observability`. `analytics` is opt-in: never wire it unless the user asked to measure.

If the user didn't specify a provider, default to:
- `auth`, `db`, `storage`, `realtime` → **Supabase** (the default in `rn-backend/references/decision-tree.md`).
- `push` → **expo-notifications + Expo push service** (the default).
- `payments` → **RevenueCat** (the default).
- `cms` → **Sanity** (the hosted Studio is the admin panel; the app reads over the HTTP Query API with no SDK in the bundle — `references/module-cms-sanity.md`). Use it for content a non-developer edits and the app only reads; user-owned data stays in `db`.

If the user specifies a non-default provider, accept it: Firebase / custom-rest / tRPC for backend; Stripe for non-digital payments.

### Step 2b — Where this module's data goes

Read `meta.json#stack.data_residency` (`dev-flow/references/eu-data-sovereignty.md`). If it is `"eu"` or `"eu-sovereign"`, create the provider's project in an EU region and say which (a Supabase project's region and a Firebase project's default resource location are chosen at creation). A provider with no EU option — the push relay, the purchase backend — is **flagged, not refused**: wire it, state the transfer, and record every provider with `python3 <dev-flow>/scripts/data_residency.py add <root> --name … --service … --data … --region … --transfer … --by rn-module-add`. `null` → ask the four questions first (`data_residency.py decide`).

### 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) |
| cms | **Sanity** — nothing in the app (plain `fetch` on the HTTP Query API); `sanity`, `@sanity/vision`, `@sanity/client` live in the separate `cms/` package | — | — | — |

### 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). See `rn-backend/references/supabase.md`.
- `auth/Firebase` → `lib/firebase.ts` + `lib/auth.ts`. See `rn-backend/references/firebase.md`.
- `auth/custom-rest` → `lib/api.ts` (already exists from rn-bootstrap, extend with refresh-on-401) + `lib/auth.ts`. See `rn-backend/references/custom-rest.md`.
- `auth/tRPC` → `lib/trpc.ts` + `lib/auth.ts`. See `rn-backend/references/trpc.md`.
- `payments/RevenueCat` → `lib/purchases.ts` + `hooks/usePro.ts`. See `rn-publishing-payments/references/revenuecat.md`.
- `push/expo-notifications` → `lib/push.ts` + edits to `app/_layout.tsx` (handlers + permissions). See `rn-push-notifications/references/patterns.md`.
- `cms/Sanity` → `cms/` Studio package (config, schema types from the PRD domain, seed script, README) + `lib/cms.ts` (`cmsFetch` over the HTTP Query API) + query hooks under `lib/queries/` + `metro.config.js` blockList for `cms/`. See `references/module-cms-sanity.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.json` at 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=`
- Sanity (cms): `EXPO_PUBLIC_SANITY_PROJECT_ID=`, `EXPO_PUBLIC_SANITY_DATASET=production` — **no token**: `EXPO_PUBLIC_*` ships in the bundle, so the catalogue dataset stays public. The Editor token for seeding lives in `cms/.env` only.

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"`, `"sanity"`).
- `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.
- ❌ Hand-roll a UI primitive in the screens a module adds (sign-in, paywall, settings) (golden rule 3, `references/contracts.md` §Golden rules). **Before writing a component, search** React Native / Expo core components (`Pressable`, `Modal`, `TextInput`, `Switch`, `expo-image`, `FlashList`…), whatever component stack `meta.json#stack` declares, and `components/shared/` — if one covers the pattern, use it; if two together do, compose them. Never add a second component library, never fork a declared component's behaviour; a truly new primitive needs a recorded exception (`meta.json#stack_config.primitive_exceptions`).
- ❌ Skip the `stack.<module>` update in meta.json — future re-runs will re-install.
- ❌ Hardcode secrets in `lib/*.ts` — read from `process.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 install` without `--legacy-peer-deps` — fails on unsupported/older Expo SDK versions due to peer-range mismatches (see `rn-bootstrap` lessons-learned).

## Updating meta.json (recommended pattern)

When this skill modifies state (artifact written, phase advanced, history appended), use the canonical script when available:

```bash
# 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`):

- **`auth` module**: 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/`.
- **`db` module**: client wiring co-located with auth (`lib/`). Query hooks → `app/<route>/_components/use<X>.ts` initially, promoted to `components/shared/<dominio>/hooks/` as they spread.
- **`storage` module**: client in `lib/storage.ts`. Image-picker UI co-located with the screen.
- **`realtime` module**: subscriptions wired in screens or in `store/` if cross-feature.
- **`push` module**: `lib/push.ts` + handlers in `app/_layout.tsx`.
- **`payments` module**: client in `lib/purchases.ts`. Paywall UI in `app/(app)/paywall/_components/`. Pro gating hook → `hooks/use-pro.ts`.
- **`cms` module**: the Studio is its own package in `cms/` (own `package.json`, excluded from Metro and from the app's `tsconfig`); read client in `lib/cms.ts`; GROQ query hooks in `lib/queries/`. Never an admin screen in `app/` for content — that is the Studio.

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).

Files in this skill

  • SKILL.md14.4 KB
  • references/contracts.md80.5 KB
  • references/decision-tree.md3.8 KB
  • references/module-analytics.md8.8 KB
  • references/module-cms-sanity.md15 KB
  • references/module-matrix.md6 KB
  • references/module-observability.md4.3 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.