# Nav Consistency Pattern (Jul 12, 2026) ## Principle All portal pages must load nav from `/nav.html` — the single source of truth for nav links, hamburger toggle, and nav CSS. The only exception is index.html (dashboard), which keeps an inline nav that matches nav.html link-for-link. ## Current state (post-Jul 12 fix) | Page | Nav source | Status | |------|-----------|--------| | index.html | Inline (matches nav.html) | OK — all 11 links + hamburger | | services.html | Fetched | OK | | servers.html | Fetched | OK | | backups.html | Fetched | OK | | audit.html, cost.html, cron.html, network.html, config.html, logs.html | Fetched | OK | ## Conversion procedure (inline → fetched) 1. **Replace the `` block** with `
`. 2. **Move `initNav()` into the fetch callback.** The old pattern of calling `window.initNav()` before the nav HTML is injected is a race condition — it tries to wire up toggle listeners on elements that don't exist yet: ```javascript // WRONG (initNav runs before nav HTML exists): window.initNav(); // ... later ... fetch('/nav.html')... // RIGHT (initNav runs AFTER nav HTML is injected): fetch('/nav.html').then(function(r) { return r.text(); }).then(function(h) { document.getElementById('nav').innerHTML = h; if (typeof window.initNav === 'function') window.initNav(); }).catch(function(e) { console.warn('Nav failed:', e); }); ``` 3. **Keep `window.initNav()`** — never use `Ops.initNav()` or bare `initNav()` inside a strict-IIFE. The nav init function is exported on `window` in `app.js`/`utils.js`. ## Index.html: inline nav maintenance The dashboard keeps inline nav. When `/nav.html` gains or loses links, update index.html's inline nav to match. Key elements: - `class="nav-logo-text"` on the brand span - Hamburger toggle: `