DEV Community

Cover image for I shipped my local Python app to the app stores as a PWA — here's the whole path
georgevillalobos
georgevillalobos

Posted on

I shipped my local Python app to the app stores as a PWA — here's the whole path

A couple of months ago, I had a Python script that ran on my desk. Today the same project is an installable app on the Microsoft Store — with Google Play and iOS on the way — and it never got a native rewrite or a cloud host for the front-end.

I learned how to do this from scattered blog posts, docs, and forum answers, and I hit a pile of small traps that cost hours each. So I wrote down the whole path and open-sourced it. This is the short version of the story; the full step-by-step guide is on GitHub.

What I was starting with

My project is a personal research dashboard for public prediction markets — it watches which proven traders are moving, cross-checks that against bookmaker odds and news, and grades every one of its own calls against reality. (It's a research tool — it places no bets and holds no money. Nothing here is financial advice.)

The important part for this post: it was a plain Python backend rendering an HTML page, running on my home PC. Great on my desk. Invisible everywhere else.

The one idea that unlocked it

Your web app + a web manifest + a service worker = a PWA (Progressive Web App). A PWA is installable on every platform. And a free tool called PWABuilder packages that same PWA into native store bundles:

Store Bundle Difficulty Cost
Microsoft Store MSIX ⭐ easiest Free (individual fee waived)
Google Play Android .aab (TWA) ⭐⭐ $25 once + hoops
iOS App Store Xcode project ⭐⭐⭐ $99/yr + a Mac

The part that surprised me most: you don't need a web host. A local app can be given a stable public HTTPS address with a free named Cloudflare Tunnel. That URL is what the stores point at.

Recommended order: PWA → Microsoft Store → Google Play → iOS. Ship the free, easy one first for the morale win.

The gotchas that actually cost me time

These are the ones I wish someone had put in bold:

  • Service workers only register over HTTPS or localhost. Testing over a plain http://<LAN-IP> address silently skips them and you'll think it's broken.
  • A 404 on sw.js breaks everything downstream — and the app still looks fine. If your server uses an allow-list, it has to actually serve sw.js, your icons, the manifest, and /.well-known/assetlinks.json at those exact paths.
  • The store app must load with no login. A store app opens for strangers, so your public view can't require a secret key. Keep any private/owner view behind auth.
  • Google re-signs your Android bundle. So the fingerprint that goes in assetlinks.json is Google's app-signing SHA-256 (from Play Console), not the upload key PWABuilder hands you. This one silently breaks deep-link verification.
  • Package IDs are permanent on both stores. Decide before your first upload.
  • Back up your Android signing keystore + passwords. Lose them and you can never update the app.

What I shared, and what I kept

Here's a line I think more solo builders should draw deliberately: I shared the mechanics, not the edge.

  • Public: the PWA-to-stores guide, and a clean reference skeleton showing how a self-grading research agent fits together — the loop, the grading/trust-ranking system, and how I route news through an LLM into a probability.
  • Private: the actual scoring math, the prompts, the wallet lists — the stuff that makes it good. Every one of those spots in the open-source skeleton is a labeled >>> PLACEHOLDER.

Sharing the frame costs you nothing and helps a lot of people. The recipe stays yours.

If you want to do the same

I built this solo, part-time, under the name PVG Production. If any of it saves you a few hours, that's the whole point — and if you find the next gotcha, open a PR.

Research tool only — not financial advice. Everything it produces is evidence to weigh, and every decision stays with a human.

Top comments (0)