RORK LABJP
BUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the outputNATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other buildersPLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screenCOMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to endPRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that backDEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verifyBUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the outputNATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other buildersPLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screenCOMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to endPRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that backDEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verify
Articles/Dev Tools
Dev Tools/2026-06-22Advanced

Serving Both Plain Rork and Rork Max From One Backend — Designing an API Response Contract That Never Breaks Old Binaries

When plain Rork (React Native / Expo) and Rork Max (native Swift) both call the same Cloudflare Workers backend, the whole design centers on not breaking old binaries you cannot force-update. Wrap responses in an envelope, evolve them additively, absorb client differences with capability flags, and retire old contracts safely — shown in code.

Rork539Rork Max233Cloudflare Workers24API versioningarchitecture12

Premium Article

One morning I "tidied up" a response by renaming a field from title to displayTitle and shipped it. On my latest local build, nothing broke. A few hours later, reports started coming in from devices still running the previous version: their list screens had gone blank. The cause was mundane — the old app reached for title, and the value was no longer there.

The decisive way a mobile backend differs from a web one is this: you cannot swap the client out from under your users. On the web, the next reload hands everyone fresh JS. An app sits behind store review and each user's decision to update. People who never update keep hitting your backend today on a binary from six months ago.

That asymmetry gets heavier the moment you start using plain Rork (cross-platform generation via React Native / Expo) alongside Rork Max (native Swift generation). The same feature receives its response through JavaScript fetch on one side and Swift URLSession on the other. As an indie developer I run several Expo apps behind a single Cloudflare Workers backend, and I am currently revisiting the contract on the assumption that native clients from Max will join it later. This article shares the implementation that lets you grow such a backend without breaking it.

Why decide the "contract" first

A response shape is a contract, not a casual promise. Once it is baked into some binary out in the world, you are bound to it until that binary disappears. So the first thing to settle is not the individual fields but the rule for how they are allowed to change.

I keep only two rules. First, every response is wrapped in an envelope that separates the payload from metadata. Second, field changes are additive only — no deletions, no renames, no quiet shifts in meaning. Holding to just these two erases most of the incidents where an old binary falls over.

The minimal response envelope

The envelope is the outer structure every endpoint shares. The payload itself lives in data, and around it you place the protocol version and any operational metadata the server wants to attach. On the Cloudflare Workers side, a thin helper does the wrapping.

// envelope.ts — every response comes back in this shape
type Envelope<T> = {
  protocol: number;       // version of the envelope itself (rarely bumped)
  data: T;                // payload; grows additively only
  meta: {
    serverTime: string;   // ISO8601
    minSupported: number; // clients below this are nudged to update
    notice?: string;      // optional announcement (maintenance, etc.)
  };
};
 
export function ok<T>(data: T, minSupported = 1): Response {
  const body: Envelope<T> = {
    protocol: 1,
    data,
    meta: { serverTime: new Date().toISOString(), minSupported },
  };
  return Response.json(body);
}
 
export function fail(code: string, message: string, status = 400): Response {
  // errors are wrapped too; clients branch on error, not on the presence of data
  return Response.json(
    { protocol: 1, error: { code, message },
      meta: { serverTime: new Date().toISOString(), minSupported: 1 } },
    { status },
  );
}

The point is that both success and error come back in the same envelope. Clients branch on "is there an error," not on "is there data." Do this, and when you later add something like retryAfter to errors, existing clients simply look past it and ignore it. That they ignore it is the whole point of the envelope.

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
A minimal response envelope that lets one backend serve both a React Native client and a native Swift client without either one breaking the other
The additive-only discipline that keeps old binaries alive when you add fields, plus a decision table of the breaking changes you must never make
An operational procedure for reading your client-version distribution from logs and deciding the threshold at which it is safe to sunset an old contract
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-05-26
Aggregating App Store Connect, RevenueCat, and AdMob into One Morning Digest with Cloudflare Workers — A Six-App Indie Architecture
A practical architecture for indie developers running multiple Rork apps: aggregate App Store Connect API, RevenueCat REST, and AdMob Reporting API in a Cloudflare Workers Cron job and ship a single daily Slack digest each morning.
Dev Tools2026-07-17
The Update That Failed Because a Profile Expired Three Months Ago
Apple signing assets expire quietly and nothing tells you. Here is how to count the days left with the App Store Connect API and put the audit on a weekly Cloudflare Workers cron.
Dev Tools2026-07-17
Killing the Export Compliance Prompt in Rork Builds for Good
Every Rork and Rork Max build lands in App Store Connect with a Missing Compliance warning. Here is how to decide whether you qualify for the exemption, and how to set it once in app.json or Info.plist so the question never returns.
📚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 →