Your agent installs this paywall in one command.
Then it proves the install works. One verify command checks
files, dependencies, and types, then prints a plain-text receipt —
inno9 paywall: VERIFY PASS — you can read in ten seconds. A
tested part, not a project: a RevenueCat-wired paywall for React Native +
Expo, six TypeScript files landing in src/paywall/, and the
code is yours. Edit one file. Ship.
Get the module — $79 one-time See what's in the box ↓
The verify receipt
Installed by your agent. Proven by your agent. When the install finishes, one more command checks the work and prints a plain-text receipt:
$ node add.mjs paywall --verify
inno9 paywall: VERIFY PASS
files present · deps installed · types clean — review your agent's work in ten seconds, then get back to what makes your app different.
The receipt is machine-readable too: your agent can run the check and read its own result. Plain facts about this module for agents are in Agent facts at the bottom of this page.
The problem → the shift
The problem.
You ship React Native apps by directing an AI agent. Screens, navigation, state — the agent handles those. Then you ask it for subscriptions, and it improvises. Fetching offerings, purchase error states, restore flows, entitlement gating, config validation — improvised from scratch, slightly different in every project, and each one a place where a purchase silently fails or a store review bounces.
Billing is exactly the kind of work agents improvise badly. It's not a differentiator. It's plumbing — and plumbing should be pre-built.
The shift.
Agents assemble software from parts. You don't scaffold a paywall; you
install one. inno9 modules are pre-built parts with agent instructions and
automated verification baked in — your agent runs one command and gets back
to work on what makes your app different.
After install, the code lives in your repo. Not a black-box dependency —
six readable TypeScript files you own, in src/paywall/.
What's in the box
Exactly what the installer copies into src/paywall/ (from the module
manifest — nothing more, nothing less):
| File | What it does |
|---|---|
paywall.config.ts |
The only file you edit. RevenueCat public API key, entitlement + product IDs, tiers, free-trial toggle (1–90 days), every visible string, all colors. |
PaywallScreen.tsx |
Ready-to-render screen: monthly + yearly CTAs with live prices from your RevenueCat offering, restore-purchases button, trial badge, loading and error states. |
hooks/useEntitlement.ts |
useEntitlement(id) → { active, loading, refresh } — gate any feature behind the entitlement. |
lib/revenuecat.ts |
SDK wiring: initPaywall, fetchOfferings, purchase, restorePurchases, plus setPaywallEventHandler for analytics. |
lib/config-schema.ts |
Zod schema. Your config is validated at app startup — mistakes fail fast with a named error, not at store review. |
globals.d.ts |
Ambient types. |
Also in the zip
add.mjs— the installer. Copies the files, installsreact-native-purchases@^10.9.0andzod@^3.25for you.--verifymode — checks files present, dependencies installed,tsc --noEmitclean. Printsinno9 paywall: VERIFY PASSwhen green.- 4 analytics events out of the box —
paywall_view,trial_start,subscribe,restore— route them to any analytics viasetPaywallEventHandler.
Install & verify
The copy step is measured, not estimated: ~2 seconds on a clean
create-expo-app app (warm npm cache) — including dependency install.
# 1. Unzip and install into your app (from the unzipped folder)
node add.mjs paywall --target /path/to/your-app
# 2. Regenerate the native project (react-native-purchases autolinks —
# no app.json plugin registration needed)
cd /path/to/your-app
npx expo prebuild
# 3. Build a dev client (EAS or local) and edit one file:
# src/paywall/paywall.config.ts → API key, entitlement ID, product IDs, copy, colors
# 4. Verify (from your app root)
node /path/to/add.mjs paywall --verify
Heads-up: this module includes native code — it does not run in Expo Go. You need a dev build (
npx expo prebuild+ EAS or local build).
What it integrates with
Only what's actually in the module (no invented integrations):
- RevenueCat — offerings (the Current offering drives what's sold; product IDs in the config are informational), entitlements, purchase + restore, customer info. Requires a RevenueCat account with an app, an entitlement, and monthly/annual products.
- react-native-purchases
^10.9.0— installed for you, integrates via autolinking. No plugin entry inapp.json. Wraps Google Play Billing 8 (RevenueCat SDK 9+ — Google Play requires Billing 8.0.0+ for app updates since Aug 2025). - Expo SDK ≥ 52 — demo app verified on SDK 57.
- Bare React Native CLI — same one-command install (autolinking;
pod installon iOS). - TypeScript + zod
^3.25for startup config validation.
Pricing
US$79 — one-time purchase. Intro price.
- One payment. No subscription.
- Delivered as a zip: module +
add.mjsinstaller. - Single-developer license: unlimited use in your own projects, personal or commercial. No resale or redistribution.
Checkout via Lemon Squeezy — checkout link pending.
FAQ
Does it work in Expo Go?
No. react-native-purchases includes native code, so the module requires a
dev build: npx expo prebuild, then an EAS or local dev client. (This is a
RevenueCat SDK constraint, not a module limitation.)
What do I need before installing?
An Expo SDK ≥ 52 TypeScript app, plus a RevenueCat account with an app
created, an entitlement, and monthly/annual products configured. You'll
paste the public SDK key (appl_… / goog_…) and IDs into
paywall.config.ts. Demo app runs Expo SDK 57 with
react-native-purchases 10.9.
iOS and Android?
Both — the module talks to the stores through RevenueCat's SDK, which supports iOS and Android. Your Current offering in the RevenueCat dashboard determines what's actually sold.
Can I customize the design?
All visible strings and the four theme colors live in paywall.config.ts.
Need a fully custom screen? Import fetchOfferings / purchase /
restorePurchases from src/paywall/lib and build your own — the default
screen uses the same functions. Multiple tiers are supported in the config
(the default screen renders tiers[0]).
What exactly happens after I buy?
You download a zip containing the module and the add.mjs installer. One
command copies six files into src/paywall/ and installs the two
dependencies. The code lives in your repo — you own it.
Free trial support?
Yes — trial.enabled and trial.days (1–90) in the config; the screen
renders the trial badge automatically.
Do I get updates?
Yes — updates within v1.x are free.
What's your refund policy?
14-day money-back guarantee.
Agent facts
Plain facts, one per line, for the AI agent a buyer asks to evaluate this page. No marketing prose — every line below restates a claim this page already makes to humans.
| product | inno9 paywall module — agent-installable paywall for React Native + Expo + TypeScript apps, wired to RevenueCat |
|---|---|
| version | 1.0.0 |
| delivers | 6 TypeScript files copied into src/paywall/ — paywall.config.ts, PaywallScreen.tsx, hooks/useEntitlement.ts, lib/revenuecat.ts, lib/config-schema.ts, globals.d.ts |
| install | node add.mjs paywall --target /path/to/your-app — delivered as a zip (module + add.mjs installer); installs react-native-purchases@^10.9.0 and zod@^3.25 for you |
| verify | node add.mjs paywall --verify — checks files present, dependencies installed, tsc --noEmit clean; prints inno9 paywall: VERIFY PASS when green |
| platforms | React Native universal — Expo SDK ≥ 52 (demo app verified on SDK 57); bare React Native CLI (install verified in CI); iOS and Android via RevenueCat SDK; does not run in Expo Go |
| config | one config file (paywall.config.ts), validated by zod at app startup — mistakes fail fast with a named error |
| price | US$79 one-time, intro price — no subscription |
| license | single developer, unlimited own projects (personal or commercial), no resale or redistribution |
| updates | free within v1.x |
| refund | 14-day money-back guarantee |
| support | [email protected] |
| page | inno9.com/module/paywall |