A blank screen in an APK built from HTML is almost always one of four things: absolute asset paths (/assets/app.js instead of assets/app.js), a history-mode router that matches no route, a script loaded from a CDN with no connection, or a file name whose capitalisation differs from the link. Reproduce the app locally by serving the build from a /web/ sub-folder, open DevTools, and the first red console error names the cause.
First: reproduce it on your computer
Release APKs do not allow chrome://inspect, so debug a faithful copy instead. The app serves your files from a /web/ sub-folder of an https origin; mimic that:
mkdir -p /tmp/appsim/web
cp -R dist/* /tmp/appsim/web/ # or your unzipped site
cd /tmp/appsim && npx serve -l 5050 .
# open http://localhost:5050/web/index.html with DevTools → device modeEvery path bug the app has, this copy has too. Read the Console and the Network panel (red rows are missing files).
The nine causes, most common first
1. Absolute or root-relative paths
<script src="/assets/index.js"> asks for the origin's root, not /web/. Fix: relative paths, or rebuild with base: './' (Vite), "homepage": "." (CRA), --base-href ./ (Angular). The absolute path fixer rewrites plain HTML.
2. History-mode routing
The router sees /web/index.html, matches nothing, renders nothing. Switch to hash routing. Routing guide.
3. A required script on a CDN
Offline or on a slow network, React/Vue/jQuery from a CDN never loads and nothing renders. Bundle it.
4. File-name case
App.js in the ZIP, app.js in the tag. Works on Windows and macOS, 404s on Android.
5. Wrong start page
The ZIP has a template index.html at the root and the real build in dist/. The builder opens the template. Zip the contents of dist/. Check with the ZIP structure checker.
6. A JavaScript error before first render
An exception in the entry file stops everything. Common: code reading window.matchMedia or localStorage in a way only a browser extension tolerated, or syntax newer than old WebViews support. Read the first console error.
7. Localhost or dev-server URLs
An API base of http://localhost:3000 or http://192.168.x.x left in the build. On the phone it points at the phone itself.
8. Plain http requests
Android blocks cleartext http by default and the page is https, so mixed content is blocked. Use https APIs.
9. An outdated WebView
Rare but real on old phones with Play updates disabled: Android System WebView far behind current Chrome. Ask the user to update "Android System WebView" in Play, or transpile to an older target (build.target: 'es2018').
When it only happens on the phone
Add Eruda to a test build to get a console on the device: <script src="vendor/eruda.js"></script><script>eruda.init()</script>. Remove it before release.
Questions people ask
Why does my HTML app work in the browser but show a white screen in the APK?
The browser served the files from the root of a server; the app serves them from a /web/ sub-folder. Root-relative paths and history-mode routes that worked at the root break there. Make paths relative and use hash routing.
Can I use chrome://inspect on my APK?
Not on a signed release build; WebView debugging is off for security. Reproduce the app locally with the /web/ sub-folder trick, or add Eruda to a test build.
Why is my Phaser or Three.js APK black?
Usually asset paths: textures and models requested from /assets/... rather than assets/.... Rebuild with a relative base and relative loader paths.