One codebase, four release targets
SWSH is a social photo-sharing app built around shared albums and events. Most teams shipping to iOS, an iOS App Clip, Android, and the web at once end up maintaining four separate build setups and a release checklist to keep them in sync. SWSH runs all four from a single React Native codebase, and a release rarely needs a person to push it along.
The web build deploys on its own track. Everything else in this story is about the three native targets: a change starts as a local build, runs through an end-to-end test suite on iOS simulators and Android emulators, and lands in both app stores with minimal human involvement. Native releases go out about once a week.
The problem with doing releases by hand
Anyone who has shipped a mobile app knows the chain: cut the builds, handle signing credentials, submit to App Store Connect and Google Play, then confirm nothing regressed on the way out. Done manually, each of those steps is a place a release can quietly break, and the more often a team ships, the more those mistakes cost.
SWSH decided to automate the whole chain rather than patch pieces of it, so human error had nowhere left to enter. Expo's build and submit tooling gave the team that automation out of the box, along with a foundation they could extend with their own tooling.
Local builds at cloud-build scale
For most teams, Expo's cloud builds are the practical default. SWSH is the exception because of volume: full iOS and Android builds on every pull request that touches native code, plus per-environment release builds, add up to roughly 300 builds a month. At that scale, the team moved compilation onto its own self-hosted macOS and Android runners using local EAS builds.
Because eas build behaves the same locally as it does in the cloud, SWSH kept the orchestration, credential handling, and submission steps as they were and moved only the heavy compilation step onto its own hardware. Continuous Native Generation, run through expo prebuild, lets the team regenerate native iOS and Android projects on demand instead of hand-maintaining Xcode and Gradle projects by hand, while still dropping into native code directly when a feature calls for it.
Signing credentials the CI never sees
Signing credentials for both App Store Connect and Google Play live in EAS. The only secret SWSH's CI holds is a single Expo access token. Code signing is normally the part of a release nobody wants sitting in a CI config or a repository, and for SWSH it simply isn't there.
Submitting to both stores without the manual App Store Connect work
EAS Submit pushes each build straight to Google Play and App Store Connect. On Google Play, that covers the whole job. iOS asks for more around the binary: a new App Store version, metadata and release notes, a configured App Clip experience, and a submission for review.
SWSH pairs EAS Submit with an App Store Connect pipeline it built in-house. Once a build is uploaded, that pipeline drives the App Store Connect API directly: it polls for the processed build, creates the App Store version, sets the metadata and "What's New" text, configures the App Clip's default experience down to the card subtitle and card image, and submits the version for review. SWSH built this pipeline itself rather than using EAS Metadata, Expo's declarative metadata tool; most teams won't need to go that far and can use EAS Metadata directly.
Validating releases and shipping JavaScript fixes over the air
Before anything ships, SWSH runs Meridian, its in-house end-to-end testing framework built on Appium and WebDriverIO and driven by Vitest. Meridian exercises the flows that matter most, login, sign-up, upload, and deep linking, across iOS, the App Clip, and Android on simulators and emulators in CI. A release counts as validated only after it's been driven through those flows, not just compiled successfully.
For changes that don't touch native code, EAS Update lets SWSH push JavaScript changes to the app the same day. An EAS Update delivers new JavaScript onto a native build already installed on a user's device, so SWSH runs the Meridian suite against the updated bundle first, to confirm the new code works correctly with the native build it's landing on. After release, EAS Observe tracks production runtime metrics like first render and time-to-interactive, so a startup or rendering regression shows up quickly and the team can push a fix over the air.
What this pipeline changes day to day
Engineers push their changes and move on. The pipeline builds, validates, submits, and monitors each release without further intervention, across roughly 300 builds a month, a native release about once a week, and same-day JavaScript fixes.
"Expo's ecosystem helped us take human error and effort out of the release process, from a local build to a validated release," says Nathan Ahn, CTO of SWSH.
“Expo's ecosystem helped us take human error and effort out of the release process, from a local build to a validated release.” (Nathan Ahn)
Sources
Inside SWSH's automated mobile release pipeline with Expo (2026-08-26)