Converting

How to prepare website files for conversion to an app

A folder layout, path rules and bundler settings that survive being packed into an app — and the quick test that tells you before any build runs.

6 min read Updated September 2026

Quick answer: a website converts cleanly when nothing in it assumes a web server. That means relative paths, lowercase filenames without spaces, fonts and libraries stored locally, a bundler base path of ./, hash-based routing for single-page apps, and a viewport meta tag. Test by opening index.html directly from your file manager — what breaks there breaks in the app.

A layout that packs well

app/
├── index.html         ← entry page at the root
├── pages/about.html
├── css/site.css
├── js/site.js
├── img/hero.webp
├── fonts/body.woff2
└── data/items.json

Nothing special about it. What matters is that every reference from one file to another can be written relative to the file making it, and the tree is complete on its own.

Five rules

1. Relative paths

From index.html: css/site.css. From pages/about.html: ../css/site.css. Never /css/site.css — there is no root inside an app.

2. Lowercase filenames

Android's filesystem distinguishes Hero.JPG from hero.jpg; your desktop probably does not. Lowercase everything and the mismatch cannot occur.

3. No spaces or accents in names

team photo.png becomes team%20photo.png in a URL and every layer that re-encodes it is a chance to break it. Use hyphens.

4. Keep assets local

Google Fonts, CDN scripts and remote stylesheets vanish offline. Download them into the project. Local files also load faster — no DNS, no TLS.

5. Include a viewport tag

<meta name="viewport" content="width=device-width, initial-scale=1">. Without it the WebView lays the page out at desktop width and shrinks it.

Bundler settings that bite

Vite, webpack and Parcel default to absolute asset URLs like /assets/index-4f2a.js — right for a server, wrong for a bundle. Make the base relative:

// vite.config.js
export default { base: './' }

// webpack.config.js
output: { publicPath: './' }

They also emit <script type="module"> by default, which does not load from file://. Either target a classic-script output, or use a converter that serves bundled content over http://localhost — confirm which rather than assuming.

Single-page apps: use hash routing

A History-API router (/products/42) relies on the server rewriting unknown paths to index.html. No server, no rewrite, so deep links 404 inside the app. Hash routing (#/products/42) needs no server and works everywhere. Most routers switch with one option.

Storage

localStorage works in a WebView and survives restarts, but it is erased when the user clears the app's data and it is not backed up. Use it for preferences and caching. Anything the user would be upset to lose belongs on a server.

The five-second test

Open index.html directly from your file manager — not through a dev server. That is the environment the app gives your pages.

HTML ValidatorCheck HTML for problems that break inside an app Open the tool
Validator results split into blocking problems, warnings and notes for a sample page
Blocking items break the app; warnings depend on how you plan to ship it.

Before packaging

CheckBecause
index.html at the rootIt is the page the app opens
Relative paths everywhereNo site root exists in an app
Lowercase names, no spacesCase-sensitive filesystem
Fonts and libraries localOffline pages still render
Hash routingNo server to rewrite deep links
Viewport meta tagCorrect mobile layout
No sources, maps or secretsEverything shipped can be extracted

Questions people ask

Where does index.html belong?

At the top level of the project and the ZIP. It is what the app opens on launch; nested in a folder, the app has to be told where it is — or opens blank.

Relative or absolute paths?

Relative. There is no web root inside an app, so /css/site.css is unreliable while css/site.css and ../css/site.css always resolve.

Will my React or Vue router work?

In hash mode, yes. History mode needs a server to rewrite deep links to index.html, and a bundled app has none. Most routers switch modes with a single setting.

Can I use a JavaScript framework?

Yes. React, Vue, Svelte and the rest run in a WebView. Set the bundler's base to ./, use hash routing, and avoid loading the output as an ES module from file://.

Is localStorage reliable in an app?

It persists between launches but is wiped when the user clears the app's data and is not backed up. Treat it as a cache, not a database.

Read next

Ready to turn your site into an app?

Upload an HTML file or a ZIP, set your icon and name, and download a signed Android app. No Android Studio, no command line.

Open the builder