# Site Audit Findings — Chrysopedia Live Site

**Audited:** 2026-04-03  
**Site URL:** http://ub01:8096  
**API Version:** v0.1.0  
**App Version:** v0.8.0 (Built 2026-04-03)

---

## Route Map Audit

All 12 frontend routes were visited in a live browser session. Every route rendered successfully with no JavaScript errors (except minor 422 warnings on admin pages from expected validation).

| # | Route | Page Title | Status | Notes |
|---|---|---|---|---|
| 1 | `/` | Chrysopedia — Production Knowledge, Distilled | ✅ Renders | Hero search, 3-step process cards, popular topics, footer with Topics/Creators cards |
| 2 | `/search?q=bass` | Search: bass — Chrysopedia | ✅ Renders | 20 results shown, sort dropdown (Relevance/Newest/Oldest/A-Z), tag/content match highlights |
| 3 | `/techniques/:slug` | Bass and Drum Design Fundamentals by COPYCATT — Chrysopedia | ✅ Renders | v2 body sections with ToC sidebar, citation superscripts, tag badges, plugin badges, key moments |
| 4 | `/creators` | Creators — Chrysopedia | ✅ Renders | Sort (Random/A-Z/Views), name filter, genre filter buttons (12 genres), creator cards with stats |
| 5 | `/creators/:slug` | COPYCATT — Chrysopedia | ✅ Renders | Avatar, video count, genre breakdown badges, technique list with sort. **Note:** Duplicate "Sound Design" badges due to inconsistent topic_category casing |
| 6 | `/topics` | Topics — Chrysopedia | ✅ Renders | 7 category cards with icons, sub-topic counts, expandable sections, topic filter input |
| 7 | `/topics/:cat/:sub` | Daw Setup — Workflow — Chrysopedia | ✅ Renders | Breadcrumb nav, category badge, creator-grouped technique cards, sort dropdown |
| 8 | `/about` | About — Chrysopedia | ✅ Renders | Static content: What Is, How Content Is Extracted (6-step pipeline), Who Maintains This |
| 9 | `/admin/reports` | Content Reports — Chrysopedia | ✅ Renders | Status filter tabs (All/Open/Acknowledged/Resolved/Dismissed), 0 reports currently |
| 10 | `/admin/pipeline` | Pipeline Management — Chrysopedia | ✅ Renders | 200 videos, status tabs (All/Queued/In Progress/Errored/Complete), recent activity feed, worker status, debug toggle, per-video actions (Retrigger/Revoke/Re-run Stage). **Note:** 422 warning from admin fetch |
| 11 | `/admin/techniques` | Admin — Technique Pages | ✅ Renders | 83 articles, 16 creators, table with title/creator/category/format/sources/versions/updated, multi-source filter, creator filter, sort. **Note:** 422 warning from admin fetch |
| 12 | `*` (fallback) | — | ✅ SPA fallback | Returns 200 with SPA shell; react-router handles unknown routes (redirects to `/`) |

### Visual Observations

- **Dark theme only** — no light mode toggle visible
- **Consistent nav bar** across all pages: Chrysopedia logo, global search (Ctrl+Shift+F), Home/Topics/Creators links, Admin dropdown
- **Footer** visible on all pages: version (v0.8.0), build date, GitHub link, About link
- **Mobile responsiveness** not tested in this audit (desktop viewport 1280×800 only)
- **No loading skeletons observed** — pages render fully or show empty states
- **Admin pages have no auth gate** — accessible without login (consistent with single-admin tool design)

---

## API Surface Audit

### Public Endpoints (10/10 verified)

