Import a Spotify, Last.fm, Apple Music, ListenBrainz or YouTube archive, and optionally attach a private MusicBee library snapshot. Nova Music Lab processes selected files in the browser and turns evidence into timelines, obsessions, emotional maps, cultural journeys, generative identity and shareable reports.
Current public version: 1.5.0 β deployed 2026-08-01. The Living Archive Gets a Face removes invalid artist-image placeholders, clarifies genre and snapshot provenance, bounds archive imports and polishes mobile, keyboard and Hebrew RTL journeys.
Engineering evidence: React 19 Β· TypeScript Β· Vite Β· Dexie/IndexedDB Β· Web Workers Β· 710 passing Vitest tests with 1 intentional private-fixture skip Β· 18/18 Playwright journeys Β· EN/ES/HE RTL Β· protected GitHub Pages CI. IndexedDB schema revision 4 is a storage contract, not the product version.
Explore the live flagship Β· Read the architecture Β· Follow the product roadmap
- Open the live flagship and enter the museum.
- Start in Explore, the visual default; switch to Guided whenever you want plain-language context.
- Open Atlas to explore artists, media and archive evidence.
- Switch to Deep Dive when you want methodology and provenance.
- In
1.2.0β deployed 2026-07-29 β Share & Feedback prepares a WhatsApp invitation and Audio Lab previews a permitted local audio file without uploading it. - In
1.4.0β deployed 2026-07-29 β a guest can add an optional local museum name, import compatible files and compare the resulting private museum directly with Kevin's public exhibition. - In
1.5.0β deployed 2026-08-01 β portrait fallbacks, genre evidence, snapshot dates and bounded local imports become easier to trust.
No account is required for the public exhibition or local archive import.
These captures document the frozen source that became 1.5.0 β deployed
2026-08-01. They were generated and source-fingerprinted while that source was
still a private candidate, then reviewed before promotion. The live
build-meta.json
is the authoritative deployment identity.
A welcoming mobile entrance β Spanish copy and controls remain readable at 390 px. |
Genres without clipping β the deep link, tabs and evidence chart fit the mobile viewport. |
A museum your friends can make their own β no account is required to name a local museum, import compatible files and begin a private comparison.
Three rooms, one story β Home β Atlas β Genres shows how the invitation becomes evidence; reduced-motion readers receive a static frame.
One system across contexts β mobile, Hebrew RTL and a light theme use the same information architecture.
Streaming platforms usually reduce years of listening to a short recap. Nova Music Lab treats an archive as a personal cultural artifact: something to investigate, revisit and interpret without surrendering the raw history to another analytics backend.
The project is built around four commitments:
- Evidence before spectacle. Unknown information remains unknown; estimates and interpretations must be distinguishable from observed facts.
- Local-first ownership. Visitor-selected archives are parsed and stored in the browser.
- Source awareness. Each provider exposes different fields, so rooms only claim capabilities their active archive can support.
- A museum, not a spreadsheet. Motion, sound-inspired art, narrative and exploration make the evidence emotionally legible.
| Mode | Purpose | Data boundary |
|---|---|---|
| Flagship Exhibition | A curated demonstration of Kevin's personal music museum and Nova's full visual language. | A reviewed aggregate dataset is intentionally published with the static site and governed by public_dataset_manifest.json. |
| My Museum | A visitor imports supported exports and rebuilds the quantitative museum from the active archive. | Raw files stay in the browser; the app does not upload them to a Nova Music Lab server. |
1.4.0 β deployed 2026-07-29 β makes My Museum a clear
Guest Museum journey. A visitor may add an optional browser-local display name,
but that label is not a login, password or public account. Compare Museums loads
the reviewed public artist catalog only when needed and labels older
top-list-only datasets as partial instead of overstating their overlap.
The evidence-first milestone, completed in 1.0.0 β published 2026-07-16 and now superseded β formalized this boundary everywhere: flagship-only stories must never masquerade as visitor-derived analysis, and every interpretive room must disclose its evidence level.
| Source | Supported export | Strongest evidence | Role |
|---|---|---|---|
| Last.fm | CSV export | Long chronology, scrobbles, sessions and streaks | Event timeline |
| Spotify | Extended Streaming History JSON | Duration, platforms, country, skips and short plays | Event timeline |
| Apple Music | Play Activity.csv |
Apple listening activity and playback history | Event timeline |
| ListenBrainz | Listen JSON export | Open timestamped listening records | Event timeline |
| YouTube / YouTube Music | Google Takeout JSON or HTML history | Music video and YouTube Music activity | Event timeline |
| MusicBee | iTunes-compatible library XML | Local artists, albums, tracks, genres and saved counters | Separate library snapshot |
| Combined museum | Any supported combination | Source labels, normalization and evidence-aware overlap handling | Evidence-aware view |
Imports can be mixed. Source-specific fields remain source-specific: for example, Last.fm alone cannot prove Spotify device or skip behavior.
MusicBee is intentionally different: it shows what is in a local library, but its cumulative play counts are not added to Spotify, Last.fm or the historical timeline. Read the MusicBee import guide for the simple export steps, retained fields and privacy boundary.
The public exhibition is a local historical snapshot, not a live account connection:
| Evidence date | Verified value |
|---|---|
| Observed listening period | 2015-03-01 through 2026-07-03 |
| Dataset generated | 2026-07-14 |
| Recent Pulse synchronized | 2026-07-02 |
| Automatic synchronization | No |
The app never labels this archive βupdated 2026-08-01.β A future Spotify, Last.fm or MusicBee refresh must be compiled privately, reconciled and pass the public-bundle privacy audit before it can replace these dates.
The museum is organized into five stable hubs:
- Home β orientation, archive overview, sharing and feedback.
- Pulse β recent movement, loops, achievements and yearly summaries.
- Atlas β Living Artist Atlas, rankings and cultural geography.
- Stories β eras, identity, emotion and the final narrative.
- Data Lab β import, local audio, comparisons, quality and advanced statistics.
Three persistent depths change how information is presented without hiding rooms or changing the URL:
- Guided β opens friendly introductions and gives a clear next step.
- Explore β the balanced default: a calm, visual, self-directed museum visit.
- Deep Dive β opens methodology and prioritizes evidence, limits and advanced controls.
The Expedition Console keeps depth and the active-archive capsule visible across desktop and mobile. Ctrl/Cmd+K opens Nova Command for keyboard-first access to the complete museum. Read the experience contract.
Representative rooms include:
| Experience | What it explores |
|---|---|
| Dashboard | Archive identity, coverage and high-level signals |
| Era Explorer | How listening identity changes across years |
| Top HistΓ³rico | Artist, track and album dossiers with evidence-linked context |
| Obsession Detector | Repetition, streaks and concentrated listening periods |
| Emotional Map | Interpretive mood stations grounded in available signals |
| Cultural Map | Artist origins and listening geography |
| Living Artist Atlas | Searchable artist territories with archive weight, galleries, tracks, albums, offline profiles, provenance and opt-in official media |
| Share & Feedback | Browser sharing, WhatsApp invitation and structured local feedback without requiring an account |
| Audio Lab | Private local preview and file evidence boundary; advanced acoustic analysis is explicitly not run yet |
| Source Observatory | Last.fm, Spotify, YouTube, Apple Music and ListenBrainz coverage, field capabilities and honest missing-source states |
| Data Quality Center | Coverage, limitations and enrichment priorities |
| Final Report | A guided closing narrative and exportable summary |
Heavy rooms and data catalogs are lazy-loaded so the museum shell can appear before rarely visited analysis code is downloaded.
- Visitor-selected raw exports are parsed in the browser.
- A selected MusicBee XML is reduced to an allowlisted library snapshot; local file paths and persistent IDs are discarded.
- Imported museum state is stored in browser IndexedDB, not in a Nova backend database.
- Raw Spotify fields that are not required for analysis, such as IP addresses, are not retained.
- Clearing browser storage removes the local visitor museum from that browser profile.
- The GitHub repository and Pages site contain a reviewed flagship aggregate dataset.
- Exact-granularity flagship sections require an explicit declaration in the public dataset manifest.
- CI audits the bundle for undeclared sections and raw identity/network fields.
| Request | When it happens | What leaves the device |
|---|---|---|
| Google Fonts | Initial document load | Normal font request metadata |
| Remote artwork | A room displays curated external media | Image request metadata |
| YouTube/Spotify media | A visitor opens an embed or verified external link | The provider receives the request |
| Gemini | Only after a visitor explicitly configures a personal key and sends a question | The question and a bounded aggregate summary; never the raw export file |
| Share / WhatsApp | A visitor explicitly opens the share sheet or WhatsApp draft | The chosen app receives the prepared public link and text |
Nova Music Lab is therefore local-first, not network-isolated. A stricter no-remote-media Privacy Mode is tracked in the roadmap.
Read the full privacy threat model and public data policy.
Every analytical or narrative output should be classified as one of:
- Observed β directly supported by normalized archive events.
- Derived β deterministically calculated from observed data.
- Inferred β an interpretation with visible evidence and limitations.
- Unavailable β the active source cannot support the claim.
The project deliberately rejects plausible-looking fabricated numbers. Data reconciliation, source coverage, media identities and public-bundle privacy are enforced through scripts and tests.
The generated artist manifest currently contains 100 artist records and 295 provenance-aware visual assets. Artist aliases, MusicBrainz/Wikidata identifiers, countries, genres, releases, members and official links remain separate from private play counts. Each image record carries its source, license-review state, attribution, focal point and cache/privacy policy; after the reviewed Wikimedia Commons metadata pass, 6 assets remain visibly queued for license review rather than being mislabeled as reusable.
The Living Artist Atlas turns those records into explorable territories: progressive galleries with deterministic local fallbacks, archive-ranked tracks and albums, documented discography, official links and an on-demand evidence panel. Spotify and YouTube players stay behind an explicit privacy gate. Remote gallery images disclose their provider and network boundary instead of being described as local assets.
1.5.0 β deployed 2026-08-01 β explains three different coverage
layers instead of collapsing them into one number. Analytical genre families
cover 94.1% of 80,550 plays; detailed evidence exists for 453 of 6,413
catalog rows; and 1,662 rows remain unclassified. The evidence bundle
contains 1,257 assertions: 85 accepted, 1,170 candidate and 2
rejected. Accepted assertions appear as documented facts, candidates remain
visible suggestions, rejected relationships stay hidden and unresolved entries
say βTo research.β Observed means an automatic classification derived from
listening evidence, while Other groups smaller known families. Emotional
readings remain a separate heuristic layer rather than masquerading as genres.
The 6,413-row catalog is not a claim of 6,413 unique people or canonical artist identities. The current reversible identity registry documents 181 known normalized-name variant groups; this candidate does not delete or merge the historical rows.
External identity relationships and rejected matches are governed by artist_external_identity_policy.json. The identity audit detects duplicate external IDs unless an exact transliteration or historical-rename relationship is declared; it also prevents known bad matches, including the rejected nightlife MusicBrainz identity, from returning silently.
The manifest installs into the local Dexie database only when its source fingerprint changes. Returning visitors download the small metadata fingerprint during idle bootstrap, not the complete artist catalog on every visit.
The interface uses a shared Living Sonic Cartography registry for room palettes, atmospheric geometry and semantic navigation icons. The Nova orbit/waveform mark now drives crisp favicon, PWA, maskable and monochrome icon variants as well as the repository's static social preview.
flowchart LR
F["Listening exports"] --> P["Source adapters"]
P --> N["Normalize and validate"]
N --> D["Cross-source deduplication"]
D --> A["Shared analytics"]
A --> S["Archive capability and provenance"]
S --> R["Lazy museum rooms"]
R --> V["Charts, stories and exports"]
S --> I["Browser IndexedDB"]
A -. "bounded aggregate, opt-in" .-> G["Gemini"]
A --> C["Local museum comparison"]
K["Lazy public artist catalog"] --> C
| Layer | Primary responsibility |
|---|---|
src/utils/parser.ts |
Source parsing, normalization and merged dataset construction |
src/utils/musicBeeSnapshot.ts |
Privacy-safe MusicBee XML parsing into a separate local library snapshot |
src/utils/analytics.ts |
Shared quantitative calculations |
src/utils/datasetStorage.ts |
Local browser persistence and portable dataset validation |
src/db/ |
Dexie/IndexedDB schema revision 4, typed storage outcomes, atomic museum activation and compatibility stores |
src/knowledge/ |
Validated artist-knowledge manifest and provenance-rich visual records |
src/components/museumVisualIdentity.ts |
Shared room families, palettes, motion atmospheres and icon identity |
src/utils/identityEngine.ts |
Deterministic generative identity |
src/context/AppContext.tsx |
Language, theme and navigation state |
src/context/ExperienceContext.tsx |
Guided, Explore and Deep Dive preference with additive legacy migration |
src/components/shell/museumNavigation.ts |
Five-hub room ownership and canonical hub entry points |
src/App.tsx |
Museum shell, routing, transitions and data gate |
src/data/ |
Curated public enrichment and the reviewed flagship bundle |
Database design, migrations and failure states are documented in Storage and migrations.
- English, Spanish and Hebrew interfaces.
- Correct Hebrew RTL document direction and
he-ILformatting. - Fourteen dark and light museum themes.
- Keyboard-aware navigation, focus restoration and mobile drawer behavior.
- Expressive, Calm and Static atmosphere modes; Calm is the default and the operating-system reduced-motion preference overrides animation.
- Reduced-motion behavior across application transitions, charts, canvas art and static repository artwork.
- Exact-value chart tables and CSV exports for non-visual access.
1.2.0 β deployed 2026-07-29 β adds Playwright browser checks at 1440Γ900 and 390Γ844 plus automated axe WCAG A/AA checks. Automated scans catch only some issues, so keyboard, screen-reader semantics, contrast, RTL and visual review remain ongoing manual quality gates. See Accessibility.
npm run verify
node scripts/audit_public_bundle_privacy.mjsThe verified Pages pipeline runs:
lint
β strict data audit
β artist-identity relationship audit
β strict media-link audit
β artist-knowledge manifest audit
β public-bundle privacy audit
β PWA/installability contract audit
β tests
β TypeScript + production build
β bundle budgets
β Pages artifact
β exact commit/version deployment smoke test
GitHub also runs CodeQL and dependency review. The Pages job can only deploy the artifact produced by the successful verification job.
Requirements: Git and the Node version declared in .nvmrc.
git clone https://github.com/LiriothTeltanion/NovaMusicLab.git
cd NovaMusicLab
npm ci
npm run devBefore opening a pull request:
npm run verify
node scripts/audit_public_bundle_privacy.mjs
git diff --check
git statusUseful commands:
| Command | Purpose |
|---|---|
npm run dev |
Start the local Vite server |
npm run build:check |
Build and enforce bundle budgets |
npm run verify |
Run the canonical code/data/test/build gate |
npm run audit:data |
Print current data coverage and priority queues |
npm run audit:identity |
Reject undeclared duplicate artist identities and known bad external matches |
npm run audit:links |
Validate curated media profiles and embeds |
npm run compile:data -- --source-dir <path> [--lastfm-file <csv>] |
Compile an explicitly selected local archive; ambiguous CSVs require an explicit path |
npm run preview |
Preview the production bundle locally |
The compiler never searches personal directories automatically. Use a review output and run the public-data audit before replacing any bundled flagship data.
The creator CV call-to-action is off by default and is never bundled as a file. CreatorCvLink reads a public HTTPS URL from the environment, validates the protocol, and omits the link entirely when unset β so a fork never ships a broken or borrowed CV link.
| Variable | Effect |
|---|---|
VITE_CREATOR_CV_EN_URL |
Enables the CV link in English |
VITE_CREATOR_CV_ES_URL |
Enables the CV link in Spanish |
VITE_CREATOR_CV_HE_URL |
Enables the CV link in Hebrew (falls back to the English URL when unset, and the Hebrew label says so) |
Set them in .env.local for local runs, or as repository variables for the Pages build:
VITE_CREATOR_CV_EN_URL="https://example.com/cv-en.pdf"Only https: URLs are accepted; anything else is ignored and the link stays hidden.
| Guide | Purpose |
|---|---|
| Current status | Verified public status, snapshot dates and release evidence |
| Architecture overview | System boundaries and data flow |
| Guest Museum | Account-free visitor import, comparison and optional future identity |
| Storage and migrations | IndexedDB, dataset envelopes and recovery |
| Privacy threat model | Assets, imports, network and public-data risks |
| Data sources | Source capabilities and honest limitations |
| MusicBee library snapshot | MusicBee XML export, retained fields, privacy and non-timeline limits |
| Public data policy | Rules for the published flagship bundle |
| Artwork schema | Artist, album, track and gallery asset contracts |
| Visual system | Living Sonic Cartography, icons and motion tiers |
| Quality gates | Local and CI verification |
| Release guide | Versioning, tags, Pages and rollback process |
| Contributing | Branch, commit, privacy and review expectations |
| Security | Private vulnerability reporting |
| Roadmap | Ordered current and future product priorities |
| Changelog | Durable release history |
The production museum is deployed through GitHub Pages from the verified main artifact:
https://liriothteltanion.github.io/NovaMusicLab/
main is intended to remain deployable. Product work should use focused branches and pull requests; the release process is documented in docs/operations/RELEASE.md.
1.5.0 β deployed 2026-08-01 β is served by the protected GitHub Pages workflow. Pull request #27 promoted the reviewed source, and workflow run 30693829107 verified, deployed and smoke-tested initial release commit 0e00227cb03d3bb2cbc1c3eead4ed3a5e6603b7d. The live build metadata remains the authoritative artifact identity after documentation-only deployments. Product versions and IndexedDB schema versions remain deliberately independent.
Kevin Cusnir β LiriothTeltanion on GitHub
Nova Music Lab combines frontend engineering, data visualization, music technology, privacy-conscious personal analytics, multilingual interaction, accessibility and generative art.
The software is MIT licensed β fork it, learn from it, build your own museum with it.
The flagship dataset, generated visuals, narrative copy and brand are reserved: that dataset is one person's listening history, published so the analysis is verifiable rather than as a dataset to redistribute. See DATA_LICENSE.md.
Album art, artist photographs and structured metadata are linked, never redistributed, and remain with their rightsholders; see THIRD_PARTY_NOTICES.md.



