mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-09 04:50:59 +00:00
The resolved per-user module map rides the client-only `/api/auth/me` query, so it is still undefined on SSR and the first client paint. The nav model's module gate fails open (`modules?.[key] !== false`), so every module-gated entry — cycle, mood, labs, coach, insights … — rendered for one frame before the query resolved and filtered it out. A user without a module saw its entry flash into the sidebar and the mobile bar, then vanish. Gate the module-dependent filtering behind `useMounted()` in both bars. SSR and the first client paint now render only the core (non-module-gated) destinations; the real module map applies once mounted. Before mount a gated entry is treated as hidden — fail-closed — so SSR and first paint are identical (no hydration mismatch) and a disabled module can never flicker in. The pure nav-model helpers keep their fail-open default for callers that pass a settled map; the bars thread the mounted flag in. Rework the sidebar and bottom-nav SSR tests to assert the fail-closed first-paint contract (core-only, gated entries absent regardless of the map); the resolved post-mount set stays covered by the pure-helper tests in nav-model.test.ts and by e2e.