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.
Offer
Builder includes 20 credits a month
- Builder now includes 20 credits a month, or 240 a year on the yearly plan, as many credits as its up to 20 Android source compiles a month. Before, a Builder month included 10, so it covered 10 compiles. Existing Builder subscriptions get the new amount, 20 a month or 240 a year, from their next renewal; nothing else about the plan or its price changes.
Engine
Android builds from your own source check Google Play's 16 KB rule
- From February 1, 2027, Google Play will not release updates of apps that target Android 15 or higher unless they support 16 KB memory pages. Every Android build from your own Flutter or native source now checks the file you get, the AAB of a Google Play build or the APK of a direct one: each 64-bit native library must be aligned for 16 KB pages, and an AAB that keeps them uncompressed must ask Google Play to place them at 16 KB offsets. The build log names the libraries that fail (the first five, then a count) and the fix: update the plugin or SDK that ships one, build your own C or C++ code with NDK r28 or later, or, for the bundle, move to Android Gradle Plugin 8.5.1 or later or compress the libraries. The check never stops a build.
- Why the AAB part matters: we built fresh Flutter 3.24.5 and 3.19.6 apps, whose new projects use Android Gradle Plugin 8.1.0 and 7.3.0. Their APKs passed Google's zipalign check, but in the APKs bundletool 1.18.3 built from their AABs for an Android 15 phone, the libraries sat at 4 KB-aligned offsets, not 16 KB. Flutter never raises a project's plugin version, and Flutter 3.35 to 3.41 still build with plugins below 8.5.1, so the Flutter 16 KB article now covers how to check a bundle and fix it.
Fix
Website apps keep their status bar colour on Android 15 and later
- Android 15 ignores the status bar colour that apps set once they target API 35 or later, as every website app built here does (API 35 for direct downloads, API 36 for Google Play), and the navigation bar colour too except over 3-button navigation. The bars showed white instead, and with a dark launch colour the status bar icons turned white on white. The bands under the bars now carry the launch colour, the navigation bar icons get the same contrast, and the rest of the screen stays white, so the gap above an opening keyboard does not flash the colour.
- Turned sideways, a phone puts its navigation bar or camera cutout at the side. The page is now padded on every side, display cutouts included, not only above and below, and the tab bar no longer adds the same space again (it grew by the keyboard's height while typing). Rebuild an app to get these; paid website rebuilds cost no credits.
Fix
Uploading a signing keystore no longer fails when the key password is left blank
- The New app wizard marks the key password optional, but a blank field was refused as an invalid upload. A blank key password now means the keystore password, which a PKCS12 keystore requires anyway, and the keystore is still checked before it is saved, so a wrong password is named instead of stored.
Fix
Git sources get the project-layout and code2native.json checks before any credit is charged
- A GitHub repository now gets the project-layout and code2native.json checks a ZIP upload gets. React Native, Expo, Capacitor and Ionic are not yet compiled here, so such a repository was charged and then stopped, and so was one with an invalid code2native.json or a Gradle project beside other folders. These are now refused first, with the same explanation. The check reads only the repository's file list and a few small files at the commit being built.
Fix
A React Native or Capacitor android/ folder zipped on its own is refused before any credit is charged
- The android/ folder of a React Native, Expo or Capacitor project builds from ../node_modules, which a ZIP of that folder cannot include, so Gradle stopped after the credit was charged. The upload check now refuses it first, with the same explanation as a whole project of that framework and, in the New app wizard, its one-click waitlist.
Fix
Flutter uploads for Google Play are checked against Play's target API before any credit is charged
- For some projects the builder uses Flutter 3.24.5 or 3.19.6: an old intl, carousel_slider or syncfusion_flutter_pdfviewer pin, a pre-3.16 android/ folder, or an sdk range that excludes current Dart. Apps built with those versions target API 34 and 33, so Play Console rejected the AAB after the build was charged. Such a Google Play build from an uploaded ZIP is now refused first, naming every change that lets current Flutter build the project. A Direct download (APK) of the same project still builds.
- A Flutter project whose android/app/build.gradle sets a targetSdk below Play's minimum is refused the same way, as native projects already were.
Fix
Android projects zipped on a Mac or with Windows PowerShell now build
- Finder's Compress often adds a hidden __MACOSX folder next to the folder you zip. The build counted it as a second folder, could not tell which one was the project, and a native Android project stopped with "No gradlew found" after the credit was charged. The build now skips __MACOSX.
- Compress-Archive in Windows PowerShell 5.1, the version built into Windows, writes paths with backslashes. The build unpacked them as single files instead of folders and stopped the same way. Paths are now unpacked as folders, the way the upload check already read them.
- A ZIP made with tar -a -cf app.zip . starts with a ./ entry for the folder itself. The build took it for an unsafe path and stopped after the charge; it is now skipped.
Fix
An unusable code2native.json is refused before any credit is charged
- A code2native.json the build cannot use (not valid JSON, a command for an unknown platform, an empty command, or an artifacts folder outside the project) stopped the build after the credit was charged. The upload check now applies the same rules and refuses the ZIP first, with the same message.
Fix
React Native, Expo, Capacitor and Ionic uploads are refused before any credit is charged
- A ZIP of one of these projects, zipped at its root, has an android/ folder beside its other folders. The upload check accepted it and the build was charged, then stopped: React Native, Expo, Capacitor and Ionic are not yet compiled here, and that stop was not refunded. The upload check now refuses such a ZIP before any credit is charged, with the same explanation. In the New app wizard, the refusal also offers that framework's one-click waitlist and a Website build instead.
- A Gradle project that sits in one folder beside other folders is refused the same way, naming those folders, with the fix: make a ZIP that contains only the project folder.
Platform
Build files: a published retention schedule
- Free builds, the newest one included, are deleted 30 days after they finish.
- While a paid plan or an App license is active, the newest successful build of each app on each platform has no deletion date; Google Play (AAB) and direct-install (APK) builds count separately. Replaced builds are deleted 90 days later on Builder and App-licensed apps, 150 days later on Pro and Agency.
- When a plan ends, its files are kept at least 30 more days.
- Each app's newest build when this schedule took effect, and every Agency source archive, is kept for at least 30 days after this schedule took effect, even if you rebuild before then. Older builds keep their normal date, which can be sooner; each build page shows it.
- Each build page and build-complete email says how long that build's files are kept, in UTC. The dashboard shows a notice about this change for at least 30 days.
- Deleting a build or a project now also deletes its app icons and the uploaded source ZIPs and images that no other project or build uses.
Fix
Android developer verification: we were wrong about directly installed APKs
- Our pricing, docs and install notes said that from September 30, 2026, certified Android devices in Brazil, Indonesia, Singapore and Thailand would refuse APKs shared directly, Preview APKs included. Google's developer verification FAQ says the September 30 rule covers installs from Google Play and six other stores in those countries, and that directly installed APKs are not affected until Google extends verification, which it plans for 2027. The notes now say that.
- Website apps signed with our shared platform key still cannot be registered by their owner. The developer verification page in the docs explains which key signs your app.
Fix
Android apps: Back after reopening, while offline and on Shopify's home
- In Android apps built from a website, on Android 12 and later: after people left the app with Back and opened it again, Back on any page closed the app instead of going to the previous page. It now goes back a page, and leaves the app only from the first one.
- When the site could not be reached, Back returned to the page that had just failed, which showed the offline page again, so Back never left the app. It now goes to the page before that one, or leaves the app. Try again on the offline page, and a connection coming back, now load the site again; they used to reload only the offline page.
- In Shopify apps, Back on the native product list leaves the app. Once other pages had been opened, it used to step back through them behind the list, so Back seemed to do nothing until they ran out.
- Build your Android app again to get these. Installed copies keep the old behavior until people install the new build.
Fix
Device-test commands in code2native.json are explained before they run
- A ZIP upload whose code2native.json runs Android device tests (connectedDebugAndroidTest, connectedCheck and the like) is refused before any credit is charged. Those tasks install and run tests on a connected phone or emulator, which cloud builds do not have, and they make no release APK or AAB.
- A Git build with such a command stops before compiling, with the same explanation; its credit is not returned. The fix: set commands.ANDROID to "./gradlew bundleRelease assembleRelease", and run device tests in Android Studio or on a device farm such as Firebase Test Lab.
- Flutter projects are not refused, for Google Play or direct download: they build with flutter build, which never runs the configured command.
Fix
Android apps: location on Android 12+, push permission on Android 13+
- Android apps with location turned on never showed the location prompt on Android 12 and later: the app asked for precise location without approximate, and Android ignores that request. Apps built after September 28, 2026 ask for both; people pick precise or approximate, and either works for your site's geolocation and Code2Native.getCurrentLocation().
- Apps with push set up ask for notification permission once, the first time they open on Android 13 and later. Before, a new install on Android 13 and later received no push unless your site called Code2Native.requestPushPermission().
- Startup permission prompts no longer come back when the theme changes, the app enters split screen or a foldable unfolds.
- Build your Android app again to get these. Installed copies keep the old behavior until people install the new build.
Dashboard
Welcome says what a credit builds; public pages pass automated accessibility checks
- A new account's Welcome says what one credit builds (a marked Android APK of your website). A Free account with no credit left is offered plans instead of a build that would be refused.
- Public pages and the blog pass automated accessibility checks (axe) at phone and desktop widths: one main landmark, headings in order, tables you can scroll with the keyboard, yes/no table cells with text.
- Code blocks on public pages wrap instead of scrolling sideways, and status colours in the blog's terminal samples are readable on their dark background.
Fix
Card failures explained, plan switches cleaned up, build lists that update
- While Stripe is retrying a failed card payment, every dashboard page says so, with both ways forward: update the card or cancel.
- On a paid plan, Billing lists what the plan includes and, on Builder, how many Android source compiles are left this month.
- A USDT plan purchase that would pay for nothing (a card subscription still renewing or retrying) is refused before you pay.
- Switching plan or billing interval closes the earlier unpaid card checkout, so it can no longer be paid alongside the new one.
- Builds, the Apps list and each app's page update on their own while builds run.
- Within the same plan priority, queued builds other than iOS and macOS take turns between accounts: one account's batch no longer fills every build slot.
- Google Play builds of native Android projects uploaded as a ZIP, whose app sets a literal targetSdk below Play's minimum, are refused before they are charged.
- For cloud-signed apps, Signing keys lists every iOS provisioning profile that expires within 45 days, has expired or failed its check, each with its own Replace link.
Engine
Prices before rebuilds, searchable builds, failures with copyable fixes
- Rebuild dialogs show the credit cost and your balance before you confirm, and charge that price.
- Search builds by app name, Android package name, iOS bundle ID or version.
- Each iOS build of an app gets a new build number (App Store Connect rejects a repeated one).
- Update app offers only the app's own source kind; picking another used to create a second app without telling you. Start a new app for another source.
- iOS builds email you when they finish, as Android builds do.
- Outages and timeouts at public package hosts (Google, Maven Central, npm, pub.dev, GitHub) now count as ours: any credit is returned and they do not count toward Free's 3 builds per 24 hours.
- Failure cards give copyable fixes for kotlin-stdlib duplicate classes, a Gradle wrapper older than the declared Android Gradle Plugin, AAR metadata requirements and Flutter version mismatches.
- Push is offered for Android builds of website and Shopify apps, and every push screen says iOS builds do not include it.
Fix
Paid builds without the watermark, queue and build progress
- Apps built on an active Builder or Pro plan, or with an App license, ship without the Preview watermark, with no setting to find.
- A renewal no longer drops an account to Free while the payment is confirmed: access runs to the billing period's end plus 3 days.
- The build page shows your place in the queue and when the build should start, then how long it has been running and, once there are enough earlier builds to compare, how long builds like it usually take.
- A new account's first Build this Preview works again (it had been refused since August 14).
- The first Android build of a website or Shopify app with an App license, or first built for iOS, is no longer refused; it builds a direct-download APK.
Offer
One chrome, one free quota, no theater
- Public nav and footer are one component. The primary button is cobalt on every marketing page.
- The Free quota became the same on every page (it has since been replaced by one marked Preview APK). Most popular is gone. Homepage no longer pins a fake Capacitor / SDK 36 toolchain.
- iOS page leads with our Mac and your certificate, not No Mac required.
- Homepage preview is Android, Source, Windows, and iOS on the real PhoneFrame (Pixel 8 / iPhone) plus a Windows 11 window. The 251s receipt and Build this are gone.
- The Free signup credit is a Preview URL wrap, not a ZIP compile. ZIP compiles required Pro at the time (Builder covers them now). Stripe Pro checkout uses the square mark, not the broken wide banner.
Offer
Preview / Release, and refunds by responsibility
- Public offer is three cards: Free Preview (marked Android wrap), Single App (Release of this website), Pro (keep shipping, including IPA).
- Starter $29 and Agency stay archived. They are not on the homepage.
- Source ZIP is a paid lane. Free accounts cannot open it.
- Refunds follow responsibility: platform and network faults return the credit; a compile that would fail on your laptop does not; cancel does not refund.
Platform
v1.0: first tagged release
- iOS cloud signing launched on the Agency plan using your Apple certificate and provisioning profile. Signing does not guarantee installation or store approval; the profile and export method determine distribution. See the current pricing and iOS setup pages for present-day access.
- At the time, pricing was Starter $29, Pro $99 (iOS builds included) and Agency $199 monthly, and Single App $149 one-time with lifetime updates ($79 regional); USDT accepted at the same USD price. Superseded. Starter and Agency are archived.
- The whole site moved to the Modernist design system, and every docs page was audited line-by-line against actual product behavior — signing tiers, managed Android upload keys, container isolation, and the native-bridge API reference now say exactly what the platform does.
- The nightly regression matrix passed 44/44 fixtures for the first time, and the failure classifier grew to ~40 hand-written diagnoses — this week alone it learned to name pasted web links that aren't Git repositories and layouts referencing private Android system resources.
Engine
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. To choose one yourself, set the Dart SDK range in pubspec.yaml; the build log names the Flutter version used.
- 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.
Platform
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.
Dashboard
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.
Engine
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.
Engine
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.
Dashboard
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.