152 lines
7.2 KiB
Markdown
152 lines
7.2 KiB
Markdown
# Agent Guide
|
||
|
||
This document orients automation agents and contributors to the mp3-com-meta-browser project. The app is a static, single-page experience for browsing a large mp3.com metadata dataset entirely in the browser.
|
||
|
||
## Mission
|
||
- Deliver a fast, predictable search and browse experience over the bundled metadata database.
|
||
- Keep the implementation lightweight: no server-side code, no build system, minimal dependencies.
|
||
- Preserve accessibility, keyboard navigation, and responsive layout from mobile through desktop.
|
||
|
||
## Non-Goals
|
||
- Hosting or streaming audio files.
|
||
- Mutating the SQLite database (it's read-only at runtime).
|
||
- Introducing new frameworks, bundlers, or complex build steps.
|
||
|
||
## Runtime & Architecture
|
||
- `index.html` is the only HTML page and contains `<template>` definitions for base views (`tpl-*`) and overlay dialogs.
|
||
- `script.js` bootstraps the app, loads the WASM SQLite runtime, manages view transitions via `UX.replace(...)`, and handles overlays with `UX.openOverlay(...)` / `UX.closeTop()`.
|
||
- Bulma (`bulma.min.css`) supplies the UI vocabulary; project-specific tweaks live in `site.css`.
|
||
- The SQLite database (`assets/mp3com-meta.sqlite`) is fetched lazily using the HTTP virtual file system so only required pages are read.
|
||
- `sql.js` (bundled `sql-wasm.js` / `sql-wasm.wasm`) provides SQLite + FTS5 inside the browser.
|
||
|
||
## Key Assets
|
||
- `index.html` – SPA shell, templates, base structure.
|
||
- `script.js` – Application state, data layer, helpers, and view constructors.
|
||
- `site.css` – Minimal overrides, transitions, and utility classes.
|
||
- `assets/mp3com-meta.sqlite` – Read-only metadata database.
|
||
- `bulma.min.css` – Upstream Bulma build; keep pristine.
|
||
|
||
## Data Access Notes
|
||
- Expect to run entirely client-side; the database is opened with read-only mode via `sql.js`.
|
||
- Always page results with `LIMIT ? OFFSET ?`; avoid `SELECT *` unless fetching a single record by ID.
|
||
- Prefer prepared statements or cached query strings when querying repeatedly.
|
||
- HTTP servers used in development or deployment must send `Accept-Ranges: bytes` so the VFS can issue range requests.
|
||
|
||
## Database Schema
|
||
Use the current schema when writing queries or documentation:
|
||
|
||
```sql
|
||
PRAGMA foreign_keys=ON;
|
||
|
||
CREATE TABLE artists(
|
||
id INTEGER PRIMARY KEY,
|
||
name TEXT NOT NULL COLLATE NOCASE UNIQUE
|
||
);
|
||
|
||
CREATE TABLE albums(
|
||
id INTEGER PRIMARY KEY,
|
||
artist_id INTEGER NOT NULL REFERENCES artists(id),
|
||
title TEXT COLLATE NOCASE,
|
||
year INTEGER,
|
||
UNIQUE(artist_id, title, year)
|
||
);
|
||
|
||
CREATE TABLE tracks(
|
||
id INTEGER PRIMARY KEY,
|
||
artist_id INTEGER NOT NULL REFERENCES artists(id),
|
||
album_id INTEGER REFERENCES albums(id),
|
||
title TEXT NOT NULL COLLATE NOCASE,
|
||
track_no INTEGER,
|
||
year INTEGER,
|
||
genre TEXT,
|
||
duration_sec INTEGER,
|
||
bitrate_kbps INTEGER,
|
||
samplerate_hz INTEGER,
|
||
channels INTEGER,
|
||
filesize_bytes INTEGER,
|
||
sha1 TEXT,
|
||
relpath TEXT NOT NULL
|
||
);
|
||
|
||
CREATE TABLE site_stats (
|
||
name TEXT PRIMARY KEY,
|
||
value TEXT NOT NULL
|
||
);
|
||
|
||
CREATE VIRTUAL TABLE fts_tracks USING fts5(
|
||
title,
|
||
artist,
|
||
album,
|
||
genre,
|
||
content='tracks',
|
||
content_rowid='id',
|
||
tokenize='unicode61 remove_diacritics 2',
|
||
prefix='2 3 4'
|
||
);
|
||
|
||
CREATE TABLE 'fts_tracks_data'(id INTEGER PRIMARY KEY, block BLOB);
|
||
CREATE TABLE 'fts_tracks_idx'(segid, term, pgno, PRIMARY KEY(segid, term)) WITHOUT ROWID;
|
||
CREATE TABLE 'fts_tracks_docsize'(id INTEGER PRIMARY KEY, sz BLOB);
|
||
CREATE TABLE 'fts_tracks_config'(k PRIMARY KEY, v) WITHOUT ROWID;
|
||
|
||
CREATE INDEX idx_tracks_artist_id ON tracks(artist_id);
|
||
CREATE INDEX idx_tracks_album_id ON tracks(album_id);
|
||
CREATE INDEX idx_tracks_year ON tracks(year);
|
||
CREATE INDEX idx_tracks_genre ON tracks(genre);
|
||
CREATE INDEX idx_artists_name ON artists(name COLLATE NOCASE);
|
||
CREATE INDEX idx_artists_name_nocase ON artists(name COLLATE NOCASE);
|
||
```
|
||
|
||
`site_stats` stores pre-computed metrics that power the stats dashboard. The FTS data tables are SQLite internals; do not query them directly.
|
||
|
||
## UI/UX Conventions
|
||
- Stick to semantic HTML with Bulma classes; avoid inline styles.
|
||
- Maintain clear focus states and keyboard navigation. `/` focuses search, `Esc` closes the active overlay, and list views support arrow + Enter activation.
|
||
- Use polite `aria-live` regions for async loading states (see `createAsyncListState`).
|
||
- Keep DOM renders incremental—do not preload entire datasets or render long tables without pagination.
|
||
|
||
## Shared Utilities (already implemented in `script.js`)
|
||
- `createTableRenderer` – Safely renders tabular data with built-in HTML escaping.
|
||
- `createPagination` – Standard pagination controls with page size selector.
|
||
- `Keyboard` helper – Normalizes Enter/Esc handling for list rows and overlays.
|
||
- `createAsyncListState` – Manages loading, error, and empty states for async lists.
|
||
- `prepareForView` – Wraps `db.prepare` to attach view/label metadata for logging.
|
||
- `normalizePaginationState` / `clampPaginationToTotal` – Normalizes and clamps pagination inputs while emitting DEBUG telemetry.
|
||
|
||
## Debugging & Logging
|
||
- Runtime diagnostics are gated behind a localStorage flag. Enable with `localStorage.setItem('mp3com.debug', 'true')` (or `'false'`/`removeItem` to disable) before reloading the app.
|
||
- When DEBUG is on, every SQLite statement logs `Query begin`/`Query end` entries (with view, SQL, params, row count, and duration) and captures detailed error payloads before rethrowing.
|
||
- Pagination helpers emit `[Pagination]` logs whenever raw inputs are normalized or clamped (including `clampedToTotal` flags when high page numbers are corrected after a count query).
|
||
- Use `prepareForView(db, VIEW_NAMES.someView, sql, label)` so statement metadata matches the originating view; this keeps console traces actionable.
|
||
|
||
## View Status
|
||
- [x] Navigation hub (`tpl-nav`, `createNavView`).
|
||
- [x] Search (`tpl-search`).
|
||
- [x] Browse Artists (`tpl-browse-artists`).
|
||
- [x] Browse Albums (`tpl-browse-albums`).
|
||
- [x] Browse Years (`tpl-browse-years`).
|
||
- [x] Browse Genres (`tpl-browse-genres`).
|
||
- [x] Stats (`tpl-stats`).
|
||
- [x] Artist overlay (`tpl-artist`).
|
||
- [x] Album overlay (`tpl-album`).
|
||
- [x] Track overlay (`tpl-track`).
|
||
- [ ] Filters overlay (`tpl-filters`).
|
||
- [ ] Keyboard shortcuts overlay (`tpl-keyboard-shortcuts`).
|
||
- [ ] About / help overlay (`tpl-about`).
|
||
- [ ] Error overlay (`tpl-error`).
|
||
|
||
## Implementation Guardrails
|
||
- Keep JavaScript modular inside `script.js`; annotate non-obvious sections with short explanatory comments when necessary.
|
||
- Reuse existing helpers before adding new ones.
|
||
- Store new assets under `assets/` and prefer lazy loading.
|
||
- Do not modify `bulma.min.css`; override in `site.css` if required.
|
||
- Maintain ASCII-only sources unless a file already contains UTF-8 text that requires preservation.
|
||
|
||
## QA Checklist Before Delivery
|
||
- Serve the site via a local static server and load `http://localhost:8000/`.
|
||
- Confirm the console is clean (no errors or unhandled promise rejections).
|
||
- Verify keyboard navigation (Tab, arrow keys, Enter, Esc) across base views and overlays.
|
||
- Exercise search and pagination to ensure queries remain performant (< ~300 ms after warm-up).
|
||
- Validate layout on both narrow and wide viewports.
|
||
|
||
Stay within these constraints to keep the project fast, accessible, and easy to host.
|