RORK LABJP
MAX — Rork Max bills itself as the first web Swift app builder, publishing to the App Store in two clicks with no Xcode requiredAPPLE — It generates native Swift apps for iPhone, iPad, Apple Watch, Apple TV, and Vision ProEXPO — The standard tier builds native iOS and Android apps on React Native (Expo) from a plain-English descriptionFUNDING — Rork raised $2.8M from a16z, strengthening its position in AI no-code mobile developmentPRICE — Free to start, with paid plans from $25/month — an accessible entry point for solo developersWWDC — WWDC 2026 pushes Apple Intelligence forward, raising the value of native features and widening AI integration options for no-code appsMAX — Rork Max bills itself as the first web Swift app builder, publishing to the App Store in two clicks with no Xcode requiredAPPLE — It generates native Swift apps for iPhone, iPad, Apple Watch, Apple TV, and Vision ProEXPO — The standard tier builds native iOS and Android apps on React Native (Expo) from a plain-English descriptionFUNDING — Rork raised $2.8M from a16z, strengthening its position in AI no-code mobile developmentPRICE — Free to start, with paid plans from $25/month — an accessible entry point for solo developersWWDC — WWDC 2026 pushes Apple Intelligence forward, raising the value of native features and widening AI integration options for no-code apps
Articles/Dev Tools
Dev Tools/2026-06-14Advanced

Building Rork Subscriptions Around RevenueCat Entitlements — Access Checks, Offering-Driven Paywalls, and Restore

Implementation notes for adding subscriptions to a Rork (Expo) app with RevenueCat. Make Entitlements the single source of truth for access, drive the paywall from Offerings so you can change prices remotely, wire up restore and the customer-info listener, and avoid the sandbox traps — all with working code.

Rork395RevenueCat21Subscriptions10Expo68Monetization29

Premium Article

When you finally have a working app out of Rork and decide to add payments, the first place most people stall isn't the SDK call — it's the question of where, and based on what, do I decide whether someone is a paying member? Do you check the purchased product ID, store a receipt, write a "purchased" flag on the device? Leave that vague and you'll pay for it later: change a price and the check breaks, or a user who switched phones writes in saying "I paid and it's gone."

The real value of dropping in RevenueCat isn't that "subscriptions take a few lines." It's that you can anchor your access check to an Entitlement rather than to product IDs. This article assumes the Expo (React Native) app that regular Rork generates, and walks through an Entitlement-centered design, an Offering-driven paywall, restore, and the sandbox issues I actually hit — with working code. I'll spend less time on the product-setup screens and more on the structure that pays off down the road.

Why "check the product ID" falls apart later

The common first move is to use the purchased product ID (com.example.app.pro_monthly) directly as the access check. It works — until operations begin. Start selling monthly and annual and now you if against both. Raise prices by cutting a new product ID and you add code to keep grandfathered subscribers. Name your iOS and Android product IDs differently and the platform branching doubles. Before long, the function that answers "may I unlock Pro?" is a growing list of product-ID comparisons.

RevenueCat's Entitlement abstracts that list away. In the dashboard you create one Entitlement — say pro — and attach "which products grant pro" to it. The app never knows a single product ID; it only asks whether pro is active. Add products or change prices and the attachment is dashboard work; your app code doesn't move. Whether you nail this down first determines, in my experience, how much the next six months of maintenance costs.

Pin the access axis to exactly one thing. "Is the Entitlement active" is the only truth for access; any device flag or product ID is at most a hint. Build the whole codebase on that premise.

Write the service layer around the Entitlement

Install the SDK first. Because billing pulls in native modules, it does not run in Expo Go — you need a development build (expo-dev-client) or EAS Build. Testing in Expo Go and wondering why the purchase call never fires is the very first trap, so I'm putting it up front.

npx expo install react-native-purchases
# Make a dev build — billing does not work in Expo Go
npx expo prebuild
eas build --profile development --platform ios

The package is react-native-purchases (you'll see an older scoped spelling around; this is the current one). Write the service layer as a thin window that returns Entitlement state, so the rest of the app never thinks about "products" or "receipts."

// src/services/purchases.ts
import Purchases, {
  CustomerInfo,
  LOG_LEVEL,
} from 'react-native-purchases';
import { Platform } from 'react-native';
 
// Decide on ONE entitlement for gating. No product IDs appear here.
export const ENTITLEMENT_ID = 'pro';
 
const API_KEY = Platform.select({
  ios: process.env.EXPO_PUBLIC_RC_IOS_KEY ?? '',
  android: process.env.EXPO_PUBLIC_RC_ANDROID_KEY ?? '',
}) as string;
 
export async function configurePurchases() {
  if (__DEV__) Purchases.setLogLevel(LOG_LEVEL.DEBUG);
  // Without an appUserID, RevenueCat assigns an anonymous one.
  // If you have your own auth, the right move is logIn() AFTER sign-in,
  // not passing an ID to configure() — that double-runs the anon→known alias.
  await Purchases.configure({ apiKey: API_KEY });
}
 
// The single access check. Nothing else decides premium access.
export function isPro(info: CustomerInfo): boolean {
  return info.entitlements.active[ENTITLEMENT_ID] !== undefined;
}
 
export async function getCustomerInfo(): Promise<CustomerInfo> {
  return Purchases.getCustomerInfo();
}

The key is that isPro takes a CustomerInfo and holds no internal state — it's a pure function. If your check depends on some global variable, the value drifts between "just purchased," "just restored," and "just launched." Always phrase it as "ask, passing the freshest CustomerInfo I have," and it lines up cleanly with the listener below.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
Use a single Entitlement as the only access check so price changes and platform differences don't break gating
An Offering-driven paywall that reads packages remotely instead of hardcoding prices
The restore flow, the CustomerInfo listener, and the sandbox issues that actually cost you time
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Dev Tools2026-06-13
You Only Get to Ask Once — Implementing a Notification Soft-Ask in Your Rork App to Lift Opt-In
On iOS, once a user denies the notification prompt you can never show it again. In a Rork (Expo) app, instead of firing the system prompt on launch, we add our own soft-ask screen and only request permission once the value has landed. Built with expo-notifications, covering Android 13 POST_NOTIFICATIONS, a recovery path after denial, and opt-in measurement.
Dev Tools2026-06-13
Keeping a Rork-Built Expo App Ready for Kotlin Migration — Design Notes After Android Studio's Migration Agent Announcement
Android Studio's new agent can migrate React Native apps to native Kotlin. Here is how I restructured a Rork-built Expo app to stay migration-ready: a native dependency audit script, a portable core layer pattern, and a readiness checklist.
Dev Tools2026-06-13
When Hiragana Doesn't Match Katakana — Japanese-Aware In-App Search for Rork Apps
A hiragana query silently missing katakana titles is a UX failure users never report. How I fixed Japanese search in my wallpaper app with NFKC normalization, kana folding, and precomputed search keys.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →