Skip to content

PATTERN Cited by 1 source

Standalone developer app for RN

Problem

In a brownfield RN integration, every RN contributor has to build the full legacy native app to iterate — even for tiny RN-only changes. This is slow, requires Xcode + Android Studio mastery, and is a major friction barrier for web engineers who are otherwise the natural RN contributor pool.

Pattern

Ship a second, parallel React Native app — the Developer App — alongside the main legacy app. The Developer App:

  • Consumes the same RN Entry Point npm package the production Framework SDK consumes (see patterns/rn-as-consumable-npm-entry-point).
  • Runs a standard RN environment (npx react-native ...).
  • Is not shipped to end users — it's a developer tool.
  • Mocks native contracts for features that depend on the legacy app's state. Any Turbo Module + DI contract (see patterns/turbo-module-plus-di-contract-for-native-interop) has a mock implementation in the Developer App.
  • Ships a custom dev menu on top of RN's default for productivity utilities (JS-bundle switching, observability hooks, feature-flag overrides).

Why this works

  • Fast iteration. The Developer App builds in seconds, not minutes, compared to the full legacy-app build. Code iterations happen at web-app speed.
  • Onboarding unlock. Web engineers joining the mobile effort don't need to master the full legacy-app toolchain. They learn the standard RN environment — which they mostly already know if they have a React background.
  • Bundle testing matrix. The custom dev menu's bundle-switching (released / PR / local) lets a developer QA any RN change in seconds — no reinstall, no full rebuild. Very powerful for code review.
  • Isolates RN from the legacy app for the dev loop. A breaking change in the legacy native code doesn't block RN development.

Example: Zalando's Developer App

Zalando's Mobile Developer App implements this pattern exactly. Its custom dev menu — added on top of RN's default (the one you see when you shake the device) — supports:

  • Switching between released JS bundles (to reproduce a customer-reported bug on the exact version).
  • Switching between PR builds (to QA a colleague's change without a local build).
  • Switching to a local bundle (for active development).
  • Other developer-experience utilities.

For interop-dependent features (e.g. the wishlist-badge system), the Developer App implements the same Swift/Kotlin protocol that the legacy app implements — but with a mocked implementation. This is Zalando's quote: "Our standalone developer app can implement those same interfaces with a mocked version, allowing us to keep using the developer app even when testing features like the wishlist."

Cost

  • Maintenance. The Developer App is a real app that must be kept building and running. Its dev menu features are engineering work.
  • Mock-contract drift. Mocks have to stay compatible with the real Swift/Kotlin protocols; protocol changes must update mocks in sync. Typically handled by the team owning the Turbo Module + DI contract (see patterns/api-contract-first-across-three-languages).

When to reach for this pattern

  • You have a brownfield RN integration (see concepts/brownfield-rn-integration).
  • Your contributor pool skews toward web engineers.
  • Full legacy-app build time is more than ~30–60 seconds.
  • You're shipping RN across more than a handful of screens.

When not to

  • Greenfield RN app — the app itself is the dev app. This pattern is specifically for the brownfield case.

Seen in

Last updated · 507 distilled / 1,218 read