--- name: static-site-development description: "Use when adding data-driven pages to a static site." version: 1.0.0 author: Hermes Agent license: MIT metadata: hermes: tags: [static-site, vanilla-js, html, nginx, tailwind, audio-player] related_skills: [gitea, proxmox-lxc-deployment] --- # static-site-development — Add Data-Driven Pages to Static Sites Use when building or extending a self-hosted static website with data-driven content (music libraries, download galleries, resource lists) where the content changes independently of the page markup. ## Core Pattern 1. **JSON manifest** (`library.json` or similar) — single source of truth for all content 2. **Vanilla JS rendering** — fetch the manifest, build DOM from it, no frameworks 3. **Folder-based assets** — organize by category/genre/type in subdirectories 4. **Match existing theme** — reuse the site's CSS framework, color tokens, nav, footer, dark/light toggle ## When to Use - Adding a new content section to an existing static site - Content that changes frequently (add/remove items without editing HTML) - Filterable lists (by genre, category, tag) - Media players (audio, video) with play + download actions - Any page where a hand-maintained HTML list would be painful ## When NOT to Use - Single static page with content that never changes — just write HTML - Sites that already use a framework (React, Vue, etc.) — use the framework's patterns - Pages requiring server-side rendering or auth — this is static-only ## Implementation Checklist 1. Read the existing site's index.html to extract: CSS framework, color tokens, nav structure, footer, theme toggle JS 2. Create the page shell: same `
`, same nav, same footer, same theme toggle 3. Design the manifest schema — minimal fields, only what the UI needs 4. Build the JS: fetch manifest → build filters → render list → bind interactions 5. Add the nav link to index.html 6. Verify: curl the page, check 200, check JS renders ## Common Patterns ### Genre/Category Filters - Filter buttons built dynamically from unique values in the manifest - "All" button always present, active by default - Click handler: set active genre, re-render visible items - Empty state when no items match ### Single Shared Media Player - One hidden `