128 lines
5.8 KiB
Markdown
128 lines
5.8 KiB
Markdown
# mp3-com-meta-browser
|
|
|
|
mp3-com-meta-browser is a static single-page web app for exploring the salvaged mp3.com metadata catalog. All queries run entirely in the browser against a read-only SQLite database compiled to WebAssembly, so the site can be hosted on any static file server.
|
|
|
|
## Highlights
|
|
- Client-side full-text search (FTS5) across track titles, artists, albums, and genres.
|
|
- Responsive Bulma-based UI with dedicated views for search, browse (artists, albums, years, genres), and dataset stats.
|
|
- Overlay detail panels for artists, albums, and tracks with keyboard navigation support.
|
|
- Zero server dependencies beyond serving static assets with HTTP range support.
|
|
|
|
## Tech Stack
|
|
- Bulma (`bulma.min.css`) for layout and components.
|
|
- Vanilla JavaScript in `script.js` for SPA state management, view controllers, and data access helpers.
|
|
- `sql.js` WASM build (`sql-wasm.js` / `sql-wasm.wasm`) to run SQLite with FTS5 support in the browser.
|
|
- Local styling refinements in `site.css`.
|
|
- Metadata database delivered as `/assets/mp3com-meta.sqlite`.
|
|
|
|
## Directory Layout
|
|
```
|
|
/
|
|
├─ index.html # Single-page app shell and HTML templates
|
|
├─ bulma.min.css # Bundled Bulma CSS (do not modify upstream file)
|
|
├─ site.css # Local overrides and micro-utilities
|
|
├─ script.js # Application logic, helpers, and view controllers
|
|
├─ README.md # Project overview (this file)
|
|
├─ AGENTS.md # Orientation and guardrails for automation agents
|
|
└─ assets/
|
|
└─ mp3com-meta.sqlite # Read-only metadata database
|
|
```
|
|
Add future static assets (icons, fonts, etc.) under `assets/`.
|
|
|
|
## Running Locally
|
|
1. Start a static file server from the repository root. Examples:
|
|
- `python3 -m http.server 8000`
|
|
- `npx http-server -p 8000`
|
|
2. Ensure the server sends `Accept-Ranges: bytes` for `/assets/mp3com-meta.sqlite` so the WASM virtual file system can page data on demand.
|
|
3. Visit `http://localhost:8000/` in a modern browser.
|
|
4. Open the developer console to confirm there are no runtime errors.
|
|
|
|
## Using the App
|
|
- **Search:** Free-text search with 250 ms debounce. Toggle between relevance and alphabetical sorting. Keyboard: `/` focuses search, `Enter` activates the highlighted row.
|
|
- **Browse Artists / Albums / Years / Genres:** Paginated listings with quick filters (artists leverage FTS prefix queries for fast prefix matching). Selecting an entry opens the corresponding overlay.
|
|
- **Stats:** Summary cards pull from pre-computed counters in `site_stats` and link into browse views with preset filters.
|
|
- **Overlays:** Artist, album, and track overlays show detailed metadata. `Esc` closes the top overlay and focus returns to the invoker.
|
|
|
|
## Keyboard & Accessibility Notes
|
|
- Global shortcuts: `/` for search, `Esc` to close overlays.
|
|
- Lists expose arrow navigation with `Enter` activation when focused.
|
|
- Focus indicators remain visible; async list regions use polite `aria-live` messages.
|
|
- Ensure new UI follows Bulma semantics and pairs labels with inputs.
|
|
|
|
## Database Schema
|
|
The bundled database enforces foreign keys and ships with an FTS5 index over key text fields. The current schema is:
|
|
|
|
```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);
|
|
```
|
|
|
|
The `fts_tracks_*` tables are managed by SQLite to back the FTS5 virtual table. `site_stats` stores pre-computed counters that power the stats view. The application issues read-only queries and never mutates the database.
|
|
|
|
## Development Notes
|
|
- Keep the app framework-free; do not introduce bundlers or additional dependencies without discussion.
|
|
- Reuse HTML templates in `index.html` through the `instantiateTemplate` helper instead of building large DOM fragments manually.
|
|
- Paginate every query (`LIMIT ? OFFSET ?`) and prefer streaming or incremental rendering for large result sets.
|
|
- Consolidate shared UI logic (pagination, keyboard handlers, async states) in `script.js` utilities.
|
|
- Restrict new CSS to scoped utility classes in `site.css`; otherwise rely on Bulma components.
|
|
- Before submitting changes, verify there are no console warnings, layout adapts from mobile to desktop, and keyboard navigation continues to work.
|
|
|
|
## License
|
|
Add licensing information here when available.
|