How I maintain 100+ apps using expo & EAS
We offer customers of our food ordering platform the ability to get a personalized iOS and Android application. And, to date, we manage over 100 of these applications. In this video, I’ll be detailing how I’m able to create these apps and manage them without breaking a sweat.
Overview
Our applications are pretty basic and are created using Expo. We offer our merchants the ability to customize their app icon & color palette through a very basic form and the data we capture gets put in a Trello list. This way, we’re able to track the progress of every individual app along the way.
We have one single mono repository that holds the configuration files and assets for every single app. The apps all follow a similar template, and using environment variables we’re able to customise them.
Starter kit
I created a starter kit on my Github to show you how you can configure multiple tenants in an Expo setup using environment variables.
If we open the codebase and run yarn start
, we’ll immediately be presented with an error - and that’s because we need to set an environment variable as follows:
TENANT=first-tenant yarn ios
And here we’ll be presented with the application for our first tenant.
If we run:
TENANT=second-tenant yarn ios
We will be presented with the application for the second tenant.
If we open app.config.js
, we’ll see we load a configuration from the configs directory based on the TENANT environment variable.
Looking into the config file for our first tenant, we can see we set things like the bundle identifier, the slug and we define the app icon and splash screen - which lives in first-tenant directory.
The appdefinition object is something we can use inside our views to customize our template.
These config values get filled in the main app.config.js
configuration together with other configuration values that aren’t tenant-specific (eg. version, orientation, etc).
If we open our Index.tsx
file, we can see we reference the appdefinition values to set the title and the color of the text.
Assets are organised in their respective directories and we have a global directory that - as you might’ve guessed - contains global assets like fonts.
Building the app
Before building the app, we need to configure the Expo Application Service (EAS for short), and we can do that by opening up eas.json
and we can add an entry for every tenant. This is called a profile, and within this profile configuration we need to let EAS know what the environment variables are. In our case we need a TENANT environment variable and we set that to the correct value.
If we take a look at the build script, our TENANT environment variable gets set as the profile, and this is needed because EAS runs in the cloud in its own environment.
Diving into app.config.js
again, we’ll see a key called assetBundlePatterns, which prevents us from bundling assets from other tenants. We only include the global assets directory, and the directory of the selected tenant.
When we run EAS build, we’ll be presented with a couple of questions, and EAS will configure a project for us. We can also configure this in the interface, but I prefer this way. We need to fill in the project id in the tenant configuration file, and after we’ve done that, EAS is able to build our tenant app successfully!
Automating as much as possible
EAS has a ‘submit’ feature that is able to submit the apps for you - and it works great! Unfortunately this only works after you’ve submitted the apps in the stores once - and that is still an entirely manual process for now.
After the first manual submission, we’re able to automate updates using EAS submit without issues.
Over the years, we’ve basically automated the entire process of creating an app besides the first submission. I created a CLI that is able to pull all apps from Trello, download the assets and resize them, create the necessary configuration files using stubs and registering the app to Firebase for Android push notifications.
Creating an app is now a process that takes me around 15 minutes - and together with the first manual submission process I can do around 4 apps per hour, which is pretty decent.
Thanks for reading!