6.3 KiB
6.3 KiB
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 viaUX.replace(...)
, and handles overlays withUX.openOverlay(...)
/UX.closeTop()
.- Bulma (
bulma.min.css
) supplies the UI vocabulary; project-specific tweaks live insite.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
(bundledsql-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 ?
; avoidSELECT *
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:
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 (seecreateAsyncListState
). - 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.
View Status
- Navigation hub (
tpl-nav
,createNavView
). - Search (
tpl-search
). - Browse Artists (
tpl-browse-artists
). - Browse Albums (
tpl-browse-albums
). - Browse Years (
tpl-browse-years
). - Browse Genres (
tpl-browse-genres
). - Stats (
tpl-stats
). - Artist overlay (
tpl-artist
). - Album overlay (
tpl-album
). - 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 insite.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.