diff --git a/.planning/todos/pending/2026-10-11-reload-open-apps-when-a-new-version-is-deployed.md b/.planning/todos/pending/2026-10-11-reload-open-apps-when-a-new-version-is-deployed.md new file mode 100644 index 0000000..a3a9678 --- /dev/null +++ b/.planning/todos/pending/2026-10-11-reload-open-apps-when-a-new-version-is-deployed.md @@ -0,0 +1,30 @@ +--- +created: 2026-10-10T23:04:41.663Z +title: Prompt open admin and site tabs to reload when a new version is deployed +area: framework +severity: minor +files: + - modules/boardwalk/boardwalk.go:110-133 + - admin/src/app/fieldTypes.ts + - admin/src/components/form/registry.ts +--- + +## Problem + +A browser tab opened before a deploy keeps running the old admin SPA bundle until the user reloads it by hand. On uat.grzybyfunkcjonalne.pl (2026-10-11) the post form showed "Unsupported field type: mlblogeditor" instead of the Blog Editor. The deployed binary (sha256 8a64d01…) and its embedded `modules/boardwalk/dist` were current. The old bundle ran against the new backend: it got a schema field type it didn't know and fell back to UnsupportedField. A reload fixed it. + +`index.html` is already served with `Cache-Control: no-store` (boardwalk.go:132), and hashed assets are long-lived. So HTTP caching isn't the gap. The gap is a long-lived open tab that never learns a new version exists. The SPA refreshes its JWT silently, so a tab can stay open for days. + +The same applies to: +- the Nuxt site apps (grzybyfunkcjonalne, journal layer), where Nitro and client chunks change per deploy; +- lazy chunks: after a deploy an old tab asking for a removed hashed chunk gets a 404 or a chunk-load error; +- plugin field-type scripts, which are already versioned with `?v=` hashes but load only once, after sign-in. + +## Solution + +TBD. Ideas: +- Expose a build version. Candidates: a response header on every admin API reply (e.g. `X-Summer-Build`, from the boardwalk dist hash plus the binary build info), or a small `/version` endpoint. +- The SPA records the version it booted with. It compares it on API responses and on `visibilitychange`/focus, or on an interval. On a mismatch it shows a non-blocking banner, "A new version is available — reload", and doesn't auto-reload, so unsaved form edits aren't lost. An auto-reload is acceptable only when no form is dirty. +- Catch dynamic-import/chunk-load failures (`vite:preloadError`) and reload once, guarded against loops by a sessionStorage flag. +- Nuxt apps: use the built-in `app:manifest:update` / `checkOutdatedBuildInterval` (Nuxt app manifest) and the same banner pattern. +- Unit-test the version comparison and the reload-once guard. Document the header or endpoint in the boardwalk README and docs.