Stage 1 — in your browser: normalising the ZIP
Nothing is uploaded when you pick a file. The builder opens the ZIP in the page and turns it into a clean bundle:
- Litter is dropped.
__MACOSX/folders and._resource-fork files are ignored. - The start page is chosen:
index.htmlat the root; otherwise, if everything sits in one folder, that folder'sindex.html(and the folder is stripped off); otherwise the shallowest HTML file. - Pages are screened against the content policy the app stores enforce.
- The bundle is re-zipped and measured — 5 MB on the free plan, 18 MB on Pro.
You see the result in the phone preview immediately, served the same way the finished app will serve it.
Stage 2 — in the cloud: building the APK
When you start a build, the bundle and your settings go to the build service, which assembles the app around the same tested Android runtime every build uses:
| Input | Where it ends up in the APK |
|---|---|
| Your site's files | assets/web/, byte for byte |
| Name, theme colour, splash, tabs, permissions, start page | assets/app_settings.json, read by the app at launch |
| Package name and version | The compiled AndroidManifest.xml |
| Icon | Launcher icon resources |
| Signing key | The APK signature (v1 + v2 schemes); a shared release key on the free plan, your own on Pro |
The app's code — the Kotlin shell around the WebView — is the same tested runtime for every build. Your files are never modified, minified or "optimised" on the way in, which is why a site that works in the preview works in the app.
Stage 3 — on the phone: the runtime
When the app launches it shows the splash (if configured), then a full-screen Android System WebView — the Chromium-based engine every Android app shares, updated through Google Play on Android 7 and later.
The key design decision is how your files reach that WebView. They are not opened as file:// URLs. An asset loader answers requests for
https://appassets.androidplatform.net/web/<path>
by reading assets/web/<path> from inside the APK — without touching the network. appassets.androidplatform.net is a hostname Android reserves for exactly this purpose. To the page, it looks like an ordinary https website.
Why the https origin matters
Under file:// a page has no origin, and Chromium blocks the features whose security depends on one. Serving from a real origin removes those restrictions:
| Feature | From file:// | In a ZIPtoAPK app |
|---|---|---|
<script type="module"> and import | Blocked | Works |
fetch('data/menu.json') | Blocked | Works |
| localStorage, IndexedDB | Unreliable | Works, persists across updates |
WebAssembly (.wasm served as application/wasm) | Limited | Works, including streaming compile |
| Calls to your API | Origin null | Origin https://appassets.androidplatform.net — allow it in CORS |
Two consequences follow, and they shape the rest of these docs. First, your site lives at /web/, not at /, so root-relative paths break. Second, the file server is literal — a request for a path that does not exist returns 404, with no fallback to index.html — so single-page apps should use hash routing.
Everything else is ordinary Android
The Android back button walks back through the WebView's history before closing the app. Links to other websites load inside the app; Pro builds hand tel:, mailto:, WhatsApp, Telegram, Play Store and Maps links to the matching app (details). Storage survives app updates as long as the package name and signing key stay the same, and is wiped when the app is uninstalled.