| # | Endpoint | Method | Status | Response Shape | Notes |
|---|---|---|---|---|---|
| 1 | `/health` | GET | 200 ✅ | `{status, service, version, database}` | version="0.1.0", db=connected |
| 2 | `/api/v1/stats` | GET | 200 ✅ | `{technique_count, creator_count}` | 83 techniques, 26 creators |
| 3 | `/api/v1/search?q=bass` | GET | 200 ✅ | `{items, partial_matches, total, query, fallback_used}` | **Discrepancy:** Research listed `results` key; actual key is `items`. Has `partial_matches` array and `fallback_used` boolean |
| 4 | `/api/v1/search/suggestions?q=dr` | GET | 200 ✅ | `{suggestions: [{text, type}]}` | Returns technique name matches |
| 5 | `/api/v1/search/popular` | GET | 200 ✅ | `{items: [{query, count}]}` | Top searches with counts |
| 6 | `/api/v1/techniques?limit=2` | GET | 200 ✅ | `{items, total, offset, limit}` | Paginated, total=83 |
| 7 | `/api/v1/techniques/random` | GET | 200 ✅ | `{slug}` | **Discrepancy:** Research implied redirect; actually returns JSON `{slug: "..."}` |
| 8 | `/api/v1/techniques/{slug}` | GET | 200 ✅ | `{title, slug, topic_category, topic_tags, summary, body_sections, body_sections_format, signal_chains, plugins, id, creator_id, creator_name, creator_slug, source_quality, view_count, key_moment_count, created_at, updated_at, key_moments, creator_info, related_links, version_count, source_videos}` | Rich response with 22 fields |
| 9 | `/api/v1/techniques/{slug}/versions` | GET | 200 ✅ | `{items, total}` | Paginated version list |
| 10 | `/api/v1/techniques/{slug}/versions/{n}` | GET | — | Not probed | Requires known version number; endpoint structure confirmed from router |

### Browse Endpoints (5/5 verified)

| # | Endpoint | Method | Status | Response Shape | Notes |
|---|---|---|---|---|---|
| 1 | `/api/v1/creators` | GET | 200 ✅ | `{items, total, offset, limit}` | **Discrepancy:** total=25 (research said 26). Paginated dict, not bare list |
| 2 | `/api/v1/creators/{slug}` | GET | 200 ✅ | `{name, slug, genres, folder_name, id, avatar_url, view_count, created_at, updated_at, bio, social_links, featured, video_count, technique_count, techniques, genre_breakdown}` | 16 fields |
| 3 | `/api/v1/topics` | GET | 200 ✅ | `list[{name, description, sub_topics: [{name, technique_count, creator_count}]}]` | 7 categories. **Note:** Returns bare list, not paginated dict |
| 4 | `/api/v1/topics/{cat}/{sub}` | GET | 200 ✅ | `{items, total, offset, limit}` | Paginated technique list for subtopic |
| 5 | `/api/v1/topics/{cat}` | GET | 200 ✅ | `{items, total, offset, limit}` | Paginated technique list for category |

### Reports Endpoints (3/3 verified)

| # | Endpoint | Method | Status | Response Shape | Notes |
|---|---|---|---|---|---|
| 1 | `POST /api/v1/reports` | POST | 422 ✅ | Validation error (empty body) | Endpoint exists, expects report payload |
| 2 | `GET /api/v1/admin/reports` | GET | 200 ✅ | Report list | Returns 200 (no auth required) |
| 3 | `PATCH /api/v1/admin/reports/{id}` | PATCH | — | Not probed (destructive) | Confirmed from router source |

### Pipeline Admin Endpoints (spot-checked 5/20+)

| # | Endpoint | Method | Status | Response Shape | Notes |
|---|---|---|---|---|---|
| 1 | `GET /api/v1/admin/pipeline/debug-mode` | GET | 200 ✅ | `{debug_mode: true}` | Debug currently enabled |
| 2 | `GET /api/v1/admin/pipeline/worker-status` | GET | 200 ✅ | `{online, workers: [{name, active_tasks}]}` | 1 worker online with active pipeline task |
| 3 | `GET /api/v1/admin/pipeline/stale-pages` | GET | 200 ✅ | `{current_prompt_hash, total_pages, stale_pages, fresh_pages, stale_by_creator}` | 83/83 pages stale (prompt hash changed) |
| 4 | `GET /api/v1/admin/pipeline/recent-activity` | GET | 200 ✅ | `{items: [...]}` | Recent pipeline events |
| 5 | `GET /api/v1/admin/pipeline/videos` | GET | 200 ✅ | `{items, total, offset, limit}` | Paginated video list with pipeline status |

**Important:** Pipeline admin endpoints use `/api/v1/admin/pipeline/` prefix, NOT `/api/v1/pipeline/`. The research doc's path listing was correct but the prefix separation matters for Phase 2 integration.

### Other Endpoints (2/2 verified)

| # | Endpoint | Method | Status | Response Shape | Notes |
|---|---|---|---|---|---|
| 1 | `POST /api/v1/ingest` | POST | 422 ✅ | Validation error (empty body) | Endpoint exists, expects transcript payload |
| 2 | `GET /api/v1/videos` | GET | 200 ✅ | `list[{...}]` | Returns bare list (not paginated dict) |

---

## Discrepancies from Research

