●BUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the output●NATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other builders●PLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screen●COMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to end●PRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that back●DEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verify●BUILD — Rork Max runs real Macs in the cloud loaded with Xcode and the iOS SDK, writing SwiftUI, compiling, reading the errors and building again. That loop, not the code generation, is what lifts the output●NATIVE — What comes out is pure Swift and SwiftUI, not React Native. Reaching AR, Metal graphics and widgets that React Native cannot touch is the real gap between this and other builders●PLATFORMS — Coverage spans iPhone, iPad, Apple Watch, Apple TV and Vision Pro, plus iMessage. Worth a look if you want to start from a watch app or an extension rather than a phone screen●COMPANION — The Rork Companion app lets you check a generated build on a real iPhone without a paid Apple Developer account, lowering the bar for trying a first project end to end●PRICING — Free to start, paid plans from $25 a month, and Rork Max on the $200 Max plan. Worth working out up front how many projects it takes to earn that back●DEADLINE — From August 31, 2026, Google Play requires target API level 36 or higher for new apps and updates alike. Ten days out, and the targetSdkVersion of what you generate is yours to verify
August 31 Means Something Different Depending on Whether You Plan to Ship an Update
Two separate conditions land on Google Play's August 31 date: API 36 to submit an update, and API 35 to stay discoverable to new users. Here is how I sorted six apps, and who actually gets the extension form.
I opened the Policy status page for all six of my apps in one sitting earlier this month. Some had warnings. Others had nothing at all. My first reaction was confusion about which state was the correct one.
Reading more carefully, I found that two conditions of different kinds happen to share the same date. Treating them as a single deadline leads either to work that was never needed, or to running out of runway on the one app that mattered.
Two conditions land on the same date
Breaking apart what the Play Console Help page actually says:
Condition
Applies to
Target API needed
What happens if you miss it
Submission
New apps and app updates
36 (Android 16) or higher
You cannot submit at all
Availability
Apps already published
35 (Android 15) or higher
New users on devices running an OS newer than your target can no longer discover the app
So an app already shipping at API 35 does not vanish from the store on August 31. What closes is the path to shipping anything new. The moment you try to publish the next version, 36 becomes the requirement.
That was the part I had backwards. I had been working from "get to 36 by August 31 or the app disappears," when in fact the only apps whose distribution was genuinely at risk were the ones still below 35. Once the location of the risk changes, so does the priority order.
Worth noting: the numbers differ by form factor. Wear OS and Android Automotive OS need 35 or higher, while Android TV and Android XR need 34 or higher. If you ship a watch target, do not reuse the phone number.
The extension form only reaches apps that got a warning
This is the detail that trips up the most people in practice.
The Play Console Help page states that only apps that are not compliant with the policy receive policy warnings and notifications, and that the extension form is reachable from the details page of that warning on the Policy status page. There is no permanent "request extension" button sitting at the account level.
Three practical consequences follow:
If no warning appears, no form appears. From Google's side that is correct behavior: a compliant app does not need one. But if you are waiting for a form that will never show up, you are waiting on nothing
The extension protects distribution, not submission. Being granted an extension does not let you publish an update built against a target below 36. The window until November 1 exists so your app keeps reaching all users, nothing more
The timing of the form is Google's call. The Help page says it will become available in Play Console later this year, which is not a promise that you can open it today
The third point deserves the most caution. If your plan depends on the extension, your next move is gated on someone else's schedule. Plan for the possibility that August 31 arrives with no form in sight.
✦
Thank you for reading this far.
Continue Reading
What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.
WHAT YOU'LL LEARN
✦You will be able to tell what your app actually loses on August 31, based on whether you plan to ship another update
✦You will spot the situations where waiting on the extension form leaves you with no moves left, and avoid getting cornered days before the deadline
✦You will be able to work backward from your staged rollout timeline to your own submission cutoff, and decide the order in which multiple apps go out
Secure payment via Stripe · Cancel anytime
✦
Unlock This Article
Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.
With two conditions in play, the decision has two entry points. Here is the order I worked through for six apps.
Step 1: Check the effective target API
Not the value written in build.gradle or app.config.js, but the value in the bundle that is actually live on the store. With Expo, a config plugin or a library can rewrite the final value, so the repository and the artifact do not always agree. I walked through that check in the three places I had to fix to get targetSdkVersion 36 through on a Rork project.
Step 2: Decide whether an update is coming in the next six months
This is the real fork. Bug fix or feature work, if you intend to publish again, raising the target to 36 is unavoidable. August 31 is beside the point; it becomes a precondition for your next release regardless.
Step 3: Assign a deadline per branch
Current target
Update planned
Effective deadline
What to do
36 or higher
Either way
None
Nothing needed
35
Yes
Your next release
Raise to 36. No need to race August 31
35
No
None
Distribution continues. Safe to leave alone for now
34 or lower
Yes
August 31
Top priority. Get a 36 build submitted
34 or lower
No
August 31 (softenable)
New-user distribution gets limited. This is the extension case
Out of six apps, only the ones matching row four genuinely needed August 31 as a deadline. Everything else resolved to "fix it before the next release."
Work backward from your staged rollout
"Submit by August 31" is a comfortable thought until you remember that staged rollouts take days.
When I update the Android wallpaper apps, I widen the rollout as 5% → 25% → 50% → 100%. Before each step I confirm that Crash-free users has not dropped below 99.7% and that ANR stays under 0.20%. Letting those numbers settle takes at least a day, and any ambiguous movement costs another.
Then review time stacks on top. Review sometimes finishes in hours and sometimes takes days, and it is safer to assume the queue is busy right before a deadline.
Doing that arithmetic by hand invites mistakes, so it became a small function.
// Work backward from the day you want the rollout finished to the submission cutoff.// Assumptions from my own operations: one observation day per stage, three days for review./** * @param {string} targetDateIso Day you want to finish at 100% (e.g. "2026-08-31") * @param {number[]} stages Observation days at each rollout stage * @param {number} reviewDays Days budgeted for review * @returns {{submitBy: string, totalDays: number}} */function submissionDeadline(targetDateIso, stages = [1, 1, 1, 1], reviewDays = 3) { const observationDays = stages.reduce((sum, d) => sum + d, 0); const totalDays = observationDays + reviewDays; const target = new Date(`${targetDateIso}T00:00:00+09:00`); const submit = new Date(target.getTime() - totalDays * 24 * 60 * 60 * 1000); // Format back to a JST calendar date const submitBy = new Intl.DateTimeFormat('sv-SE', { timeZone: 'Asia/Tokyo', }).format(submit); return { submitBy, totalDays };}console.log(submissionDeadline('2026-08-31'));// => { submitBy: '2026-08-24', totalDays: 7 }// Widen the observation window for an app you want to watch closelyconsole.log(submissionDeadline('2026-08-31', [2, 1, 1, 1], 4));// => { submitBy: '2026-08-22', totalDays: 9 }
August 24 surprised me a little. That is a full week ahead of the date on the calendar, and running several apps in parallel pushes it earlier still. The observation days are my own choice, so tightening them moves the cutoff later. Tightening them also raises the odds of carrying a crash all the way to 100%.
One clarification: the submission requirement is evaluated at submission time. If a 36 build goes in before August 31, a rollout that spills into September is not itself a problem. The backward calculation exists so that you decide in advance what gets dropped if the upgrade work runs long.
A script for sorting several apps at once
Opening six apps one at a time in Play Console costs half an hour every time you want a status check. The Google Play Developer API can list what is live per track.
// List the versionCodes currently on each app's production track.// Prepare a service account JSON key and grant it "Release manager" access in Play Console.import { google } from 'googleapis';const PACKAGES = [ 'net.dolice.beautifulwallpapers', 'net.dolice.ukiyoe',];async function listProductionVersions() { const auth = new google.auth.GoogleAuth({ keyFile: process.env.PLAY_SERVICE_ACCOUNT_JSON, // e.g. ./play-service-account.json scopes: ['https://www.googleapis.com/auth/androidpublisher'], }); const publisher = google.androidpublisher({ version: 'v3', auth }); const rows = []; for (const packageName of PACKAGES) { // Track data is unreadable without opening an edit session first const { data: edit } = await publisher.edits.insert({ packageName }); try { const { data } = await publisher.edits.tracks.get({ packageName, editId: edit.id, track: 'production', }); const active = (data.releases ?? []).filter((r) => r.status !== 'draft'); for (const release of active) { rows.push({ packageName, status: release.status, // completed, inProgress, and so on fraction: release.userFraction ?? 1, // 0.05 etc. while staged versionCodes: (release.versionCodes ?? []).join(','), }); } } finally { // Always discard the edit session; leftovers collide with the next insert await publisher.edits.delete({ packageName, editId: edit.id }); } } console.table(rows);}listProductionVersions().catch((err) => { console.error('Failed to fetch:', err.message); process.exitCode = 1;});
That finally block is there because of a real detour. Repeating edits.insert on the same package without discarding leaves sessions hanging open, and the resulting error message points nowhere near the cause. I spent a while suspecting a permissions problem.
Note the limit: this API returns versionCode, not targetSdkVersion. The effective target still has to come from the bundle itself. Even so, seeing at a glance which app is parked mid-rollout and how old the last release is changes how fast the sorting goes.
Do not delete "ship nothing" from the option list
Running several apps alone, keeping everything current quietly turns into the goal itself. The option I deliberately kept on the table this time was the one where nothing ships.
Per the Play Console Help page, users who already installed the app are unaffected and can still reinstall it. The restriction lands on new users whose devices run an OS newer than the app's target.
If an app takes a few days to move to 36 and brings in a few dozen new installs a month, spending those days elsewhere can be the sounder call. The deciding input is not crash rate or revenue but where that app's new installs are coming from right now. It is the same lens I used in checking four countries where new installs stop, against the traffic mix of six apps, with the axis switched from country to OS version.
Stopping updates also stops security fixes, of course. The point is not that neglect is fine, but that "not this month" and "not ever" are different decisions.
What to settle today
Projects generated with Rork or Expo often carry whatever target the template shipped with. The faster your path from generation to submission, the easier it is to never look at that value. How to structure the rollout itself is covered in staged release strategy for Rork apps.
Pick one app and check the effective target in the bundle that is live. Then write down when the next update is going out. Whether August 31 is your deadline answers itself at that point.
When a deadline is close, simply separating the conditions can take real weight off. If you are carrying a handful of apps the way I am, I hope this makes the next decision a lighter one.
Share
Thank You for Reading
Rork Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.