A regression from #395, live on demo.ihasmail.com. Production isn't affected, because its root is the app.
What goes wrong.
Since #395 the service worker answers app routes from its kept page.
It kept whatever the mount's root returned at install time, and whatever HTML any navigation returned.
On the demo, the root is the landing page, so from their second load on, a visitor got the landing page on every route.
Reproduced locally with a stand-in front door (landing at /, the demo container behind it): first load showed the inbox, the reload showed the landing page.
The fix (web/public/sw.js):
Recognising the app page: by the asset list the build writes into it (id="ihasmail-assets", from #394). No other page is kept.
Install: fetches /mail for the kept page instead of /.
Navigations: only the app's own routes (/mail, /search, /contacts, /calendar, /files, /settings, /admin, /login) are answered from the kept page. The root and any page in front of the app go to the network, as before #395.
Activation: a kept page that isn't the app page is dropped, which repairs browsers that already cached the landing page.
staleBuild.ts: the reload for a new build primes the kept page from /mail, and only with the app page.
Verified locally, upgrading in place in one browser profile from the broken image to the fixed one:
the first load after the swap was still served by the old worker;
after that, three reloads each showed the inbox (25 rows);
/ showed the landing page, /goodbye the farewell page, and /contacts the app.
Tests: web tests 1,371 pass; typecheck and build are clean. sw.js has no unit tests, so the check above is its test.
**A regression from #395, live on demo.ihasmail.com.** Production isn't affected, because its root is the app.
**What goes wrong.**
- Since #395 the service worker answers app routes from its kept page.
- It kept whatever the mount's root returned at install time, and whatever HTML any navigation returned.
- On the demo, the root is the landing page, so from their second load on, a visitor got the landing page on every route.
- Reproduced locally with a stand-in front door (landing at `/`, the demo container behind it): first load showed the inbox, the reload showed the landing page.
**The fix (`web/public/sw.js`):**
- **Recognising the app page:** by the asset list the build writes into it (`id="ihasmail-assets"`, from #394). No other page is kept.
- **Install:** fetches `/mail` for the kept page instead of `/`.
- **Navigations:** only the app's own routes (`/mail`, `/search`, `/contacts`, `/calendar`, `/files`, `/settings`, `/admin`, `/login`) are answered from the kept page. The root and any page in front of the app go to the network, as before #395.
- **Activation:** a kept page that isn't the app page is dropped, which repairs browsers that already cached the landing page.
- **`staleBuild.ts`:** the reload for a new build primes the kept page from `/mail`, and only with the app page.
**Verified locally**, upgrading in place in one browser profile from the broken image to the fixed one:
- the first load after the swap was still served by the old worker;
- after that, three reloads each showed the inbox (25 rows);
- `/` showed the landing page, `/goodbye` the farewell page, and `/contacts` the app.
**Tests:** web tests 1,371 pass; typecheck and build are clean. `sw.js` has no unit tests, so the check above is its test.
No new UI strings.
**Merged** 2026-09-16 as coffey-labs/ihasmail@2740129c6a39
<sub>Rebuilt from: git history, session transcript.</sub>
This repo is archived. You cannot comment on issues.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
A regression from #395, live on demo.ihasmail.com. Production isn't affected, because its root is the app.
What goes wrong.
/, the demo container behind it): first load showed the inbox, the reload showed the landing page.The fix (
web/public/sw.js):id="ihasmail-assets", from #394). No other page is kept./mailfor the kept page instead of/./mail,/search,/contacts,/calendar,/files,/settings,/admin,/login) are answered from the kept page. The root and any page in front of the app go to the network, as before #395.staleBuild.ts: the reload for a new build primes the kept page from/mail, and only with the app page.Verified locally, upgrading in place in one browser profile from the broken image to the fixed one:
/showed the landing page,/goodbyethe farewell page, and/contactsthe app.Tests: web tests 1,371 pass; typecheck and build are clean.
sw.jshas no unit tests, so the check above is its test.No new UI strings.
Merged 2026-09-16 as coffey-labs/ihasmail@2740129c6a
Rebuilt from: git history, session transcript.