From 517ac6fb4668067649686735bcc818f0034b084f Mon Sep 17 00:00:00 2001 From: Walter Oggioni Date: Wed, 14 Oct 2026 22:14:43 +0000 Subject: [PATCH] Make the frontend an installable PWA Add a web app manifest and an install-only service worker (no offline caching: live state always comes from the server and hashed asset names change every build), registered from the WASM bundle. The worker must live at the site root for its scope to cover the app, and Granian only serves /static and /assets, so tavolo/static.py answers /manifest.webmanifest and /sw.js from STATIC_DIR with the content types browsers require; index.html gains the manifest link, icons, theme-color and Apple standalone meta tags. Icons are committed under web/assets/icons/ with vector sources and a make-icons.sh regeneration script, mirroring the card art workflow. --- README.md | 25 +++++- server/Dockerfile | 3 + .../packages/tavolo-app/src/tavolo/static.py | 71 ++++++++++++++---- server/tests/test_routes_me.py | 40 ++++++++++ web/Cargo.toml | 2 +- web/assets/icons/apple-touch-icon.png | Bin 0 -> 9058 bytes web/assets/icons/icon-192.png | Bin 0 -> 11335 bytes web/assets/icons/icon-512.png | Bin 0 -> 35605 bytes web/assets/icons/icon-maskable-512.png | Bin 0 -> 31031 bytes web/assets/icons/icon-maskable.svg | 14 ++++ web/assets/icons/icon.svg | 15 ++++ web/index.html | 17 ++++- web/make-icons.sh | 16 ++++ web/manifest.webmanifest | 31 ++++++++ web/src/main.rs | 2 + web/src/pwa.rs | 20 +++++ web/sw.js | 34 +++++++++ 17 files changed, 271 insertions(+), 19 deletions(-) create mode 100644 web/assets/icons/apple-touch-icon.png create mode 100644 web/assets/icons/icon-192.png create mode 100644 web/assets/icons/icon-512.png create mode 100644 web/assets/icons/icon-maskable-512.png create mode 100644 web/assets/icons/icon-maskable.svg create mode 100644 web/assets/icons/icon.svg create mode 100755 web/make-icons.sh create mode 100644 web/manifest.webmanifest create mode 100644 web/src/pwa.rs create mode 100644 web/sw.js diff --git a/README.md b/README.md index 7df91f9..21c2d7c 100644 --- a/README.md +++ b/README.md @@ -20,8 +20,8 @@ and a secret partner: WebAssembly, built with [Trunk](https://trunkrs.dev) and styled with [Bootstrap](https://getbootstrap.com) 5.3 (MIT, vendored under `web/vendor/` so builds work offline) plus the custom felt theme in - `web/theme.css`. Card images are the - CC0 *woodcut napoletane* deck traced from a 1902 Naples print + `web/theme.css`. Also an installable PWA — see [PWA](#pwa). Card images + are the CC0 *woodcut napoletane* deck traced from a 1902 Naples print ([SONDLecT/woodcut-napoletane](https://github.com/SONDLecT/woodcut-napoletane)). ## Run the whole stack @@ -77,6 +77,23 @@ the called card is played, so the secret partner stays secret. The the URL to share. A spectator who opens the URL before the match starts sees a "game not started yet" waiting room. +## PWA + +The frontend is an installable PWA: `web/manifest.webmanifest` describes +the app (standalone display, felt theme colors, PNG icons), and `web/sw.js` +is an install-only service worker — it deliberately caches nothing, since +live state always comes from the server and hashed asset names change every +build. Browsers offer to install Tavolo over HTTPS (or on localhost in +development). + +Both files must be served from the site root, or the worker's scope and the +manifest's `start_url` could not cover the app: Granian only serves +`/static` and `/assets`, so `tavolo/static.py` answers +`/manifest.webmanifest` and `/sw.js` (revalidated on every load) from the +same build directory as the shell. Icons are committed under +`web/assets/icons/`; `web/make-icons.sh` regenerates them with +`rsvg-convert` after editing the vector sources. + ## Development Backend (from `server/`): @@ -115,4 +132,6 @@ OIDC_0_POST_LOGOUT_REDIRECT=http://localhost:8000/ \ ``` Card images are committed under `web/assets/cards/`; `web/fetch-cards.sh` -re-downloads them if needed. +re-downloads them if needed. PWA icons are committed under +`web/assets/icons/`; `web/make-icons.sh` regenerates them from the SVG +sources. diff --git a/server/Dockerfile b/server/Dockerfile index d929eb0..19b6d0b 100644 --- a/server/Dockerfile +++ b/server/Dockerfile @@ -30,6 +30,9 @@ WORKDIR /web # Card images are committed in the repository (CC0 woodcut napoletane deck); # web/fetch-cards.sh can regenerate them. COPY web/Cargo.toml web/Cargo.lock web/index.html web/style.css web/theme.css web/Trunk.toml ./ +# PWA manifest and service worker: trunk's copy-file entries need them at +# the build root, and the runtime serves both from the site root (static.py). +COPY web/manifest.webmanifest web/sw.js ./ COPY web/assets ./assets # Vendored Bootstrap (MIT) loaded by index.html; kept out of the CDN so the # image builds and runs without network access. diff --git a/server/packages/tavolo-app/src/tavolo/static.py b/server/packages/tavolo-app/src/tavolo/static.py index 067525a..72bde7e 100644 --- a/server/packages/tavolo-app/src/tavolo/static.py +++ b/server/packages/tavolo-app/src/tavolo/static.py @@ -1,19 +1,27 @@ """SPA shell hosting for the compiled single-page application. -Static assets (wasm, js, css, card images) are served by Granian itself -under the ``/static`` prefix (``GRANIAN_STATIC_PATH_*`` env vars; see the -Dockerfile) and never reach Python. This module only serves ``index.html`` -from ``STATIC_DIR``: at the site root and — via the glob catch-all — for -every path no API or auth route claimed, so client-side routes -(``/game/`` etc.) work on direct loads and refreshes. +Static assets (wasm, js, css, card images, PWA icons) are served by +Granian itself under the ``/static`` and ``/assets`` prefixes +(``GRANIAN_STATIC_PATH_*`` env vars; see the Dockerfile) and never reach +Python. This module serves the few files that must live at the site root +from ``STATIC_DIR``: -kaya-openapi deliberately skips glob routes, so this handler never appears -in the API specification. +- ``index.html`` at the site root and — via the glob catch-all — for + every path no API or auth route claimed, so client-side routes + (``/game/`` etc.) work on direct loads and refreshes; +- the web app manifest, whose ``start_url``/``scope`` cover the app; +- the service worker, whose default scope is its own directory: served + from ``/static`` it could only control ``/static``, so it is served at + ``/sw.js`` instead. + +kaya-openapi deliberately skips glob routes, so the fallback handler +never appears in the API specification. """ from __future__ import annotations import asyncio from pathlib import Path +from typing import Optional from kaya.core import HttpContext @@ -21,14 +29,30 @@ from .app import app from .config import settings -async def _send_shell(ctx: HttpContext) -> None: - """Serve the SPA shell, or 404 when the frontend build is missing.""" - index = Path(settings.static_dir) / "index.html" - if not index.is_file(): +async def _send_from_dist(ctx: HttpContext, + filename: str, + content_type: str, + cache_control: Optional[str] = None) -> None: + """Serve one file from ``STATIC_DIR``, or 404 when the build lacks it. + + Unlike the SPA fallback, a missing file is not silently replaced by + the app shell: a manifest or worker answer with the wrong content + type would only confuse the browser. + """ + file = Path(settings.static_dir) / filename + if not file.is_file(): await ctx.send_empty(404) return - body = await asyncio.to_thread(index.read_bytes) - await ctx.send_bytes(200, body, {"content-type": ("text/html; charset=utf-8",)}) + body = await asyncio.to_thread(file.read_bytes) + headers = {"content-type": (content_type,)} + if cache_control is not None: + headers["cache-control"] = (cache_control,) + await ctx.send_bytes(200, body, headers) + + +async def _send_shell(ctx: HttpContext) -> None: + """Serve the SPA shell, or 404 when the frontend build is missing.""" + await _send_from_dist(ctx, "index.html", "text/html; charset=utf-8") @app.GET("/") @@ -38,6 +62,25 @@ async def index(ctx: HttpContext) -> None: await _send_shell(ctx) +@app.GET("/manifest.webmanifest") +async def manifest(ctx: HttpContext) -> None: + """Serve the web app manifest (linked from index.html).""" + await _send_from_dist(ctx, "manifest.webmanifest", "application/manifest+json") + + +@app.GET("/sw.js") +async def service_worker(ctx: HttpContext) -> None: + """Serve the service worker from the site root so its scope is the + whole app. The script is revalidated on every load (no-cache) so a new + build's worker takes over promptly.""" + await _send_from_dist( + ctx, + "sw.js", + "text/javascript; charset=utf-8", + cache_control="no-cache", + ) + + @app.GET("/*", recursive=True) async def spa(ctx: HttpContext, _matched: object = None) -> None: """SPA fallback: any path that matched no other route renders the app diff --git a/server/tests/test_routes_me.py b/server/tests/test_routes_me.py index 619d0bc..a829043 100644 --- a/server/tests/test_routes_me.py +++ b/server/tests/test_routes_me.py @@ -81,6 +81,46 @@ class StaticRouteTest(unittest.TestCase): self.assertEqual(200, fallback.status_code) self.assertIn(b"spa", fallback.content) + @async_test + async def test_serves_pwa_manifest_and_worker(self) -> None: + """The manifest and the service worker are served from the site + root, with the content types browsers require, instead of falling + through to the app shell.""" + with tempfile.TemporaryDirectory() as dist: + (Path(dist) / "index.html").write_text("spa") + (Path(dist) / "manifest.webmanifest").write_text('{"name": "Tavolo"}') + (Path(dist) / "sw.js").write_text("self.addEventListener('fetch', () => {});") + + patched = dataclasses.replace(settings, static_dir=dist) + with mock.patch("tavolo.static.settings", patched): + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://127.0.0.1") as client: + manifest = await client.get("/manifest.webmanifest") + self.assertEqual(200, manifest.status_code) + self.assertEqual("application/manifest+json", manifest.headers["content-type"]) + self.assertEqual('{"name": "Tavolo"}', manifest.text) + + worker = await client.get("/sw.js") + self.assertEqual(200, worker.status_code) + self.assertEqual("text/javascript; charset=utf-8", worker.headers["content-type"]) + # The worker script itself must never be cached stale. + self.assertEqual("no-cache", worker.headers["cache-control"]) + self.assertIn(b"addEventListener", worker.content) + + @async_test + async def test_missing_pwa_files_return_404(self) -> None: + """A build without the PWA files must 404 those exact paths rather + than answer them with the shell (the wrong content type).""" + with tempfile.TemporaryDirectory() as dist: + (Path(dist) / "index.html").write_text("spa") + + patched = dataclasses.replace(settings, static_dir=dist) + with mock.patch("tavolo.static.settings", patched): + transport = ASGITransport(app=app) + async with AsyncClient(transport=transport, base_url="http://127.0.0.1") as client: + self.assertEqual(404, (await client.get("/manifest.webmanifest")).status_code) + self.assertEqual(404, (await client.get("/sw.js")).status_code) + @async_test async def test_missing_dist_returns_404(self) -> None: patched = dataclasses.replace(settings, static_dir="/nonexistent-dist") diff --git a/web/Cargo.toml b/web/Cargo.toml index fdaa36f..38c4c55 100644 --- a/web/Cargo.toml +++ b/web/Cargo.toml @@ -13,7 +13,7 @@ serde_json = "1" wasm-bindgen = "0.2" wasm-bindgen-futures = "0.4" futures = "0.3" -web-sys = { version = "0.3", features = ["Window", "Location", "Clipboard", "Navigator", "console", "Storage"] } +web-sys = { version = "0.3", features = ["Window", "Location", "Clipboard", "Navigator", "console", "Storage", "ServiceWorkerContainer"] } js-sys = "0.3" gloo-timers = "0.3" console_error_panic_hook = "0.1" diff --git a/web/assets/icons/apple-touch-icon.png b/web/assets/icons/apple-touch-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..da128b39a3526ef9b84f1f8f382d412c46322f53 GIT binary patch literal 9058 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 UI$$GSvH$=807*qoM6N<$f literal 0 HcmV?d00001 diff --git a/web/assets/icons/icon-192.png b/web/assets/icons/icon-192.png new file mode 100644 index 0000000000000000000000000000000000000000..3c27bfb5cc4a15ae4c73089b3536f0184973b628 GIT binary patch literal 11335 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 JPDHLkV1g-Pcl7`O literal 0 HcmV?d00001 diff --git a/web/assets/icons/icon-512.png b/web/assets/icons/icon-512.png new file mode 100644 index 0000000000000000000000000000000000000000..7d289b2ac75bce92b57fb06630f8aa8a6343b496 GIT binary patch literal 35605 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

*LfJ8C`Miy)VT087koNC=UDg+C^Z?{o2I(0sU2Y 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%0A2Iw#)mgJ@fG%2lYHq&x!>k;X5^$l0 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 AFaQ7m literal 0 HcmV?d00001 diff --git a/web/assets/icons/icon-maskable-512.png b/web/assets/icons/icon-maskable-512.png new file mode 100644 index 0000000000000000000000000000000000000000..87f8f91642da5e653eb40f0ad58bbd189b853b24 GIT binary patch literal 31031 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 + + + + + + + + + + diff --git a/web/assets/icons/icon.svg b/web/assets/icons/icon.svg new file mode 100644 index 0000000..f9fa1d2 --- /dev/null +++ b/web/assets/icons/icon.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + diff --git a/web/index.html b/web/index.html index 1280622..69df316 100644 --- a/web/index.html +++ b/web/index.html @@ -4,12 +4,27 @@ Tavolo + + + + + + + + + + + - + diff --git a/web/make-icons.sh b/web/make-icons.sh new file mode 100755 index 0000000..260edf7 --- /dev/null +++ b/web/make-icons.sh @@ -0,0 +1,16 @@ +#!/bin/sh +# Regenerate the PWA icon PNGs from the vector sources in assets/icons/. +# The PNGs are committed (like the card art) because the Docker builder has +# no SVG rasterizer; run this only after editing icon.svg or +# icon-maskable.svg. Requires rsvg-convert (librsvg). +set -eu + +ICONS="$(dirname "$0")/assets/icons" + +rsvg-convert -w 192 -h 192 "$ICONS/icon.svg" -o "$ICONS/icon-192.png" +rsvg-convert -w 512 -h 512 "$ICONS/icon.svg" -o "$ICONS/icon-512.png" +rsvg-convert -w 512 -h 512 "$ICONS/icon-maskable.svg" -o "$ICONS/icon-maskable-512.png" +# iOS masks the home-screen icon itself; a full-bleed square is expected. +rsvg-convert -w 180 -h 180 "$ICONS/icon-maskable.svg" -o "$ICONS/apple-touch-icon.png" + +echo "icons ready in $ICONS" diff --git a/web/manifest.webmanifest b/web/manifest.webmanifest new file mode 100644 index 0000000..641be49 --- /dev/null +++ b/web/manifest.webmanifest @@ -0,0 +1,31 @@ +{ + "name": "Tavolo", + "short_name": "Tavolo", + "description": "Multiplayer card games: scopone, scopa and briscola.", + "id": "/", + "start_url": "/", + "scope": "/", + "display": "standalone", + "background_color": "#14341f", + "theme_color": "#14341f", + "icons": [ + { + "src": "/assets/icons/icon-192.png", + "sizes": "192x192", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/assets/icons/icon-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "any" + }, + { + "src": "/assets/icons/icon-maskable-512.png", + "sizes": "512x512", + "type": "image/png", + "purpose": "maskable" + } + ] +} diff --git a/web/src/main.rs b/web/src/main.rs index ed0c83a..2a9774c 100644 --- a/web/src/main.rs +++ b/web/src/main.rs @@ -4,6 +4,7 @@ mod auth; mod components; mod model; mod pages; +mod pwa; mod ws; use sycamore::prelude::*; @@ -91,5 +92,6 @@ fn main() { ) } }); + pwa::register(); restore_page_after_login(); } diff --git a/web/src/pwa.rs b/web/src/pwa.rs new file mode 100644 index 0000000..fa76d21 --- /dev/null +++ b/web/src/pwa.rs @@ -0,0 +1,20 @@ +//! Service worker registration. +//! +//! Registering `/sw.js` is what makes the app installable as a PWA; the +//! worker itself is install-only (no offline caching — see `web/sw.js`). +//! Registration is best-effort: browsers without service worker support, +//! and insecure origins other than localhost, simply skip it. +use wasm_bindgen_futures::{spawn_local, JsFuture}; + +/// Register the service worker, if the browser supports it. +pub fn register() { + let Some(window) = web_sys::window() else { + return; + }; + let container = window.navigator().service_worker(); + spawn_local(async move { + // Rejections (e.g. insecure origin) are ignored: the app works + // without a service worker, it just is not installable. + let _ = JsFuture::from(container.register("/sw.js")).await; + }); +} diff --git a/web/sw.js b/web/sw.js new file mode 100644 index 0000000..d576ed0 --- /dev/null +++ b/web/sw.js @@ -0,0 +1,34 @@ +// Tavolo service worker: installability only, no offline caching. +// +// The app is a thin client for a live game server: state arrives over +// /api and /ws and is never safe to replay from a cache, and a new build +// changes the hashed asset names, so stale cached files would break the +// app until the cache expired. The worker therefore only performs the +// passthrough fetch below — enough for the browser to treat the app as +// installable — and leaves every request's caching to the network stack. + +self.addEventListener("install", () => { + // A new worker takes over on the next reload instead of waiting for + // every tab of the old version to close. + self.skipWaiting(); +}); + +self.addEventListener("activate", (event) => { + event.waitUntil(self.clients.claim()); +}); + +self.addEventListener("fetch", (event) => { + const url = new URL(event.request.url); + // Let the browser handle other origins and the live endpoints directly + // (respondWith would only add a hop; /auth navigations must be allowed + // to follow their redirects untouched). + if ( + url.origin !== self.location.origin || + url.pathname.startsWith("/api/") || + url.pathname.startsWith("/auth/") || + url.pathname.startsWith("/ws") + ) { + return; + } + event.respondWith(fetch(event.request)); +});