Most of the PWA writing out there is aimed at content sites, and games break those assumptions immediately because the asset budget is an order of magnitude larger. This is the split that has worked for us, written for people who ship builds rather than blog posts.
The Three Requirements, Briefly
A browser game becomes installable when three things are true: it is served over HTTPS, it links a web app manifest, and it registers a service worker. The manifest is a JSON file describing the name, the icon set, the theme colors, the display mode and the start URL, and it is what turns the thing from a page into a home screen icon with a splash screen. The service worker is the part that does real work.
Split Your Assets Into Two Groups
The mistake is caching everything during service worker install. A 200 MB precache means the install event runs for a minute on a bad connection and the browser may kill it, so you get no offline support at all rather than partial support.
Split instead. The install group is whatever the player needs to reach an interactive first screen: the engine bundle, the UI atlas, the font, the first level, the menu music. That should be small enough to fetch in a few seconds. Everything else is the lazy group, cached on first use with a cache-first handler, so level 12 lands in the cache the first time someone reaches level 12 and is available offline afterward.
Version your cache names and delete old caches in the activate event. Without that, a shipped update leaves the previous build's assets on the device forever, and players report bugs you already fixed.
Where Saves Actually Live
Small state goes in localStorage: settings, the current level, a coin count. It is synchronous, it is capped around 5 MB, and it is fine for anything you would have put in a config file.
Anything structured goes in IndexedDB: full save states, replays, downloaded user content, large inventories. It is asynchronous and awkward to use directly, so wrap it or use a small library, but it is the only browser storage that will hold a real save file.
Both are subject to eviction. A player who installs the game to their home screen gets persistent storage in most browsers, which is a good argument for prompting the install rather than treating it as a nice extra.
iOS Is Where the Plan Breaks
Test on iOS before you commit to a PWA-only distribution plan. Storage limits are tighter and eviction is more aggressive, audio behavior around the first user gesture is stricter, and the install flow is a manual Add to Home Screen through the share sheet rather than a prompt you can trigger. None of that is fatal, but all of it is easier to design around than to retrofit.
The longer version, covering install prompts, the manifest fields that matter and the honest comparison against native, is in our guide to PWA games.
When Not To Bother
If your game is a one-off jam entry that nobody will open twice, the service worker is wasted work. PWA pays off when players come back, and the return visit is the whole reason to spend the effort on cache versioning and save durability.