Changelog
What shipped, with dates.
Specific enough to be falsifiable. If an entry can't name what changed, it doesn't go in. Build engine work also gets written up on the blog.
Flutter version matrix: old projects build on their own era
- Three toolchains now run side by side: Flutter 3.44.5 (Dart 3.12), 3.24.5 (Dart 3.5, intl 0.19) and 3.19.6 (Dart 3.3, intl 0.18). The builder reads your pubspec sdk constraint, your intl pin, and your android/ template generation, then picks the era your project was written for. A manual override lives in project settings.
- Proof build: Google's archived flutter/gallery — legacy imperative Gradle apply, 2023 lockfile — compiled unchanged into a 117.6MB signed APK on Flutter 3.19.6.
- Projects that pin intl ^0.19 with flutter_localizations no longer die with "version solving failed"; they route to 3.24 and resolve natively.
Upload limits relaxed 5×; failures stopped charging twice
- Source zip limits: single file 200MB → 1GB, total expansion 500MB → 4GB, 20k → 60k files. Zip-bomb protection unchanged. An 81MB Flutter project with a 276MB Windows debug symbol used to be rejected; it builds now.
- Re-submitting the exact upload that just failed with a non-retryable diagnosis is intercepted before charging, with the previous diagnosis shown.
- Failed builds now say "your credit was automatically refunded" on the build page. Refunds always happened; now you can see them.
- Git sources are validated before charging: a wrong branch name gets rejected with the repository's actual default branch suggested.
App Hub, in-dashboard billing, and guided failure playbooks
- Apps is now a first-class view: every app with its latest build, install QR from the last successful artifact, version history, inline rename and delete.
- Billing moved inside the dashboard: credit balance, plan, order history, and a per-build ledger where refunded builds are marked as refunded.
- Failed builds show a playbook instead of a dead end: at most three concrete paths (a copy-paste command, a prefilled wizard link, or docs), derived from the failure class.
Real-repo hardening: five public GitHub projects, six engine fixes
- Built skydoves/pokedex (modern native Kotlin/Compose, 8.25MB signed APK) through the Git pipeline.
- Stale pubspec.lock is no longer a wall: strict resolution falls back to regeneration with a visible log line. Both flutter/gallery and Best-Flutter-UI-Templates ship locks that no longer satisfy their own pubspec.
- Pre-null-safety Dart 2 projects and the removed imperative Gradle apply are now diagnosed by name instead of failing as PROCESS_EXITED.
- Native Android build containers grew from 3GB to 8GB after a real out-of-memory failure.
Toolchain floors: old Flutter projects auto-normalize
- The engine now raises what Flutter 3.44 requires when a project ships less: Gradle wrapper (seeded or raised), AGP, Kotlin, core-library desugaring, and plugin compileSdk floors — each gated so modern projects are untouched.
- shrinkResources conflicts with minifyEnabled=false are fixed automatically instead of failing the build.
- Pre-flight upload validation: a zip with no buildable project is rejected before a credit is charged, with an inventory of what the zip actually contains.
Push campaigns, OTA remote config, instant preview
- Push console: send now or schedule, campaign history with delivered and clicked counts from OneSignal.
- OTA remote config: change splash color, status bar, trusted domains, custom JS, and bottom navigation without rebuilding — apps verify an HMAC signature before applying anything.
- Paste a URL on the homepage and see your app in a live phone frame before signing up. No build consumed.