paulandClaude Opus 4.8 071cc3f85a fix: pierce new-reddit (shreddit) shadow DOM when collecting comment text (closes task/handle-shreddit-shadow-dom)
Source: task/handle-shreddit-shadow-dom (plan/steward-linker-design) — the TreeWalker only walked light DOM, so new-reddit comment bodies inside shadow roots were missed.

- collectTextNodes now walks the comment-tree root's light DOM AND recursively descends into the open shadow roots of elements within that subtree, so comment text is reached whether reddit slots it (light DOM) or encapsulates it (shadow DOM).
- Scoped to getRoot()'s comment tree (never the whole document's shadow roots); bounded by a depth cap; a no-op on old reddit (no shadow roots).
- Slotted light-DOM nodes are not double-collected (a shadow walker sees the shadow tree's own nodes, not a <slot>'s assigned light nodes); a Set de-dupes by node identity belt-and-braces.
- All existing guards preserved (inSkippable / rsl-link skip). README + AGENTS document the support.
- Limitation: CLOSED shadow roots are unreachable from a content script and stay unlinked.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 14:28:31 +00:00

Reddit → Spotify / Bandcamp linker

A Firefox extension that, while you browse a Reddit thread, finds artist / band names and album titles 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 and albums instead of names you have to copy-paste into search.

The hard part is "which words are artists/albums 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 or albums. The resolver confirms names two ways (you enable either or both): Spotify (exact-name match across artists and albums → direct Spotify pages) and an optional local LLM via ollama (classifies which candidates are artists/albums). A confirmed name links to its Spotify artist/album page when available, otherwise to a Google search for " bandcamp". Album links are italicised so you can tell an album from an artist at a glance.

 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 or album by exact name match) and supplies the direct Spotify page link. A single search call covers both types, so albums confirm and link with no extra setup. To enable it:

  1. Create a free app at https://developer.spotify.com/dashboard and copy its Client ID and Client Secret.

  2. cp .env.example .env and fill them in (the .env file is gitignored):

    SPOTIFY_CLIENT_ID=your_id
    SPOTIFY_CLIENT_SECRET=your_secret
    
  3. 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):

  1. Install ollama — https://ollama.com/download or brew install ollama.

  2. 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).

  3. In service/.env, point the resolver at ollama (and optionally override the model):

    OLLAMA_URL=http://localhost:11434
    OLLAMA_MODEL=qwen2.5:3b
    
  4. Restart the resolver. Startup reports (spotify: off, llm: qwen2.5:3b) (or (spotify: on, llm: qwen2.5:3b) if you also set Spotify creds).

  5. Confirm: curl localhost:8787/health should 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:

  1. Open about:debugging#/runtime/this-firefox.
  2. Load Temporary Add-on…
  3. 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

  1. Make sure the resolver service is running.
  2. Open any Reddit comments thread (a URL with /comments/ in it).
  3. Artist names and album titles become a single link — to Spotify if it's on Spotify, otherwise to Bandcamp — colour-coded (green = Spotify, blue = Google/Bandcamp); album links are italicised so they read as albums. New comments loaded as you scroll are linked automatically.
  4. 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:

  1. Confirm the resolver is running — curl localhost:8787/health should return {"ok":true,"spotify":<bool>,"llm":<model|false>,"cached":<n>}. If both spotify and llm are off, nothing can link — configure at least one gate above.
  2. 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. A resolve failed line means the background script can't reach the resolver (is it on :8787?); candidates found: 0 means the comment text wasn't matched (please report the thread).
  3. The content script reaches the resolver through the extension's background script — a page-context fetch to http://localhost is blocked by reddit's CSP — so make sure the add-on loaded without errors in about: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.jsonpermissions (Firefox needs the host listed there to let the content script reach it).

Limitations (MVP)

  • Artist 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.
  • Album detection leans on two precise signals — quoted titles ("Reek of Putrefaction") and album cue phrases ("the album X", "X LP/EP"). Album free-text is noisier than artist names, so it deliberately over-generates only from these cues and lets the Spotify exact-album match (and/or the LLM) be the precision filter. A bare album title written with no quotes or cue may be missed.
  • Links are direct to Spotify when Spotify has the artist/album; otherwise a confirmed name links to a Google search for " bandcamp" (which surfaces the Bandcamp page).
  • Without Spotify creds or the LLM, nothing links — at least one gate must be configured.
  • New reddit (shreddit) shadow DOM — the comment-text scan pierces the open shadow roots of the shreddit-* web components within the comment tree, so it links comment bodies whether reddit slots them into light DOM or encapsulates them in a shadow root. Closed shadow roots are unreachable from a content script and stay unlinked (a browser limitation, not a setting).
  • 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.

S
Description
No description provided
Readme
275 KiB
Languages
JavaScript 98.4%
CSS 0.9%
Shell 0.7%