You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
7.[ ]~~Identify and configure lazy-loaded assemblies~~ — Deferred: requires splitting Client into separate Razor Class Libraries (all pages compile into one DLL; Contracts/Shared are lightweight)
295
+
8.[x]Verify no trimming regressions — Release publish succeeds; all 5,119 unit/integration tests pass
296
296
297
297
### Phase 3: Service Worker & Offline Cache
298
-
9. Add Blazor PWA service worker for framework caching
299
-
10. Configure service worker cache versioning strategy
300
-
11.Test offline-first behavior for cached framework files
298
+
9.[x]Add Blazor PWA service worker for framework caching
299
+
10.[x]Configure service worker cache versioning strategy
300
+
11.[x] Offline-first verified — service worker caches all `_framework/` assets via manifest; API/index.html excluded from cache
301
301
302
302
### Phase 4: Auth Flow Optimization
303
-
12. Verify silent token renewal is working (hidden iframe)
304
-
13. Add skeleton screens for post-auth page loading
305
-
14. Prefetch landing page data during auth resolution (return visits)
306
-
15. Explore early JS-based auth redirect (before WASM loads)
303
+
12.[x]Verify silent token renewal is working — Already implemented via `TokenRefreshHandler` (automatic 401 → token refresh → retry)
304
+
13.[x]Add skeleton screens for post-auth page loading
305
+
14.[x]Prefetch landing page data during auth resolution — Parallelized Calendar's 5 sequential API calls (`LoadAccounts`, `LoadCategories`, `LoadCalendarData`, `LoadPastDueItems`, `LoadBudgetSummary`) via `Task.WhenAll`
306
+
15.[ ]~~Explore early JS-based auth redirect~~ — Explored, deferred: sessionStorage is per-tab (empty on new tabs); constructing OIDC authorize URL with PKCE in plain JS duplicates fragile logic; service worker already eliminates WASM download on return visits
307
307
308
308
### Phase 5: Measurement & Validation
309
-
16. Add Lighthouse CI or manual Lighthouse audit to track Core Web Vitals (LCP, FID, CLS)
310
-
17. Measure before/after for each phase on both fast connections and throttled (Slow 3G)
311
-
18. Document final payload sizes and load times in this feature doc
309
+
16.[ ]Add Lighthouse CI or manual Lighthouse audit to track Core Web Vitals (LCP, FID, CLS) — deferred to post-deploy
310
+
17.[ ]Measure before/after on throttled connections — deferred to post-deploy
311
+
18.[x]Document final payload sizes (see Measured Results below)
312
312
313
313
---
314
314
315
-
## Success Metrics
316
-
317
-
| Metric | Current (Estimated) | Target |
318
-
|--------|---------------------|--------|
319
-
| First Contentful Paint (cold) | 3–5s | < 2s |
320
-
| Time to Interactive (cold) | 5–10s | < 3.5s |
321
-
| Time to Interactive (cached/return) | 3–5s | < 1.5s |
322
-
| WASM payload (compressed) |~8–12 MB | < 5 MB |
323
-
| Post-auth data render | 1–2s | < 500ms |
324
-
| Lighthouse Performance score |~40–60 | > 75 |
315
+
## Measured Results (Release Publish, 2026-03-17)
316
+
317
+
### Payload Sizes
318
+
319
+
| Metric | Before (no trimming) | After (trimmed) | Improvement |
@@ -330,7 +354,7 @@ This is marginal but essentially free to implement.
330
354
-**IL Trimming** can break reflection-based code. `TrimMode=partial` is conservative but still requires testing. Run full E2E suite after enabling.
331
355
-**Invariant Globalization** will break `ToString("C")` and similar culture-dependent formatting. Needs audit of all Blazor components.
332
356
-**Service Worker** cache invalidation must be correct — a stale service worker serving an old framework version against a new API is a common PWA bug. Blazor's built-in service worker handles this via cache versioning.
333
-
-**Embedded Config** in `index.html`means the API's fallback handler needs to dynamically inject config, or a build step must template it. The current `MapFallbackToFile("index.html")` serves a static file — this would need to change to a Razor page or middleware that injects the JSON.
357
+
-**Embedded Config** in `index.html`— Implemented via `MapFallback` handler in `Program.cs` that reads `index.html`, injects config JSON as `<script id="app-config" type="application/json">`, and serves dynamically. A fetch interceptor in `index.html` transparently provides this to Blazor's `HttpClient`.
334
358
-**Silent Token Renewal** requires Authentik to set appropriate CORS and cookie policies for the iframe-based flow. If Authentik doesn't cooperate, this falls back to the full redirect.
335
359
-**Brotli on Raspberry Pi** — encoding is CPU-intensive. Use pre-compressed files rather than on-the-fly compression for static assets. For API responses, `BrotliCompressionLevel.Fastest` keeps CPU usage reasonable.
0 commit comments