Case study at Core Tech

Amer Customer: one app, many brands

Rebranding a property-management customer app into a white-label product shipped as three brands — Amer, Alnahdi and RREM — and building the Expo EAS workflow and OTA pipeline that ships it safely.

React NativeExpo 57TypeScriptEAS Workflowsexpo-updates (OTA)JestEN/AR · RTL

The problem

The same customer experience — units, financial reports, collections, requests, invitations — had to be delivered as three separate branded apps, each with their own name, colors, icon, store listing and Firebase project. Forking the app per brand would have multiplied every bug fix and release.

Approach: brand as configuration

  • One codebase (dev) is the source of truth; everything brand-specific lives under brands/<name>/ — palette, gradients, home/login style, app name, bundle id, icons, splash, Firebase files and EAS config.
  • A generator script writes the active brand into eas.json; app.config.ts reads it, so the same source builds a different app per brand.
  • Brand-aware runtime assets (logo, icon) are resolved from a single brand-assets module, so screens never hard-code a brand.
  • Bilingual English/Arabic with full RTL, so each rebrand ships in both languages.

Delivery: Expo EAS workflows

  • Branch-per-brand releases: merging dev into release/<brand> triggers that brand's EAS workflow in its own EAS project.
  • Gates first: a project guard aborts any run that lands in the wrong EAS project; brand tripwires check for config drift and wrong-brand builds; then type-check and Jest must pass.
  • Then Android and iOS builds run in parallel and are submitted to TestFlight and Google Play. Build numbers come from remote versioning, so no manual bumps.
  • Separate development, preview and production profiles with their own update channels; a gates-only workflow validates changes at zero build cost.
devsingle source of truthbrands/<name>/.envpalette · identity · EASrelease/<brand>branch per brandGatesproject guard · brand tripwirestsc + Jestquality checksEAS Build ×2Android + iOSOTA updatemanual · JS-only fixesTestFlight + Playstore submitInstalled appssame runtimeVersion

OTA updates

  • JS-only fixes go straight to installed production builds with expo-updates — no store review wait — through a manual, gated workflow (same checks as a release, since an OTA reaches users instantly).
  • Updates are pinned per brand by runtimeVersion and point at that brand's own EAS project; if a brand has no project id, updates are disabled rather than silently pointing at another brand's.

Screens

Store-listing screens from one brand (English and Arabic).