From 1cb379add06528ddc529f112c7afc3a5784c416f Mon Sep 17 00:00:00 2001 From: Nicolas Dreno Date: Fri, 6 Nov 2026 13:48:33 +0100 Subject: [PATCH] fix(pwa): let docs navigations past the service worker The mdBook docs are deployed under /werb/docs/, inside the PWA service worker's /werb/ scope. Workbox answers every unknown navigation with the precached index.html, and the docs are copied into dist/ after the Vite build so they are never precached: once a browser had opened the app, every docs URL (README, issues, CLI help links) showed the app instead. navigateFallbackDenylist now excludes docs/ so those navigations go to the network. Browsers with the old worker get the fix after accepting the next update. Tests: e2e drives the production bundle, waits for the worker to control the page, then loads a page under docs/ (fails without the fix: the app shell comes back). --- CHANGELOG.md | 4 ++++ apps/desktop/test/e2e/pwa.spec.ts | 31 +++++++++++++++++++++++++++++++ apps/desktop/vite.config.ts | 6 +++++- 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 apps/desktop/test/e2e/pwa.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index bb1acc5..2344592 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,10 @@ follow [Semantic Versioning](https://semver.org/spec/v2.0.0.html). ### Fixed +- **Docs links open the docs on the web.** Once the web app had been opened, + links to the [documentation](https://werb-dev.github.io/werb/docs/) showed + the app instead. A browser that already has the app picks up the fix with + the next update (*Reload* on the "New version available" banner). - **Library cards show OG, FG, ABV, IBU and color for every recipe** ([#49](https://github.com/werb-dev/werb/issues/49)). A card used to show "—" for any figure the recipe file didn't state (e.g. ABV on an imported BeerXML diff --git a/apps/desktop/test/e2e/pwa.spec.ts b/apps/desktop/test/e2e/pwa.spec.ts new file mode 100644 index 0000000..589f012 --- /dev/null +++ b/apps/desktop/test/e2e/pwa.spec.ts @@ -0,0 +1,31 @@ +import { mkdirSync, rmSync, writeFileSync } from "node:fs"; +import { fileURLToPath } from "node:url"; +import { expect, test } from "@playwright/test"; + +/** + * Service worker scope. The mdBook docs are deployed under the app's + * `docs/`, inside the service worker's scope; they must load as docs, + * not as the app shell. + */ + +const docsDir = fileURLToPath(new URL("../../dist/docs/", import.meta.url)); +const probe = `${docsDir}e2e-probe.html`; + +test.beforeAll(() => { + mkdirSync(docsDir, { recursive: true }); + writeFileSync(probe, "Werb docs probe

Docs probe

"); +}); + +test.afterAll(() => { + rmSync(probe, { force: true }); +}); + +test("docs pages load once the app's service worker controls the site", async ({ page }) => { + await page.goto("/"); + await page.evaluate(() => navigator.serviceWorker.ready); + await page.reload(); + expect(await page.evaluate(() => navigator.serviceWorker.controller !== null)).toBe(true); + + await page.goto("/docs/e2e-probe.html"); + await expect(page).toHaveTitle("Werb docs probe"); +}); diff --git a/apps/desktop/vite.config.ts b/apps/desktop/vite.config.ts index 8f37e89..5615605 100644 --- a/apps/desktop/vite.config.ts +++ b/apps/desktop/vite.config.ts @@ -33,6 +33,7 @@ function gitCommit(): string { } const COMMIT = gitCommit(); const BUILD_DATE = new Date().toISOString().slice(0, 10); +const BASE = process.env.VITE_BASE ?? "/"; // Vite config tuned for Tauri 2: fixed dev port, no auto-clear of stderr, // HMR over the host Tauri injects, and exclusion of the Rust build dir from @@ -43,7 +44,7 @@ const BUILD_DATE = new Date().toISOString().slice(0, 10); // • GitHub Pages deploy: base="/werb/" (CI sets VITE_BASE=/werb/) // • custom domain on Pages: base="/" (CI sets VITE_BASE=/) export default defineConfig({ - base: process.env.VITE_BASE ?? "/", + base: BASE, define: { __APP_VERSION__: JSON.stringify(pkg.version), __APP_COMMIT__: JSON.stringify(COMMIT), @@ -110,6 +111,9 @@ export default defineConfig({ // bumping so it's precached alongside everything else. maximumFileSizeToCacheInBytes: 5 * 1024 * 1024, globPatterns: ["**/*.{js,css,html,wasm,woff,woff2,png,svg,webmanifest}"], + // The mdBook docs are deployed under docs/, inside this + // worker's scope: navigations there go to the network, not the app shell. + navigateFallbackDenylist: [new RegExp(`^${BASE}docs(/|$)`)], }, }), ],