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 underbrands/<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.tsreads 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
devintorelease/<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,previewandproductionprofiles with their own update channels; a gates-only workflow validates changes at zero build cost.
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
runtimeVersionand 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).