| # | Area | Research Said | Live Reality | Severity |
|---|---|---|---|---|
| 1 | Search response key | `results` | `items` (with additional `partial_matches`, `fallback_used`) | **Medium** — affects client integration |
| 2 | `/techniques/random` | Implied HTTP redirect | Returns JSON `{slug: "..."}` | **Low** — client handles either way |
| 3 | Creator count | 26 creators | 25 creators (from `/api/v1/creators`), but `/api/v1/stats` says 26 | **Low** — possible creator with 0 techniques excluded from browse endpoint |
| 4 | `/api/v1/topics` response | Implied dict | Returns bare list `[{name, description, sub_topics}]` | **Low** — affects typing |
| 5 | `/api/v1/videos` response | Not detailed | Returns bare list (not paginated dict) | **Low** — inconsistent with other endpoints |
| 6 | Admin pipeline prefix | Listed as 20+ endpoints | All under `/api/v1/admin/pipeline/` prefix, not `/api/v1/pipeline/` | **Medium** — prefix matters for routing |
| 7 | Creator detail genre badges | Expected clean categories | Duplicate "Sound Design" badges from inconsistent topic_category casing | **Low** — known data quality issue |

---

## Component Inventory Observations

### Nav Bar (all pages)
- Chrysopedia logo + link to `/`
- Global search input (`Ctrl+Shift+F` shortcut)
- Home, Topics, Creators nav links
- Admin dropdown (Pipeline, Techniques, Reports)

### Footer (all pages)
- Version display (v0.8.0)
- Build date (2026-04-03)
- GitHub link
- About link

### Page Components Confirmed
- **Home:** Hero section, search bar, 3-step process cards (with counter animation), popular topic tags, Topics/Creators feature cards, stats counters
- **SearchResults:** Search input, sort dropdown, result cards with tag/content match highlights, partial match section
- **TechniquePage:** Back link, title, category badge, creator link, metadata (sources, key moments, date), tags, plugin badges, v2 body sections with heading hierarchy, ToC sidebar, citation superscripts, key moments section
- **CreatorsBrowse:** Sort buttons (Random/A-Z/Views), name filter input, genre filter buttons, creator cards (avatar, name, technique/video/view counts, last updated)
- **CreatorDetail:** Avatar, creator name, video count, genre breakdown badges, technique list with sort
- **TopicsBrowse:** Topic filter input, category cards (icon, name, description, sub-topic count, technique count, expandable sub-topic lists)
- **SubTopicPage:** Breadcrumb (Topics > Category > SubTopic), category badge, technique count, sort dropdown, creator-grouped technique cards
- **About:** Static content sections with numbered pipeline step cards
- **AdminReports:** Status filter tabs, empty state ("No reports yet")
- **AdminPipeline:** Video count, orphaned pages warning, debug toggle, worker status, auto-refresh, recent activity feed, video list with status tabs, per-video actions
- **AdminTechniquePages:** Article/creator count, multi-source filter, creator filter, sort dropdown, technique table (title, creator, category, format badge, sources, versions, updated)

---

## Data Snapshot

| Metric | Value |
|---|---|
| Technique pages | 83 |
| Creators (stats) | 26 |
| Creators (browse) | 25 |
| Videos | 200 |
| Topic categories | 7 |
| Pipeline status | 148 queued, 3 in progress, 13 errored, 36 complete |
| Stale pages | 83/83 (prompt hash changed) |
| Workers | 1 online |
| Debug mode | Enabled |
| App version | v0.8.0 |
| API version | 0.1.0 |
| Content reports | 0 |

---

## Integration Notes for Phase 2

1. **Search API uses `items` key** (not `results`) — any new search integration must use this key
2. **Response shape inconsistency:** `/api/v1/topics` and `/api/v1/videos` return bare lists; all other list endpoints return paginated `{items, total, offset, limit}` dicts. New endpoints should follow the paginated pattern.
3. **No auth on any endpoint** — admin endpoints are fully open. Phase 2 should decide whether to add auth or continue with network-level access control.
4. **Pipeline actively running** — the worker is processing videos during audit. Any schema migrations or API changes need to coordinate with active pipeline runs.
5. **All technique pages are "stale"** — prompt hash has changed, meaning all 83 pages would be regenerated if bulk resynthesize is triggered. Consider freezing pipeline before major changes.
6. **Admin pages trigger 422s** — likely from fetching endpoints that require query params. These are benign but could mask real errors in browser console monitoring.
