mp3-com-meta-browser/AGENTS.md

7.5 KiB
Raw Permalink Blame History

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.
  • Reserve FTS (fts_tracks) for the free-text Track Search overlay; browse views should stick to indexed base tables to keep fan-out predictable.
  • 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 (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.
  • sqlValue, sqlLike, sqlIdentifier, and the sql template tag central helpers for manual SQL construction; always use these when interpolating dynamic values.

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

  • 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 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.