Build my web app
WordPress · self-hosted · WordPress.com · WooCommerce

Turn a WordPress site into an installable web app

WordPress is the easiest major platform to make installable, because on most plans you control the files at the root of your domain. Here is what to generate, where to put it, what WooCommerce must never cache, and the one plan where you need the Android wrapper instead.

Generate the files → Android package instead

First: which WordPress do you have?

QuestionAnswer
Self-hosted (any host with FTP, SFTP or a file manager)Full PWA. You can place manifest.json, sw.js and offline.html at the root. Best case.
WordPress.com Business, Commerce or higherFull PWA. These plans allow plugins and SFTP access.
WordPress.com Free, Personal or PremiumNo root files, no plugins. Use the Android package route, or upgrade.
Managed WordPress (Kinsta, WP Engine, SiteGround…)Full PWA. Upload through SFTP; check the host's caching layer excludes sw.js from long cache times.

Plugin or generated files?

There are capable PWA plugins for WordPress, and if you would rather click than upload, use one. The trade-off is control: plugins write a generic service worker and register it from every page, and the good ones are large. The builder gives you three small files you can read, edit and version alongside your theme, with a caching policy you chose. Either way the outcome — an install prompt on Android, add-to-home-screen on iPhone — is the same. Don't run both; two service workers fighting over one scope is a classic source of "the site shows old content".

Where the files go

  1. Unzip the download. Upload manifest.json, sw.js and offline.html to the same directory as wp-config.php (the site root, often public_html). Upload the icons/ folder there too.
  2. Add the manifest link and registration snippet to the <head>. Use your theme's Additional CSS & JS, a child theme's header.php, or a snippet plugin hooked to wp_head:
<link rel="manifest" href="/manifest.json">
<meta name="theme-color" content="#4F46E5">
<link rel="apple-touch-icon" href="/icons/icon-192x192.png">
<script>
if ('serviceWorker' in navigator) {
  window.addEventListener('load', () => navigator.serviceWorker.register('/sw.js'));
}
</script>
  1. Confirm https://yoursite.com/sw.js loads as plain JavaScript (not a 404 page, not redirected to /sw.js/ with a trailing slash — some permalink settings do that; a rewrite rule excluding .js fixes it).
  2. Visit the site in Chrome on Android. The install prompt appears on the second visit within a few minutes, or immediately via menu → Install app.

WooCommerce: the caching rules that matter

A service worker that caches the wrong page will show a customer someone else's cart. The generated sw.js only caches GET requests and never caches HTML in the aggressive mode's dynamic paths, but you should still make the exclusions explicit for a shop. In the service worker's fetch handler, bypass the cache for:

  • /cart/, /checkout/, /my-account/ and anything under them
  • /wp-admin/, /wp-login.php, /wp-json/ (the REST API — includes the Store API used by block checkout)
  • Any URL with ?add-to-cart=, ?wc-ajax= or a nonce parameter

Product pages, category pages, images and the theme's CSS/JS are safe to cache and are where the speed gain comes from. Pick Balanced in the builder; Network first if prices change during the day.

Push notifications for new posts

The natural WordPress use of push is "new article published". The builder's OneSignal field wires the service worker for web push; on the WordPress side, OneSignal's own plugin sends a notification automatically on publish and handles the subscription prompt. iPhone users receive them only after adding the site to their home screen (iOS 16.4+), so say so on your install page — the push guide has the details and the etiquette.

Scope and the wp-content problem

Set the manifest scope to / so every post and page is "inside" the app. Links to /wp-admin/ will open in a browser tab from the installed app, which is what you want. If your site lives in a subdirectory (/blog/), the files go in that subdirectory and the scope becomes /blog/; a service worker cannot control paths above where it is served.

When the Android package is the right call

On WordPress.com Free/Personal/Premium you cannot upload root files, so a real PWA is off the table without upgrading. The Android app builder wraps the live site into an APK/AAB with your icon and splash — content stays live, and you can publish it to Google Play. It does nothing for iPhone users, so weigh that against the cost of the plan upgrade.

Frequently asked questions

Will a PWA break my caching plugin?

No, they operate at different layers: WP Rocket, LiteSpeed Cache and friends cache on the server; the service worker caches in the browser. Just make sure the server cache does not serve sw.js with a long max-age — a day is fine, a year is not, or users will keep an old service worker.

Does this work with Elementor, Divi or block themes?

Yes. The service worker doesn't care how the HTML was produced. Page builders that load many scripts benefit most from the Balanced mode's asset caching.

Can WordPress.com Free users do anything?

Only the Android wrapper route. Free plans do not allow root files or custom head code, both of which a PWA needs.

Do I need to update the files when I change my theme?

Only if the theme changes your colours or icon. The service worker caches by URL pattern, not by theme, so new assets are picked up automatically.