Skip to content

feat: PWA manifest + service worker so dashboard is installable#44

Open
jakduch wants to merge 4 commits into
josepe98:mainfrom
jakduch:feat/pwa-installable
Open

feat: PWA manifest + service worker so dashboard is installable#44
jakduch wants to merge 4 commits into
josepe98:mainfrom
jakduch:feat/pwa-installable

Conversation

@jakduch
Copy link
Copy Markdown
Collaborator

@jakduch jakduch commented May 23, 2026

What does this add and why do you believe it belongs in this dashboard?

This PR makes the local dashboard a Progressive Web App by adding a manifest.json, a minimal sw.js service worker, and an SVG app icon, plus the matching <link rel="manifest">, <meta name="theme-color">, Apple apple-touch-icon / apple-mobile-web-app-* metas in <head> and a feature-detected navigator.serviceWorker.register("/sw.js") boot. Once installed, the dashboard opens in its own OS window with no browser chrome and gets its own dock/taskbar icon — Chrome and Edge show their "Install app" affordance, and on iOS Safari "Add to Home Screen" produces a real standalone web app.

It belongs in this dashboard because Claude Code Usage is the kind of tool you check repeatedly throughout the day. Hunting for the right localhost:8080 tab is friction; a real installable app removes that friction without giving up the "it's just a local Python script" property of the project. The cost is genuinely tiny — three new do_GET branches and ~10 HTML lines, no new third-party dependencies, no build step, no PNG raster (SVG icons are accepted by modern Chrome/Edge/Safari for PWA installs). The service worker only caches the Chart.js CDN bundle as stale-while-revalidate; every /api/* request goes straight to the network, so installed users never see stale numbers.

Checklist

Code correctness

  • All calcCost() calls pass 6 arguments: (model, inp, out, cache_read, cache_creation, cache_1h)
  • JavaScript template literals use bare backticks (`), not escaped ones (\`)
  • No JS variables referenced before they are defined
  • No new third-party dependencies introduced

Tests

  • python3 -m unittest discover -s tests -v — all passing
  • python3 -m unittest tests.test_browser -v — all passing
  • New behaviour is covered by at least one test

Scope

  • This is a single concern — one feature or fix per PR
  • Only touches existing files (dashboard.py, scanner.py, cli.py, pricing.py, cowork.py, tests/) — or I've explained below why a new file is needed

tests/test_pwa.py is the one new file. It is the unit-test home for the three new PWA routes (/manifest.json, /sw.js, /icon.svg) plus the HTML manifest-link and SW-register hooks. Putting these checks in their own module keeps test_dashboard.py focused on the existing HTML/API surface and means a future "remove PWA" patch is a single-file delete.

jakduch added 2 commits May 23, 2026 20:40
Adds GET /manifest.json, GET /sw.js, and GET /icon.svg routes plus the
matching <link rel="manifest">, theme-color meta, icon links, and
navigator.serviceWorker.register('/sw.js') boot in the HTML head/tail.

Chrome (and Edge/Safari) now offers 'Install Claude Usage' as a desktop
app. The service worker is intentionally tiny: install, claim clients,
fetch passthrough with a stale-while-revalidate cache for the Chart.js
CDN bundle so repeat loads are instant and the dashboard still boots
when offline-after-first-visit. All /api/* traffic goes straight to the
network — no stale data risk.

Icon is a single SVG (bar-chart glyph in the Apple-theme accent blue),
served at /icon.svg with image/svg+xml. Modern browsers accept SVG for
PWA manifest icons, so no PNG raster is needed.

Tests: 5 new tests in tests/test_pwa.py cover manifest JSON shape +
required keys, sw.js content-type + scope header, icon.svg content,
HTML <link rel=manifest> hook, and the SW register call.
@josepe98 josepe98 closed this May 25, 2026
@josepe98 josepe98 reopened this May 25, 2026
@josepe98 josepe98 closed this May 25, 2026
@josepe98 josepe98 reopened this May 25, 2026
@josepe98 josepe98 closed this May 25, 2026
@josepe98 josepe98 reopened this May 25, 2026
@josepe98 josepe98 closed this May 25, 2026
@josepe98 josepe98 reopened this May 25, 2026
@josepe98 josepe98 closed this May 25, 2026
@josepe98 josepe98 reopened this May 25, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants