How to handle with 173 copies of an app

Image created by vectorpocket โ€”

Sometimes developers need to create different applications with different branding, for different companies, even if they start from the same code.

Imagine creating a management and booking platform for hospitals. But major hospital brands, (The Mayo Clinic, Singapore General Hospital, for example) want their patients to use their own application.

(Yes, usually this kind of corporations have enough resources to create their own platforms, but this is only an example ๐Ÿคจ)

Creating these applications initially may not be difficult, the real problem is maintaining a solid structure to keep every one of them up to date.

Letโ€™s assume that all these applications have the same requirements, but each one needs different ids, name, colors, images and icons. ๐ŸŽจ

With these 173 emojis you can get used to the idea:
๐Ÿ˜€๐Ÿ˜๐Ÿ˜‚๐Ÿคฃ๐Ÿ˜ƒ๐Ÿ˜„๐Ÿ˜…๐Ÿ˜†๐Ÿ˜‰๐Ÿ˜Š๐Ÿ˜‹๐Ÿ˜Ž๐Ÿ˜๐Ÿ˜˜๐Ÿฅฐ๐Ÿ˜—๐Ÿ˜™๐Ÿ˜š๐Ÿ™‚๐Ÿค—๐Ÿคฉ๐Ÿค”๐Ÿคจ๐Ÿ˜๐Ÿ˜‘๐Ÿ˜ถ๐Ÿ™„๐Ÿ˜๐Ÿ˜ฃ๐Ÿ˜ฅ๐Ÿ˜ฎ๐Ÿค๐Ÿ˜ฏ๐Ÿ˜ช๐Ÿ˜ซ๐Ÿ˜ด๐Ÿ˜Œ๐Ÿ˜›๐Ÿ˜œ๐Ÿ˜๐Ÿคค๐Ÿ˜’๐Ÿ˜“๐Ÿ˜”๐Ÿ˜•๐Ÿ™ƒ๐Ÿค‘๐Ÿ˜ฒโ˜น๏ธ๐Ÿ™๐Ÿ˜–๐Ÿ˜ž๐Ÿ˜Ÿ๐Ÿ˜ค๐Ÿ˜ข๐Ÿ˜ญ๐Ÿ˜ฆ๐Ÿ˜ง๐Ÿ˜จ๐Ÿ˜ฉ ๐Ÿคฏ๐Ÿ˜ฌ๐Ÿ˜ฐ๐Ÿ˜ฑ๐Ÿฅต๐Ÿฅถ๐Ÿ˜ณ๐Ÿคช๐Ÿ˜ต๐Ÿ˜ก๐Ÿ˜ ๐Ÿคฌ๐Ÿ˜ท๐Ÿค’๐Ÿค•๐Ÿคข๐Ÿคฎ๐Ÿคง๐Ÿ˜‡๐Ÿค ๐Ÿคก๐Ÿฅณ๐Ÿฅด๐Ÿฅบ๐Ÿคฅ๐Ÿคซ๐Ÿคญ๐Ÿง๐Ÿค“๐Ÿ˜ˆ ๐Ÿ‘ฟ๐Ÿ‘น๐Ÿ‘บ๐Ÿ’€๐Ÿ‘ป๐Ÿ‘ฝ๐Ÿค–๐Ÿ’ฉ๐Ÿ˜บ๐Ÿ˜ธ๐Ÿ˜น๐Ÿ˜ป๐Ÿ˜ผ๐Ÿ˜ฝ๐Ÿ™€๐Ÿ˜ฟ๐Ÿ˜พ๐Ÿ‘ถ๐Ÿ‘ง๐Ÿง’๐Ÿ‘ฆ๐Ÿ‘ฉ๐Ÿง‘๐Ÿ‘จ๐Ÿ‘ต๐Ÿง“๐Ÿ‘ด๐Ÿ‘ฒ๐Ÿ‘ณโ€โ™€๏ธ๐Ÿ‘ณโ€โ™‚๏ธ ๐Ÿง•๐Ÿง”๐Ÿ‘ฑโ€โ™‚๏ธ๐Ÿ‘ฑโ€โ™€๏ธ๐Ÿ‘จโ€๐Ÿฆฐ๐Ÿ‘ฉโ€๐Ÿฆฐ๐Ÿ‘จโ€๐Ÿฆฑ๐Ÿ‘ฉโ€๐Ÿฆฑ๐Ÿ‘จโ€๐Ÿฆฒ๐Ÿ‘ฉโ€๐Ÿฆฒ๐Ÿ‘จโ€๐Ÿฆณ๐Ÿ‘ฉโ€๐Ÿฆณ๐Ÿฆธโ€โ™€๏ธ๐Ÿฆธโ€โ™‚๏ธ๐Ÿฆนโ€โ™€๏ธ๐Ÿฆนโ€โ™‚๏ธ๐Ÿ‘ฎโ€โ™€๏ธ๐Ÿ‘ฎโ€โ™‚๏ธ๐Ÿ‘ทโ€โ™€๏ธ๐Ÿ‘ทโ€โ™‚๏ธ๐Ÿ’‚โ€โ™€๏ธ๐Ÿ’‚โ€โ™‚๏ธ๐Ÿ•ต๏ธโ€โ™€๏ธ๐Ÿ•ต๏ธโ€โ™‚๏ธ๐Ÿ‘ฉโ€โš•๏ธ๐Ÿ‘จโ€โš•๏ธ๐Ÿ‘ฉโ€๐ŸŒพ๐Ÿ‘จโ€๐ŸŒพ๐Ÿ‘ฉโ€๐Ÿณ๐Ÿ‘จโ€๐Ÿณ ๐Ÿ‘ฉโ€๐ŸŽ“๐Ÿ‘จโ€๐ŸŽ“๐Ÿ‘ฉโ€๐ŸŽค๐Ÿ‘จโ€๐ŸŽค๐Ÿ‘ฉโ€๐Ÿซ๐Ÿ‘จโ€๐Ÿซ๐Ÿ‘ฉโ€๐Ÿญ๐Ÿ‘จโ€๐Ÿญ๐Ÿ‘ฉโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘ฉโ€๐Ÿ’ผ๐Ÿ‘จโ€๐Ÿ’ผ๐Ÿ‘ฉโ€๐Ÿ”ง๐Ÿ‘จโ€๐Ÿ”ง๐Ÿ‘ฉโ€๐Ÿ”ฌ๐Ÿ‘จโ€๐Ÿ”ฌ๐Ÿ‘ฉโ€๐ŸŽจ๐Ÿ‘จโ€๐ŸŽจ๐Ÿ‘ฉโ€๐Ÿš’๐Ÿ‘จโ€๐Ÿš’๐Ÿ‘ฉโ€โœˆ๏ธ๐Ÿ‘จโ€โœˆ๏ธ๐Ÿ‘ฉโ€๐Ÿš€

