RORK LABJP
DEADLINE — Four days remain until Google Play requires Android 16 (API level 36). From August 31 it applies to new apps and to updates of existing ones alikeRULES — The submission rule and the visibility rule are separate. An app you have stopped updating still disappears for new users on newer devices if it targets below API 35EXTENSION — An extension keeps you shipping to all users until November 1, but the form lives in Play Console and has to be filed before the deadline passesEXPO — Expo SDK 57 moves React Native from 0.85 to 0.86 while React stays at 19.2, and 0.86 is intended to land without breaking changesHERMES — 57.0.9 updates React Native to 0.86.2 and clears the Hermes V1 memory regression from SDK 56, which shows up in apps importing reanimated or workletsPREBUILD — expo prebuild now clears and regenerates the native android and ios directories by default, so hand-edited native changes vanish unless you audit for them firstDEADLINE — Four days remain until Google Play requires Android 16 (API level 36). From August 31 it applies to new apps and to updates of existing ones alikeRULES — The submission rule and the visibility rule are separate. An app you have stopped updating still disappears for new users on newer devices if it targets below API 35EXTENSION — An extension keeps you shipping to all users until November 1, but the form lives in Play Console and has to be filed before the deadline passesEXPO — Expo SDK 57 moves React Native from 0.85 to 0.86 while React stays at 19.2, and 0.86 is intended to land without breaking changesHERMES — 57.0.9 updates React Native to 0.86.2 and clears the Hermes V1 memory regression from SDK 56, which shows up in apps importing reanimated or workletsPREBUILD — expo prebuild now clears and regenerates the native android and ios directories by default, so hand-edited native changes vanish unless you audit for them first
Articles/Business
Business/2026-04-26Beginner

Rork's Free Plan and Free Trial — What You Actually Keep When the Credits Run Out

What ends a Rork free trial is messages, not days. Export while it is still free, verify it builds outside Rork with a small script, then decide about paying.

Rork544Rork Max232Free PlanFree Trial2Indie Development23Expo186Export

import { Callout } from '@/components/ui/callout';

The thing I got wrong on my first Rork trial was not the message counter. It was that I waited until the credits were gone before trying to move the project out of Rork.

Inside the browser, the prototype ran. On my own machine, it stopped before the build even started. What was missing was not code. It was the identifiers that sit around the code.

So the useful question is not "how many screens did I get for free." It is whether anything survived outside Rork. Answer that, and the upgrade decision answers itself.

What Ends the Trial Is Messages, Not Days

Asking "how many days is the free trial" hides the actual constraint, because days are not what stops you.

Common assumptionWhat actually binds
A clock runs outThe message quota runs out. Untouched, an account can sit there for weeks
Bad generations are freeA round trip costs a message even when the output misses. Vague prompts drain fastest
Upgrading adds leftovers to the new planPlans are monthly. Switching starts a fresh allowance
Running on a real device requires payingCompanion testing is available inside the free tier

Because the unit is one round trip, consumption tracks how often you have to ask again rather than how big the app is. For me, a single-screen app has landed somewhere around 30–80 messages, and something with three or four interacting features around 150–300. Rework, not ambition, is what doubles the number.

Plan names and prices get revised. When money is the deciding factor, read the figure off the Rork pricing page on the day rather than from any article's table. For how the tiers differ in intent, see Rork Pricing Compared: Free vs Pro vs Max.

Measure the Trial by What Runs Outside Rork

Rork has an Export function that pushes the whole React Native + Expo project to GitHub. Running it once while you are still on the free tier is what keeps the trial from evaporating.

An exported project is not automatically a buildable one, though. Settings that Rork did not need while it hosted the preview become mandatory the moment the project is somewhere else — and you normally discover them after npm install, which is the slowest possible moment to find out.

This is the script I run before installing anything. Node built-ins only.

