Source: human-feedback note 01KVDYV3A35B57N15CRBQDXPCH (project/reddit-spotify-linker, 2026-06-18) — "remove the musicbrainz integration and just use spotify"; a google search for "<name> bandcamp" fallback; and "would a local llm be better able to categorise these ... include instructions for running something suitable via ollama (16GB M2)". - Remove MusicBrainz entirely (viaMusicBrainz + url-rels + rate-gate; lib relUrls/mbResult). Spotify is now the only music API; it both gates by exact-name match and supplies the direct artist link. - Optional ollama LLM gate (OLLAMA_URL enables it, OLLAMA_MODEL default qwen2.5:3b) called over plain HTTP -> stays zero npm-dep. It classifies which candidates are real artists/albums (the matching-quality lever). Pure prompt/parse logic in new llm.js (unit-tested in llm.test.js); the fetch + resolveAll gate wiring live in resolver.js. - A confirmed name links to its direct Spotify page when available, else a Google search for "<name> bandcamp". New "google" primary platform rendered by the extension (styles.css blue accent + platform-aware link title in content.js). - README: drop MusicBrainz; document the two gates + a runnable local-LLM setup for a 16GB MacBook M2. AGENTS.md: flip the old "no ML/NER" standing decision per the human override. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
7.6 KiB
Reddit → Spotify / Bandcamp linker
A Firefox extension that, while you browse a Reddit thread, finds artist / band names in the comments (and the post body) and turns them into inline links to Spotify and Bandcamp — so a recommendation thread like this one becomes a list of clickable artists instead of names you have to copy-paste into search.
The hard part is "which words are artists and which aren't?". Rather than guess with client-side rules, the extension hands candidate names to a tiny local resolver service that confirms each one and only links the names that are really artists. The resolver confirms names two ways (you enable either or both): Spotify (exact-name match → direct artist pages) and an optional local LLM via ollama (classifies which candidates are artists/albums). A confirmed name links to its Spotify artist page when available, otherwise to a Google search for " bandcamp".
reddit page content script resolver service
─────────── ────────────── ────────────────
comment text ──extract──> candidate names ──POST /resolve──> Spotify API (exact-match + direct links)
and/or
<a> links <──rewrite── confirmed links <───────────────── local LLM (ollama, optional)
Layout
service/ tiny Node.js resolver (one file, zero npm deps)
resolver.js
package.json
.env.example
extension/ Firefox MV2 extension
manifest.json
background.js (does the resolver fetch; talks to the content script)
content.js
styles.css
icon.svg
1. Run the resolver service
Requirements: Node 18+ (uses the built-in fetch). No npm install needed —
there are no dependencies.
cd service
node resolver.js
# resolver listening on http://localhost:8787 (spotify: off, llm: off)
For anything to link you need at least one of two gates configured — Spotify credentials or the local LLM (or both). With neither, the resolver warns at startup and nothing links.
Spotify credentials (one of the two gates)
Spotify does two jobs: it gates a name (a candidate links only when Spotify has that artist by exact name match) and supplies the direct artist-page link. To enable it:
-
Create a free app at https://developer.spotify.com/dashboard and copy its Client ID and Client Secret.
-
cp .env.example .envand fill them in (the.envfile is gitignored):SPOTIFY_CLIENT_ID=your_id SPOTIFY_CLIENT_SECRET=your_secret -
Restart the service. Startup reports
(spotify: on, llm: off).
With Spotify alone, names that aren't on Spotify don't link — precise, but it misses real artists Spotify doesn't carry. The local LLM gate (below) catches those.
Quick check that it works:
curl -s localhost:8787/resolve \
-H 'content-type: application/json' \
-d '{"candidates":["Cerebral Bore","Devourment","Notarealband Xyzzy"]}'
# {"Cerebral Bore":{...},"Devourment":{...},"Notarealband Xyzzy":null}
A confirmed name links to its Spotify artist page when available, otherwise to a Google search for " bandcamp" (which surfaces the artist's Bandcamp page).
Better matching with a local LLM (optional)
The optional LLM gate is the matching-quality lever: it classifies which candidate strings are real artists/albums, so confirmed names that aren't on Spotify still link (via the " bandcamp" Google fallback). The resolver calls ollama over plain HTTP, so it stays zero npm dependencies.
On a 16GB MacBook (M2):
-
Install ollama — https://ollama.com/download or
brew install ollama. -
Pull a small model:
ollama pull qwen2.5:3b(~2GB; runs comfortably on a 16GB M2; the first resolve call warms the model so it's a little slow once, then fast). -
In
service/.env, point the resolver at ollama (and optionally override the model):OLLAMA_URL=http://localhost:11434 OLLAMA_MODEL=qwen2.5:3b -
Restart the resolver. Startup reports
(spotify: off, llm: qwen2.5:3b)(or(spotify: on, llm: qwen2.5:3b)if you also set Spotify creds). -
Confirm:
curl localhost:8787/healthshould show"llm":"qwen2.5:3b".
With both gates, the LLM decides which names are artists and Spotify supplies the direct links; with the LLM alone, confirmed names get a Spotify direct link if one exists, else the Google fallback.
2. Install the extension in Firefox
The extension is unpacked / unsigned, so load it as a temporary add-on:
- Open
about:debugging#/runtime/this-firefox. - Load Temporary Add-on…
- Select
extension/manifest.json.
It's now active until you restart Firefox. (To keep it permanently you'd sign it
via AMO or use Firefox Developer/ESR
with xpinstall.signatures.required = false.)
3. Use it
- Make sure the resolver service is running.
- Open any Reddit comments thread (a URL with
/comments/in it). - Artist names become a single link — to Spotify if the artist is on Spotify, otherwise to Bandcamp — colour-coded (green = Spotify, teal = Bandcamp). New comments loaded as you scroll are linked automatically.
- The toolbar icon shows the extension is active; its badge shows how many links were added on the current page.
Troubleshooting
If nothing gets linked:
- Confirm the resolver is running —
curl localhost:8787/healthshould return{"ok":true,"spotify":<bool>,"llm":<model|false>,"cached":<n>}. If bothspotifyandllmare off, nothing can link — configure at least one gate above. - On the reddit thread, open the browser console (F12) and look for
[rsl]logs: they report the root element, candidate count, and resolver responses on each scan. Aresolve failedline means the background script can't reach the resolver (is it on:8787?);candidates found: 0means the comment text wasn't matched (please report the thread). - The content script reaches the resolver through the extension's background script
— a page-context fetch to
http://localhostis blocked by reddit's CSP — so make sure the add-on loaded without errors inabout:debugging.
Configuration
The resolver URL is the constant RESOLVER_URL at the top of
extension/background.js (default http://localhost:8787). If you change the host
or port, update both that constant and the matching entry in
extension/manifest.json → permissions (Firefox needs the host listed there to
let the content script reach it).
Limitations (MVP)
- Detection is mostly capitalization-based, with a cue-phrase pass that also catches lowercase names right after "check out / by / fan of / recommend …". Names split across inline formatting (e.g. bold mid-name) can still be missed. The resolver's exact-name match keeps false positives low; the trade-off is some false negatives.
- Links are direct to Spotify when Spotify has the artist; otherwise a confirmed name links to a Google search for " bandcamp" (which surfaces the artist's Bandcamp page).
- Without Spotify creds or the LLM, nothing links — at least one gate must be configured.
- The optional LLM adds a little latency on the first call (ollama warms the model), then is fast.
- The resolver caches results in memory; it resets when you restart it.
- Built and tested as a Firefox MV2 extension.
License
Personal project — do as you like.