Skip to content
Back to skills

Add Nav Page

ASecurity

Use when adding a new UI page to the trading journal (new nav entry + page-view + JS handler). Triggers on "add a Score Comparison page", "create a new analytics view", "wire up a new tool".

  • 3 stars
  • 0 votes
  • 0 copies
  • 1 view
  • Added May 27, 2026
data-aibashapifrontendsecurity

Works with

  • cli
  • api

Security analysis

A100/100

Scanned May 27, 2026

npx -y skills add anvilfilbert/Auto-Crypto-Tradingjournal --skill add-nav-page --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Add Nav Page?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Add Nav Page
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/anvilfilbert-add-nav-page/badge)](https://www.skillsdirectory.com/skills/anvilfilbert-add-nav-page)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: add-nav-page
description: Use when adding a new UI page to the trading journal (new nav entry + page-view + JS handler). Triggers on "add a Score Comparison page", "create a new analytics view", "wire up a new tool".
---

# Add a New UI Page

The frontend uses a single-page architecture: nav clicks call `showPage(name)`, which toggles `.active` on `.page-view` divs. State is in `currentPage`. Recent example (2026-05-24): Score Comparison page.

## Three-file pattern

| File | Change |
|---|---|
| `templates/index.html` | Add nav entry + `#page-<name>` div |
| `static/js/13-init.js` | Extend `showPage` switch to dispatch your loader |
| `static/js/<module>.js` | Implement loader + render functions |

## Reference implementation

The **Score Comparison page** (added 2026-05-24) is the clean reference:
- Nav entry: `templates/index.html` (search `nav-score-comparison`)
- Page div: `templates/index.html` (search `page-score-comparison`)
- showPage dispatch: `static/js/13-init.js:5+13` (extras list + loader call)
- Loader: `static/js/09-analysis.js::loadScoreComparison`
- API endpoint: `routes/analytics.py::api_score_comparison`

## Checklist

### 1. Decide section + icon
- Existing sections: Trading, AI-Trade, Manual-Trade, Analysis, Tools, Docs, Acki Nacki — DoDEX, System
- Choose an emoji icon (1 char, prefix the span).

### 2. Add nav entry
- File: `templates/index.html`
- Find the section's existing nav-item block.
- Add:
  ```html
  <div class="nav-item" onclick="showPage('<page-name>')" id="nav-<page-name>" data-section-of="<section-key>">
    <span class="nav-icon">⚖️</span><span>Display Name</span>
  </div>
  ```
- The `data-section-of` value matches the section's `data-section` (e.g., `analysis`, `tools`). Required for the collapsible-nav feature added 2026-05-24.

### 3. Add page-view div
- File: `templates/index.html`
- Find the location matching the section's other pages.
- Add:
  ```html
  <!-- ══════════════════════════════════════════════════════════════════ -->
  <!-- N. <SECTION>                                                       -->
  <!-- ══════════════════════════════════════════════════════════════════ -->
  <div id="page-<page-name>" class="page-view">
    <div class="page-title">⚖️ Display Name</div>
    <div class="page-subtitle">One-line description of the page</div>

    <div id="<page>-header" style="margin:16px 0;..."></div>
    <div id="<page>-content"></div>
  </div>
  ```
- Containers ONLY. No content. JS populates them on `showPage` dispatch.

### 4. Wire showPage dispatch
- File: `static/js/13-init.js`
- Add the page name to the `extras` array at the top.
- Add a dispatch line:
  ```js
  if (name === '<page-name>') { load<PageName>(); }
  ```

### 5. Implement the loader
- File: `static/js/09-analysis.js` (or a new module if scope justifies).
- Pattern:
  ```js
  async function load<PageName>(forceRefresh) {
    const header = document.getElementById('<page>-header');
    if (!header) return;
    header.textContent = '';
    // Loading state
    const loading = document.createElement('small');
    loading.style.color = 'var(--muted)';
    loading.textContent = '⧗ Loading…';
    header.appendChild(loading);

    try {
      const res = forceRefresh
        ? await api('/api/<path>/recompute', 'POST')
        : await api('/api/<path>');
      if (!res.ok) throw new Error(res.error || 'failed');
      _render<PageName>(res.data || {});
    } catch (e) {
      header.textContent = '';
      const err = document.createElement('small');
      err.style.color = 'var(--red)';
      err.textContent = 'Error: ' + e.message;
      header.appendChild(err);
    }
  }
  ```

### 6. Implement render helpers
- **ALWAYS use safe DOM methods (createElement + textContent)**. NEVER use innerHTML.
- The security hook blocks innerHTML edits — see Score Comparison's `_scRenderAggregates` for the pattern.
- For tables: build `<table>` → `<thead>` → `<tbody>` with appendChild chains, set `textContent` for cell values, set `style.cssText` for layout.

### 7. Bump JS cache version
- File: `templates/index.html`
- Find your module's `<script src="/static/js/XX-name.js?v=X.Y">` and bump to next minor.
- Also bump `13-init.js` cache version since you modified it.
- WITHOUT this bump, browsers will serve the cached old JS and your new page won't work.

### 8. Browser verification (mandatory per CLAUDE.md)
- Per CLAUDE.md: any deploy touching `static/js/*.js` or `templates/*.html` requires browser verification.
- Use Playwright (already installed). Reference: `/tmp/verify_*.py` scripts from past deploys.
- Verify: page renders, no console errors, no JS exceptions, content populates as expected.

### 9. Deploy
- Sync via `/tmp/deploy_audit.exp`
- Restart: `restart_pi.exp` (frontend only — no snapshot/config touch).
- Verify HTTP 200 + browser test.
- Backup `bash ~/trading-journal/scripts/backup_db.sh`.

## Red flags

- "I'll use innerHTML for the dynamic HTML" → stop. Security hook will block. Use createElement + textContent.
- "I won't bump the cache version" → stop. Browsers serve stale JS without it; nothing will work.
- "I'll skip the data-section-of attribute" → stop. Without it, the collapsible-nav feature breaks the new entry (item never hides on section collapse).
- "I'll wire showPage but forget to add to extras list" → stop. The dispatch only runs for items in `extras`. Falls through to `_origShowPage` otherwise.
- "I'll skip browser verification because it's a small change" → stop. JS rendering bugs are easy to introduce + hard to spot without rendering in a browser.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…