Part 2 of 4: the second phase of the KMP contest starter kit. Firebase, sign in and a AI backend proxy, added only when your app needs them. New here? Part 1 introduces the kit and gets your app running on your machine.
Your app runs on your phone and works offline. That was phase 1’s whole point. So why would you ever connect it to anything?

Three honest reasons:
- Users switch phones. If data lives only on the device, it is lost with the device. Authentication (such as Sign in Google or Sign in Apple) allows people to keep their data synced and linked to their account.
- Some features need a server. If your app calls AI models, the secret API keys (like OpenAI API key, Replicate API key) can’t ship inside the app, where anyone can reverse engineer and use your API key. A small backend proxy holds the keys and makes the API requests.
- You want to know when it breaks. Crash reports tell you about bugs before the one star reviews do.
If none of these apply to your app, skip this phase entirely. A piano map or a notes app can live its whole life offline. Come back when you need it. That’s the phase system working.
Still here? Good. Before touching any service, meet the three files that control all of this.
The three files that hold your configuration
The kit keeps configuration in exactly three places, and once you know them, nothing in this phase is mysterious.
AppConfiguration.kt (in shared/src/commonMain/…/root/) is most important configuration file that your app needs. This is where you set things like:
- CLOUD_FUNCTIONS_URL — the url of your firebase backend, once you deployed one.
- AUTH_SOCIAL_LOGIN_ENABLED — whether the app should show Google and Apple sign-in buttons.
- PREMIUM_FEATURES_ENABLED — whether your app has paid features at all (by default it is false)
- your privacy policy and terms URLs, and your contact email
Nothing secret goes here. It’s committed to git like any other code.
local.properties (in MobileApp/) is the opposite: this is where secrets and build config fields live: API keys, sign in client IDs, subscription keys. The file is gitignored, so it never leaves your machine. You already met it in part 1 when you set sdk.dir. Every other key in it is optional and labeled with the phase that needs it.
gradle.properties contains one important switch: SUBSCRIPTION_PROVIDER. It determines which billing provider the app uses: Adapty or RevenueCat. (See Part 4 for more details; you can ignore this for now.)
And here’s the part that saves you from guessing. The kit ships a script that reads your config and tells you exactly what’s missing for each phase:
./MobileApp/scripts/check_env.sh --phase integrations
# getting-started | integrations | publishing | monetization | growth | all
It prints a checklist: green for set, a warning for missing, and a note for keys you only need if you opted into something. Your AI assistant runs it too, so “what do I still need?” always has a real answer.
Firebase Integration
Firebase is Google’s box of ready backend services: user accounts, crash reports, analytics, push notification. Instead of renting a server and writing backend code, you create a project on their website and your app talks to it. The free tier covers a small app comfortably.
In the kit, setting it up is one guided sequence:
- Create a project at console.firebase.google.com.
- Register your Android app there. It needs your app id and a fingerprint called SHA-1, which can sound scary but is one command:
./gradlew :androidApp:signingReport prints it, you copy it.
- Register your iOS app with your bundle id.
- Download the two config files Firebase gives you: google-services.json goes into MobileApp/androidApp/, GoogleService-Info.plist goes into MobileApp/iosApp/iosApp/.
- In the Authentication section, switch on Anonymous sign in, and optionally Google and Apple Sign In.
That’s it. All the code that uses those files is already in your app.
Notice how this works with the AI assistant: the kit’s phase guide is written for it too, and it knows which steps only you can do. It runs commands, tells you exactly what to click in the console, then stops and waits until you confirm. All you need to tell your AI coding agent that, “I am in integration phase, and integrating firebase, guide me”
Sign in, already built
Why did we switch on anonymous sign in? Because nothing kills a first open like a login wall in mobile apps. Users start anonymously by default, no account, no friction, and can attach a real account later without losing their data. For most first apps, anonymous sign in is all you need, and you’re already done: the app signs users in silently, their data has an identity, done.
Want the “Continue with Google” and “Continue with Apple” buttons too? They already exist in the kit, screens and logic included. Enabling them is just configuration:
- Set AUTH_SOCIAL_LOGIN_ENABLED = true in AppConfiguration.kt.
- Enable Google and Apple as sign in methods in the Firebase console, then re-download the two config files.
- Copy one value (the web client ID) into GOOGLE_WEB_CLIENT_ID in local.properties.
- On iOS: fill google client ID in Info.plist and tick the Sign In with Apple capability in Xcode.
The kit’s enable-auth skill lists every detail you need.
AI features
If your app has no AI features, skip this section. If it does, we need few more things to do.
The problem: calling something like OpenAI, or Replicate needs a secret API key, and a secret inside a client app is not a secret. The proper answer is a small backend that holds this key and forwards requests. Writing one is exactly the kind of chore that kills side projects.
So the kit ships one. The Web/functions folder is a ready backend that runs on Firebase, checks that requests come from a signed in user of your app, and forwards them to OpenAI or Replicate with the key attached. Deploying it:
- Put your provider keys in Google’s Secret Manager (a console page, two clicks per key). They live on Google’s servers, never in your code.
- From the Web/ folder: firebase deploy –only functions.
- Copy the URL it prints into CLOUD_FUNCTIONS_URL in AppConfiguration.kt.
But here’s the shortcut for while you’re still prototyping: you can skip all of that. Put your API key in local.properties (OPENAI_API_KEY or REPLICATE_API_KEY), leave CLOUD_FUNCTIONS_URL blank, and the app calls the provider directly. Since local.properties never leaves your machine, this is fine for testing on your own device. It’s not good for a released app, because the key would ship inside the binary, and the kit’s release checker (you’ll meet it in part 3) will flag exactly that.
The nice part: the app picks the right mode on its own. Empty url, direct calls. URL set, everything routes through your firebase backend. Your app code doesn’t change at all between the two.
What this phase actually costs
An evening, roughly. Most of it is clicking through consoles and copying values, which nobody enjoys, and I won’t pretend otherwise. The guides and the assistant remove the “what do I click now” part.
Two more honest notes. Deploying the backend functions requires Firebase’s Blaze plan, which asks for a credit card; at prototype scale the bill rounds to zero, but the card ask surprises people. And the social sign in setup on iOS involves Xcode and the Apple developer portal.
At the end, run ./scripts/check_env.sh –phase integrations again. When it’s green, run the app. It looks the same. But now a user can sign in, their data can survive a lost phone, crashes report themselves to you, and your AI feature works without shipping secrets.
Next post, the publishing phase: icons, signing, store listings, and getting your first release reviewed. The part everyone fears most, and the part the kit automates.
The kit is free and open source: github.com/KotlinFoundation/kmp-contest-starter-kit, with full documentation at https://kotlinfoundation.org/kmp-contest-starter-kit-documentation/.
Koko, KMP Starter Kit — Part 2: Integrations was originally published in ProAndroidDev on Medium, where people are continuing the conversation by highlighting and responding to this story.