Initial skills documentation — 25 categories, all SKILL.md + references + scripts
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
# Nav Consistency Fix — July 12, 2026
|
||||
|
||||
## Problem
|
||||
Multiple ops portal pages had erratic behavior on mobile — hamburger menu didn't work, nav links were missing or stale, some pages showed no data.
|
||||
|
||||
## Root Causes Found (3 issues)
|
||||
|
||||
### 1. Mixed nav strategies — inline vs fetched
|
||||
Some pages had the nav hardcoded inline in the HTML, while others fetched `/nav.html` dynamically. The inline navs were stale — missing Audit, Costs, and Grafana links. The fetched navs were always up to date.
|
||||
|
||||
**Fix:** Every page should use:
|
||||
```html
|
||||
<div id="nav"></div>
|
||||
```
|
||||
And fetch nav at the bottom of the page script:
|
||||
```javascript
|
||||
fetch('/nav.html').then(r => r.text()).then(html => {
|
||||
document.getElementById('nav').innerHTML = html;
|
||||
if (typeof window.initNav === 'function') window.initNav();
|
||||
});
|
||||
```
|
||||
|
||||
Pages affected: backups.html, servers.html, services.html (all had inline navs that were replaced)
|
||||
|
||||
### 2. `Ops.initNav()` vs `window.initNav()` — TypeError kills nav
|
||||
The `initNav` function is defined in utils.js as `window.initNav`, NOT as `Ops.initNav`. Pages calling `Ops.initNav()` throw a ReferenceError that kills ALL JavaScript execution on the page — including the data loading and rendering code.
|
||||
|
||||
**Fix:** Replace all `Ops.initNav()` with `window.initNav()`:
|
||||
```javascript
|
||||
// BROKEN:
|
||||
Ops.initNav();
|
||||
// FIXED:
|
||||
if (typeof window.initNav === 'function') window.initNav();
|
||||
```
|
||||
|
||||
Pages affected: index.html, backups.html, servers.html, services.html
|
||||
|
||||
### 3. CSS/JS MIME types — wrong content-type kills scripts
|
||||
The backend (FastAPI FileResponse) and Caddy reverse proxy served JS and CSS files with `Content-Type: application/json`. Browsers refuse to execute scripts or apply stylesheets with the wrong MIME type.
|
||||
|
||||
**Root causes:**
|
||||
- FastAPI's `FileResponse()` without explicit `media_type` parameter sometimes resolves `.js` files as `application/json`
|
||||
- Caddy `handle_path /js/*` block was nested inside another `handle_path` block by accident (sed nesting bug)
|
||||
- File permissions were `600` (root-only) — Caddy returned 403, browser silently failed
|
||||
|
||||
**Fix — Caddy approach (most reliable):**
|
||||
```caddy
|
||||
ops.itpropartner.com {
|
||||
handle_path /data/* {
|
||||
root * /var/www/ops/data/
|
||||
file_server
|
||||
}
|
||||
handle_path /js/* { # ← TOP LEVEL
|
||||
root * /opt/ops-portal/static/js
|
||||
file_server
|
||||
}
|
||||
handle_path /css/* { # ← TOP LEVEL
|
||||
root * /opt/ops-portal/static/css
|
||||
file_server
|
||||
}
|
||||
reverse_proxy 127.0.0.1:8090
|
||||
}
|
||||
```
|
||||
|
||||
**Plus fix file permissions:** `chmod 644 /opt/ops-portal/static/js/*.js /opt/ops-portal/static/css/*.css`
|
||||
|
||||
**Verification:**
|
||||
```bash
|
||||
curl -sI https://ops.itpropartner.com/js/app.js | grep -i content-type
|
||||
# Expected: text/javascript; charset=utf-8
|
||||
|
||||
for page in / /services.html /servers.html /backups.html /audit.html /cost.html; do
|
||||
echo "$page → $(curl -sS -o /dev/null -w '%{http_code}' https://ops.itpropartner.com$page)"
|
||||
done
|
||||
# All should return 200
|
||||
```
|
||||
|
||||
## Prevention Checklist
|
||||
- Every new page: use `<div id="nav"></div>` + fetch pattern, never inline nav
|
||||
- Every new page: call `window.initNav()` (not `Ops.initNav()`) inside the fetch callback
|
||||
- After any Caddy config change: verify `handle_path` blocks are top-level, not nested
|
||||
- After adding any new static file: `chmod 644`
|
||||
- After any static file change: test with `curl -sI` to verify MIME type
|
||||
Reference in New Issue
Block a user