We must take in mind that it will not be 2 or 3 apps, if everything goes well it will be about 173 applications. 173 in Android and 173 in iOS.

(173 + 1) * 2 repositories

The first idea was the following. The base code is stored in a repository that serves as a submodule for different configuration repositories. Each of these is a project that launches the AppCore Activity / ViewController with the corresponding configuration:

The code is developed on AppCore, which is convenient, because the maintenance of this repository is simple. But every time you need to make an upload of all the applications you need a script like this:

repositories.forEach {
git pull
git pull submodule
fastlane deploy
git commit
git push

This structure has many problems:

  1. Letโ€™s start by creating the repositories. We will need 1 for the AppCore and 173 for each app. Remember that since we are working on both platforms, all this is doubled. (1 + 173) * 2 = 348 repositories. ๐Ÿค“
  2. This approach โ€œrequiresโ€ to have every repository downloaded if we want every update to be released quickly. If you are used to Android or iOS projects you will know that each project, and its compilations, takes up a lot of hard disk space. ๐Ÿ˜ฉ
  3. The process of updating each application is really slow, cause each application requires many git actions. ๐Ÿฅฑ
  4. Each new version of gradle or Xcode usually requires changes in the project, so sometimes you have to make scripts that make changes in all the repositories to adapt them to the new versions. ๐Ÿฅด

2 Repositories with 173 + ~2 branches each

Trying to solve mainly the problems 1 and 2 of the previous system, we started looking for single-repository solutions. We thought that what before was a repository could now be a branch, so we designed something like that:

  • ~2 branches for development; master, develop. And all necessary branches like feature, hotfix, etc.
  • 173 branches with the master content customized for each app.

I mean, the master code is the production code and each of the branches has a master copy with the appropriate configuration for each app. This way, changes in master are propagated in each production upload to each of the app branches. So you need a script like this:

branches.forEach {
git checkout
git merge from master
fastlane deploy
git commit
git push

This also solves point 4 above, since structural changes in the project are automatically propagated to each of the branches.

But this solution is still not perfect:

  1. Problem 3 remains: the update process is still very slow, each branch contains a โ€œproject versionโ€ so, in addition to being a huge repository, each branch contains a lot of information. ๐Ÿฅฑ
  2. If you have to make changes in every app configuration you need to write a script that goes through all the branches and makes the appropriate modifications. ๐Ÿคญ

A repository with a submodule with 173 branches

The previous problems left us with only one option, to find a solution that keeps its base code in only one repository (well, one for android and another for iOS). And the configuration is stored in an external repository. So we set up the following structure:

The repository works like a normal repository, containing an alternative android flavour and iOS scheme. This project is accompanied by a configuration submodule. This submodule contains 173 branches which store only the necessary info like ids, colors, icons, firebase configuration files, etc.

Then, we need a script for every app deploy:

submodule.branches.forEach {
git reset
git submodule checkout branch
merge config with project
fastlane deploy

It goes through the configuration branches and each one of them is integrated in the code to upload the application. By not having to make commits on each branch or pushes, the script is much faster and the repository can be kept clean of branches. ๐Ÿฅ‡

Git Hooks

Git lets you create actions or run scripts when certain git actions happen. Using a post-checkout hook, you can make the script run every time you change the configuration branch. This way you can test it at any time. ๐Ÿค™

Things to keep in mind

Apple App Store Connect

Apple does not allow the publication of these โ€œcopiesโ€ in the same developer account. ๐Ÿคจ You may encounter the following issues:

  • Guideline 4.2.6: The solution to this problem is to create different developer accounts for each brand.
  • Guideline 5.2: You must prove that you have the right to use the images and logos in the application. Attaching this information once should be enough.

Google Play Developer Console

At the time of writing this article, seems there is no problem in keeping all versions in the same developer account. But this may change at any time. ๐Ÿ˜‰

Why 173?

It is a number high enough to understand the dimension of the solution and above all, it is a prime number, composed of prime numbers. ๐Ÿค“

See you in the next post ๐Ÿ‘‹



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store