#!/usr/bin/env node
// audit-export.mjs — decide whether an Expo project exported from Rork
// can build outside Rork, before running npm install.
import { readFileSync, existsSync, readdirSync, statSync } from "node:fs";
import { join, extname } from "node:path";
 
const root = process.argv[2] ?? ".";
const read = (p) => JSON.parse(readFileSync(join(root, p), "utf8"));
const problems = [];
const flag = (level, msg, why) => problems.push({ level, msg, why });
 
// 1) app.json (app.config.js needs evaluation and is out of scope here)
if (!existsSync(join(root, "app.json"))) {
  flag("FAIL", "no app.json", "for app.config.js, run expo config --json first");
} else {
  const { expo = {} } = read("app.json");
  if (!expo.ios?.bundleIdentifier) flag("FAIL", "ios.bundleIdentifier missing", "EAS build refuses to start");
  if (!expo.android?.package) flag("FAIL", "android.package missing", "same, on the Android side");
  if (!expo.extra?.eas?.projectId) flag("FAIL", "extra.eas.projectId missing", "eas build / submit cannot resolve the project");
  if (!expo.scheme) flag("WARN", "scheme missing", "deep links and auth callbacks will not come back");
}
 
// 2) reconcile EXPO_PUBLIC_* references against .env
const walk = (dir) =>
  readdirSync(dir).flatMap((name) => {
    if (name === "node_modules" || name.startsWith(".")) return [];
    const p = join(dir, name);
    return statSync(p).isDirectory()
      ? walk(p)
      : [".ts", ".tsx", ".js", ".jsx"].includes(extname(name)) ? [p] : [];
  });
 
const envFile = existsSync(join(root, ".env")) ? readFileSync(join(root, ".env"), "utf8") : "";
const defined = new Set([...envFile.matchAll(/^([A-Z0-9_]+)=/gm)].map((m) => m[1]));
const used = new Map();
for (const file of walk(root)) {
  const src = readFileSync(file, "utf8");
  for (const m of src.matchAll(/process\.env\.(EXPO_PUBLIC_[A-Z0-9_]+)/g)) {
    if (!used.has(m[1])) used.set(m[1], file);
  }
}
for (const [name, file] of used) {
  if (!defined.has(name)) flag("FAIL", `${name} is not defined in .env`, `referenced from ${file}`);
}
 
// 3) report
const fails = problems.filter((p) => p.level === "FAIL").length;
console.log(`export audit: ${root}  (${used.size} EXPO_PUBLIC_* references)`);
for (const p of problems) console.log(`[${p.level}] ${p.msg}\n        -> ${p.why}`);
console.log(problems.length === 0 ? "clean" : `blockers ${fails} / warnings ${problems.length - fails}`);
process.exit(fails > 0 ? 1 : 0);

Run against a freshly exported project — two screens, two environment variables — it reports:

export audit: .  (2 EXPO_PUBLIC_* references)
[FAIL] ios.bundleIdentifier missing
        -> EAS build refuses to start
[FAIL] android.package missing
        -> same, on the Android side
[FAIL] extra.eas.projectId missing
        -> eas build / submit cannot resolve the project
[WARN] scheme missing
        -> deep links and auth callbacks will not come back
[FAIL] EXPO_PUBLIC_ANALYTICS_KEY is not defined in .env
        -> referenced from app/index.tsx
blockers 4 / warnings 1

Add the three keys to app.json, add the missing line to .env, run it again:

export audit: .  (2 EXPO_PUBLIC_* references)
clean

It signals through the exit code, so it drops into CI unchanged. If it returns clean on the last day of your trial, the trial produced an asset rather than a memory.

What Each Finding Actually Costs You

All five are things Rork did not need while it was hosting your project. Knowing what they do makes the findings easy to clear.

