docs / preparing your site

Paths reference: relative URLs, base href and the /web/ folder

Almost every "works on my server, blank in the app" bug is a path. This is the resolution table for every kind of URL a page can contain, from inside the app.

7 min read·6 sections·updated Sep 2026
TL;DR

Your site is served from /web/, so a URL starting with / points outside it and 404s. Write paths relative to the file that contains them (css/app.css, ../img/a.webp), or set a /web/ base where a tool cannot do relative.

The one rule

In the app, your index.html lives at

https://appassets.androidplatform.net/web/index.html

A browser resolves every URL on the page against that address. Anything that starts with / is resolved from the host, not from your folder — /css/app.css becomes https://appassets.androidplatform.net/css/app.css, which is outside /web/, is not one of your files, and fails. On your web server the same link worked because your site was at the root.

Resolution table

For a page at /web/index.html and one at /web/blog/post.html:

Written in the pageFrom /web/index.htmlFrom /web/blog/post.htmlOK?
css/app.css/web/css/app.css/web/blog/css/app.css✓ relative to each page
./css/app.css/web/css/app.css/web/blog/css/app.css✓ same thing
../css/app.css/css/app.css ✗/web/css/app.css✓ from sub-pages only
/css/app.css/css/app.css/css/app.css✗ outside /web/
/web/css/app.css/web/css/app.css/web/css/app.css✓ works, but ties the site to the app
https://cdn…/lib.jsthe CDNthe CDN✓ online only
//cdn…/lib.jshttps://cdn…https://cdn…✓ online only

What each kind of URL is relative to

  • HTML attributes (src, href, srcset, poster, action): the page — or its <base href>, if it has one.
  • CSS url() and @import: the stylesheet, not the page. css/app.css referencing ../fonts/a.woff2 finds /web/fonts/a.woff2 from every page.
  • fetch(), XMLHttpRequest, new Image().src: the page, even when the call is inside js/app.js. A script that does fetch('data.json') needs the path from the HTML file's location.
  • ES module import: the importing module. For assets next to a module, use new URL('./data.json', import.meta.url).
  • Web workers: new Worker('js/worker.js') is relative to the page; importScripts() inside it, to the worker script.
  • manifest.json icons: the manifest file. (The app ignores the web manifest anyway — see the PWA doc.)

<base href>: a shortcut with a trap

A <base href="./"> or <base href="/web/"> in the head makes every relative URL on that page resolve from there. It is how Angular sets its root. The trap: it also changes where in-page anchors (href="#top") point, turning them into navigations to base + #top. If your page uses fragment links, check them after adding a base.

Fixing an existing site

  1. Search your HTML, CSS and JS for ="/, url(/ and '/. Every hit that is a path to your own files needs changing.
  2. In HTML at the root, remove the leading slash: /img/a.png → img/a.png. In pages inside subfolders, add ../ per level.
  3. For a framework build, change the setting instead of the output — base: './' and friends. The build configurator has the setting for each tool.
  4. Rebuild, and check the new index.html: no src="/ or href="/ should remain.
Filename Case CheckerFind links that only work on Windows and macOS — wrong letter case, missing files, root paths Open tool

Absolute https:// links to other sites are unaffected by any of this: they load normally when the phone is online. How they open — inside the app or in another app — is covered in links, downloads and pop-ups.

FAQ

Why not make the app serve my site from / instead of /web/?

Keeping the bundle in its own folder separates your files from the app's own assets and keeps the rules identical for every app. Relative paths work in both places, so a site written with them runs unchanged on your web server and in the app.

My CSS background images are missing but the stylesheet loads — why?

url() inside a stylesheet is resolved from the stylesheet's own location. If css/app.css uses url(img/bg.webp), the browser looks for css/img/bg.webp. Use url(../img/bg.webp).

Is /web/ guaranteed to stay the same?

It is how current builds serve your files, and it is what the framework recipes that cannot produce relative paths rely on. Relative paths are still the more portable choice wherever a tool supports them.

Tools for this step

Unzip it on a phone today

Upload the ZIP, name the app, pick an icon — and download a signed APK a few minutes later. Free builds, no watermark, no Android Studio.

Convert a ZIP — free site.zip → app-release.apk