Retro-styled web player that picks random tracks from data/metadata.tsv and streams MP3s from the Internet Archive item The Myspace Dragon Hoard (2008–2010). URLs follow the same pattern as the official IA “Hobbit” player (ZIP member paths).
- Node.js 20+
data/metadata.tsvin this repo (Dragon Hoard export). No local MP3 mirror is required.
-
Copy
.env.exampleto.envand adjust:METADATA_TSV— path tometadata.tsv(default:data/metadata.tsvinside this project).- Ports — defined in
config/ports.tsas paired pools. UsePORT_INDEX(0–3) to pick a pair, or setPORT/VITE_DEV_PORTexplicitly. Defaults: API38471, Vite dev38472(index 0). IA_ITEM_ID(optional) — Internet Archive item id (defaultmyspace_dragon_hoard_2010).SERVE_STATIC— ifdist/index.htmlexists afternpm run build, the app serves the SPA +/apiautomatically. SetSERVE_STATIC=falsefor API-only. Explicittrue/1is optional; use it when you want a clear flag in PM2/systemd.
-
Install dependencies:
npm install
Start the API and the Vite app together (/api → http://localhost:38471 with default PORT_INDEX=0):
npm run devOpen the URL Vite prints (by default http://localhost:38472 with PORT_INDEX=0).
One process can serve both the SPA and /api after build:
npm run build
SERVE_STATIC=true npm run startProduction runs compiled JavaScript (node dist-server/server/index.js), not tsx. Dev still uses tsx watch server/index.ts for the API hot reload.
Or use PM2 (from this folder, after npm run build):
npm run pm2:prod
# or: pm2 start ecosystem.config.cjs --env production
pm2 save
pm2 startupSet METADATA_TSV to an absolute path on the server inside ecosystem.config.cjs → env_production, or use a .env next to the app.
- Ensure
data/metadata.tsvis present aftergit clone/ deploy (large file; clone may take a while). If you omitted it, copymetadata.tsvnext to the app and setMETADATA_TSVto an absolute path. Relative paths resolve fromprocess.cwd()(the app root). - Restart the process and check
GET /api/health: you should seetracksReady: true,trackCount> 0,metadataExists: true, and ahintif something is still wrong.
Point HTTPS at the Node port (default from pool index 0: 38471, or whatever PORT / PORT_INDEX sets). Example nginx:
server {
server_name mymusics.murad.gg;
location / {
proxy_pass http://127.0.0.1:38471;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}No extra vite.config base URL is needed when the site is served at the domain root.
Embed (/embed) on third-party sites: The Node server sends Content-Security-Policy: frame-ancestors * on HTML responses so the player can be iframed. If the iframe still appears blank elsewhere, check that nginx (or another proxy) is not adding X-Frame-Options: DENY / SAMEORIGIN or a stricter frame-ancestors — those headers override or combine with the app’s policy.
The API returns 503 only when the in-memory track pool is empty (trackCount: 0). The browser request is reaching Node; fix metadata path and env on the server.
-
On the VPS (SSH), call health locally (replace
38471if you use anotherPORT):curl -sS http://127.0.0.1:38471/api/health
Check
metadataTsv,metadataExists,metadataSizeBytes,trackCount,tracksReady, andhint. -
Align
METADATA_TSVwith the real file (e.g./opt/mymusics/data/metadata.tsv). Wrong paths such as/opt/data/metadata.tsvlook “almost right” but fail if the file lives under the app directory. Alternatively removeMETADATA_TSVfrom.env/ PM2 so the app uses the defaultdata/metadata.tsvnext to the project. If the env path is missing butdata/metadata.tsvexists inside the app, the server falls back to that file automatically and logs a warning (you should still fix.envto avoid confusion). -
Restart the process after editing env so variables reload:
pm2 restart mymusics --update-env
(Use your PM2 app name if different.)
-
Re-run
curluntiltracksReadyistrueandtrackCount> 0.
Messages such as “The kernel '…' for backend 'cpu' / 'webgl' is already registered” (often under content.js) or “Platform browser has already been set” (under classifier.js) come from browser extensions that bundle TensorFlow.js — not from MyMusics (this repo does not ship TensorFlow). To confirm, open a private/incognito window with extensions disabled for that session, or turn extensions off temporarily.
- The browser loads audio directly from
https://archive.org/download/...URLs. First play may be slow while the Archive serves the file from inside large ZIPs. - HTTP 503 (or other failures) on the MP3 URL come from Internet Archive (overload, ZIP member extraction, etc.), not from this app’s API. The player may auto-skip to another random track a few times; use Next if streaming keeps failing.
- This is not DRM; users can still capture network traffic or use devtools.
| Command | Description |
|---|---|
npm run dev |
Vite + API with hot reload |
npm run build |
Production frontend build |
npm run start |
API (node dist-server/server/index.js — run npm run build first); SERVE_STATIC=true also serves dist/ |
npm run build:server |
Compile API + config/ports to dist-server/ (included in npm run build) |
npm run pm2:prod |
npm run build then PM2 with ecosystem.config.cjs |
public/mymusics.png is the MyMusics logo asset.