FieldWhy it becomes mandatory outside RorkChangeable later?
ios.bundleIdentifierIt is your app's identity in App Store Connect. EAS will not start without itEffectively no, once published
android.packageThe same identity on Google Play. Easier to manage if it matches iOSNo, once published
extra.eas.projectIdThe destination for builds and OTA updates. Local runs work without it; cloud builds do notYes
schemeWhere deep links and auth callbacks return toYes, but existing links break
EXPO_PUBLIC_*Values you set inside Rork are not always part of the exportYes

The right-hand column is the point. The first two are one-way doors, and filling them with a placeholder "for now" is exactly how a throwaway identifier ends up shipped and frozen. If you are still deciding on names, read The names you can change, and the ones you can't before your first release.

Note the prefix on the last row: EXPO_PUBLIC_ variables are embedded in the client bundle. Never put a secret there. Keep placeholders like YOUR_API_KEY in .env and move real credentials to a server or a build-time secret.

Four Ways the Free Tier Drains

Prompts that are vague enough to need a second pass

Quota goes to retries, not to features. Spending the first message on screen layout, data shape, and which APIs are involved is cheaper than three corrective rounds afterwards.

Asking for a large feature in one shot

Big requests are hard to partially fix. Finishing one feature at a time and checking each on a device keeps consumption predictable. For how long free device testing holds up, see How far Rork Companion's free device testing goes.

Hand edits disappearing on the next generation

Once you have exported and started editing by hand, running another generation in Rork can revert those edits. Keeping Manual Fixes Alive Across Rork Regenerations covers where to draw the boundary — worth internalizing while it is still free to get wrong.

Signing up "to have it ready"

Free credits expire. I have let a batch lapse without touching them. Create the account on a day you have actually blocked out time to build.

⚠️
The remaining-quota indicator is not always where you would look for it. Open Settings → Billing early and confirm which plan you are on and how much is left, so an upgrade never happens without you noticing.

Where Paying Starts to Make Sense

By the time the free tier ends, you already hold the evidence.

How the trial endedWhat to do next
Audit is clean and the app feels right on a deviceUpgrade and take it to release. Budget 200–400 messages for a launch including review round trips
Audit is clean but the idea is still fuzzyDo not upgrade yet. Undefined scope burns quota faster than anything else
UI comes out well but a required capability does not close inside RorkCompare continuing in the exported project with Expo CLI as a serious option
Quota is left over because you had no timeDo not upgrade. Time is the constraint, not messages
A second and third project are already plannedA tier that spans projects lowers the per-project cost sharply

What changed things for me was treating the free tier as a place to test fit rather than a place to build. Building can wait until after you pay. Testing fit cannot.

Your Next Step

If you have not signed up, create an account at Rork, generate a single screen, and push it through Export the same day. Then run the script above — the blockers count is your first real result. When it reaches zero, you have everything you need to decide about paying.

The free tier is not there to be used up. It is there to make the decision arrive sooner.

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 $15 for lifetime access
View Membership →

If you found this article helpful, a small tip ($1.50) would mean a lot to us. Your support helps keep this site ad-free and covers server and hosting costs.

Related Articles

Business2026-08-25
I Split Rork and Claude Code by Who Owns the Build Environment
How to decide between Rork and a terminal coding agent using data from your own repository instead of impressions of generated code. Includes a script that counts which layer your maintenance work lands in, and a check that catches native settings silently disappearing on regeneration.
Business2026-08-11
Four Countries, Not the World: Checking Which of My Six Apps the September 30 Deadline Actually Touches
Android developer verification goes live on September 30, 2026 in Brazil, Indonesia, Singapore, and Thailand. Here's how to decide from your own install data whether that date is urgent for you, and what actually blocks indie developers.
Business2026-07-05
When Your AdMob Earnings Suddenly Get Deducted: Preventing Invalid Traffic as a Solo Developer
Invalid traffic deductions in AdMob are unsettling because the cause is rarely obvious. From the perspective of running several apps solo, here is a minimal setup that prevents the most common accidents, plus how to respond when a deduction actually happens.
📚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 →