Setting Up a New App
Checklist for turning the MobiWeb shell into a new client app, from an empty branch to store submission. Apps are published under our own accounts: Apple team D33A49X2M4 and our Google Play organization account. For a client that needs its own account, see Publishing Under Another Account.
Work top to bottom. CI and store-review steps have their own pages:
CI Release: environment, signing and service-account access for the pipeline.
Google Play Review and App Store Review: store listing and review phases.
1. Collect from the client
Item | Used for |
|---|---|
App name, at most 30 characters | Store listings, home-screen label |
Web app URL for prod and dev |
|
Icon source: square PNG, at least 1024×1024, no transparency for iOS | Icons and splash |
Splash/brand colors, light and dark | Splash backgrounds |
Privacy policy URL | Both stores (required) |
Support URL and contact email | Both stores |
Demo account for reviewers (login + password, no 2FA) | Both reviews: every app here starts behind a login |
Which native features the web app uses: push, camera, location, Bluetooth printing, NFC, biometrics, OAuth, offline | Permissions, usage texts, store declarations |
Domains for deep links, if any | Associated Domains / App Links |
Decide the identifiers once and never change them: the Android applicationId and the iOS bundle ID. Existing apps use reverse-DNS like ph.ity.<app>. The two may differ, as in com.seriousmd and com.seriousmd.cloud.
2. Create the branches
Keep both branches. Dev is for testers (Firebase App Distribution and TestFlight). Pushing prod starts a store upload. Merge main into both branches to pick up shell updates.
3. Configure the shell
Android
File | Change |
|---|---|
|
|
|
|
| Deep-link |
| From the Firebase project (step 5) |
iOS
File | Change |
|---|---|
|
|
|
|
|
|
| From the Firebase project (step 5) |
Rewrite the permission texts (NS…UsageDescription) for this app. The defaults, such as "…for various purposes", are generic and App Review rejects vague texts (guideline 5.1.1). Say what the feature does in this app, for example: "Bluetooth is used to print delivery receipts on your thermal printer." Remove the keys for features the app doesn't use.
Notification sounds (optional)
Add .wav files to sounds/ on the app branch. See Notification Sounds.
4. Icons and splash screens
Generate them with @capacitor/assets, which is already a dev dependency. Put the sources in assets/ at the repo root:
File | Size | Use |
|---|---|---|
| 1024×1024 | Full icon (iOS and legacy Android) |
| 1024×1024 | Android adaptive icon foreground (keep the logo inside the center 66%) |
| 1024×1024 | Android adaptive icon background (or a solid color) |
| 2732×2732 | Splash, light and dark |
Or use "easy mode" with a single assets/logo.png (and optionally logo-dark.png) plus background colors:
--ios --android skips the PWA icons, which this shell doesn't use. Commit the sources in assets/ together with the generated files under android/app/src/main/res/ and ios/App/App/Assets.xcassets/. iOS icons must not have transparency.
5. Firebase project
Create the project in the Firebase console. Keep Google Analytics on: the app uses Analytics and Crashlytics.
Add the Android app with the
applicationIdand downloadgoogle-services.jsonintoandroid/app/. Add the SHA-1 of the upload key only if the app uses Google sign-in.Add the iOS app with the bundle ID and download
GoogleService-Info.plistintoios/App/App/.APNs key for iOS push: go to Project settings → Cloud Messaging → Apple app configuration and upload an APNs auth key (
.p8) from developer.apple.com → Keys, with Apple Push Notifications enabled, plus its Key ID and Team IDD33A49X2M4. One APNs key works for every app in the team, so reuse it rather than creating one per app.App Distribution (dev builds): grant the CI service account access. See CI Release.
6. Push proxy (fcm-proxy)
The proxy sends through one service account (FCM_CREDENTIALS_FILE) for every Firebase project.
In the new Firebase project's Google Cloud IAM, grant that service account the role Firebase Cloud Messaging API Admin, and make sure the Firebase Cloud Messaging API (v1) is enabled.
In the fcm-proxy repo, add a mapping for the web team's user id to
config/project-mappings.json, withproject_idand, if the app uses notification actions with requests,allowed_action_origins. Restart the proxy.Generate the web team's token:
npx ts-node scripts/generateUuid.ts -t -n(new user id + non-expiring token), and send it to them over a secure channel.
7. Apple Developer and App Store Connect
App IDs: register
<bundle>with Push Notifications, Associated Domains, Communication Notifications and Time Sensitive Notifications, and<bundle>.NotificationServicewith no capabilities. Critical Alerts needs a separate entitlement request to Apple, so only ask for it if the app needs it.App record: App Store Connect → Apps → + → New App: platform iOS, name, primary language, bundle ID, SKU.
Internal TestFlight group with the team, so dev builds reach testers right away.
The listing itself is part of App Store Review.
8. Google Play Console
Create the app: name, default language, App (not game), Free/Paid. Free/Paid can't be changed from free to paid later.
Play App Signing is on by default. Our shared keystore holds the upload key for the app; Google holds the app signing key.
First upload is manual: build a signed AAB once (or download one from a CI run's artifacts) and upload it to the internal testing track. Google rejects API uploads until then.
Invite the CI Play service account for this app. See CI Release.
The listing and policy declarations are part of Google Play Review.
9. CI and the first builds
Follow CI Release → Onboarding an app: create the GitHub environment, add the key to the shared keystore, set the per-app secrets and variables, push dev, and start a manual run.
Smoke-test the dev builds on real devices:
login
push notifications in the foreground, in the background and while killed
every native feature the client named in step 1
deep links, if any
dark mode splash
10. Deep links (if used)
The web team hosts the verification files on each domain:
iOS:
https://<domain>/.well-known/apple-app-site-association, listingD33A49X2M4.<bundle>.Android:
https://<domain>/.well-known/assetlinks.json, with the app signing key SHA-256 from Play Console → App integrity (not the upload key).
Both must be served over HTTPS without redirects.