This episode ships the app to users: building release app bundles for Android and iOS, code signing, provisioning profiles, and app store submission, web deployment and desktop packaging, and responsible release channel and versioning management.

Good code only has value when it reaches users' hands. Episode 14 covers the complete release path: building release artifacts for Android and iOS, code signing and app store submission, web deployment and desktop packaging, and disciplined versioning and release channels.
For Play Store distribution, build an app bundle; for manual sharing, build an APK:
flutter build appbundle --releaseflutter build appbundle --release produces app-release.aab in the build/app/outputs/bundle/release/ folder. The Play Store then generates per-device optimized APKs from that bundle — smaller in size and compliant with store policy.
flutter build apk --release --split-per-abiflutter build apk --release --split-per-abi produces separate APKs per ARM architecture — saving size compared with one universal APK.
For iOS, build an archive, then upload through Xcode:
flutter build ipa --releaseflutter build ipa --release produces an archive ready to upload. Before this succeeds, make sure the iOS project is set up correctly — including signing (below).
Android uses a keystore to sign APKs. Prepare the keystore once, reference it in android/key.properties, and configure it in build.gradle. Never commit the keystore or its passwords to the repository — store them in a secret manager and CI.
iOS requires a provisioning profile and signing certificates managed in your Apple developer account. The typical flow:
Once the artifact is ready, submission happens through App Store Connect — for the App Store or TestFlight. Each platform has review policies; keep access notes for test accounts so reviews don't get held up.
Android offers free sideloading; the Play Store requires a developer account. iOS requires an Apple Developer account to sign and distribute. Factor these costs into the project budget.
Flutter web is built as static files that can be hosted anywhere:
flutter build web --releaseflutter build web --release produces a build/web folder with HTML, JavaScript, and assets ready to upload to static hosting like Nginx, Cloudflare Pages, or Vercel. Configure a fallback to index.html so deep-link routing works.
For desktop, build a bundle per platform:
flutter build linux --releaseflutter build linux --release produces a bundle in build/linux/x64/release/bundle/. For polished cross-platform distribution, consider flutter_distributor or MSIX for Windows.
The app version is defined in pubspec.yaml:
version: 1.2.0+5The format version: 1.2.0+5 means 1.2.0 is the semver version and 5 is the build number, which must increase with every upload. Bump the major for breaking changes, minor for new features, patch for fixes.
Automate versioning with semantic-release or similar: based on commit types (feat, fix, breaking), the version is bumped and a changelog generated automatically. This removes manual version decisions that are often forgotten or inconsistent.
Use channels to control risk:
Separate environment configuration (API URLs, flags) per channel. Don't mix staging endpoints with production just because you forgot to change the configuration.
Key takeaways:
flutter build appbundle for the Play Store; flutter build apk --split-per-abi for manual distribution.flutter build ipa, then signing and submission via App Store Connect.build/web and hosted as a static site.flutter build <platform>.In the next episode 15 we discuss performance optimization — rendering performance and jank reduction, profiling with DevTools, the widget inspector, and timeline, reducing rebuilds and caching widgets, image optimization, and memory usage and app startup time. Your app starts being measured and accelerated.