9. First Builds, Signing Certificates, and Other Ways to Lose a Weekend
Alright, we've survived sign-ups, store listings, and the age-rating questionnaires. Now comes the first real technical hurdle: actually generating builds that can be uploaded to Apple and Google.
This is the moment you'll either feel like a real app developer… or like you've made terrible life choices.
Step 1: Building the Native Projects
If you're using Ionic + Capacitor (like me), here's the starter command sequence:
npx cap add android
npx cap add ios
npm run build
npx cap copy
npx cap sync
npx cap open ios
npx cap open android
This sets up the native iOS and Android projects, copies your web assets over, and then launches Xcode/Android Studio.
Yes, you need both installed. No, you can't skip.
Step 2: Apple Provisioning Profiles (The Gatekeeping Ritual)
Apple doesn't let you publish anything without a Provisioning Profile and Distribution Certificate.
👉 https://developer.apple.com/account/resources/profiles/list
Process:
Create a new provisioning profile → App Store Connect.
Link it to your App ID (bundle identifier).
Generate a new Distribution Certificate.
Use Keychain Access on your Mac to create a CSR (Certificate Signing Request).
Upload CSR to Apple, download your shiny new cert.
Do this dance twice because Apple apparently hates continuity.
Finally, export the certificate as a .p12 file. Name it something obvious (e.g. CutCompass_Distribution.p12) so future-you knows what it is.
Step 3: Android Keystore (Don't Lose This or You're Toast)
On Android, life is simpler… but with one deadly trap.
In Android Studio: Build > Generate Signed App Bundle or APK
Choose App Bundle (AAB).
Create a new Keystore (.jks file).
Set an alias and password.
⚠️ Write these down. Put them in a password manager. Save them offline. Tattoo them on your arm if you have to.
Because if you lose this keystore, or forget the alias/password, you will never be able to update your app again. Ever. You'd have to publish a new app under a different listing.
Once created, you'll reuse the same keystore for every future build.
Step 4: Auto-Versioning
Don't manually bump version numbers like a caveman. Set it up so your CI/CD pipeline does it automatically.
iOS → Info.plist:
Bundle version string (short) -> 1.1.$(CI_BUILD_NUMBER)
Bundle version -> $(CI_BUILD_NUMBER)
Android → build.gradle:
def sysBuildNumber = System.getenv("CI_BUILD_NUMBER")
versionCode Integer.valueOf(sysBuildNumber)
versionName "1.0." + sysBuildNumber
This way, every build increments automatically and you don't get rejections for duplicate version numbers. This is a Appflow automation, if you're using a different CI/CD, update accordingly.
Step 5: Manual Uploads (First Time Only)
Before automation, you must do one manual upload:
Apple: build
.ipain Xcode, upload via Transporter or App Store Connect.Google: build
.aabin Android Studio, upload via Play Console.
After this, you can connect Appflow (or your CI/CD of choice) to push future builds automatically. But the first one? Manual, painful, unavoidable.
Step 6: CocoaPods (Preview of Pain)
If you're building for iOS, eventually you'll run into CocoaPods install errors.
It's Apple's duct-taped package manager for iOS libraries, built on Ruby gems. Sometimes it installs fine. Sometimes it implodes spectacularly.
I won't go full deep dive here (that deserves its own article), but just know:
If you see "Cocoapods install failed," you're not alone.
Fixing it often requires Fastlane, Bundler, Gemfiles, and a lot of swearing.
We'll cover the whole fix in Article 10: CocoaPods - The Dumpster Fire That Refuses to Die.
Survival Tips
Back up everything:
.p12files, provisioning profiles,.jkskeystore, alias, password. Lose them, and you're done.Automate versioning early: saves rejections and headaches.
Do manual builds once: automation won't save you until you've proven you can ship a build manually.
Prepare for CocoaPods rage: don't panic, just know the fix is ugly but possible.
Coming Up Next
In the next article, we'll dive into CocoaPods properly. Why it exists, why it breaks, and how to duct-tape it back together with Bundler, Gemfiles, and Fastlane.
And then after that, we'll get into CI/CD automation with Appflow - the thing that saves you from doing all of this every single time.
Oh, and don't worry: we're also going to talk about the App Review Hunger Games. Apple vs Google reviewers, arguing endlessly over miscommunications, and why sometimes the real job isn't coding - it's justifying your app to a faceless reviewer until they give in.


