A tool that turns SPL's PSU Tier List (a Google Sheet) into a userscript that injects coloured Tier badges directly onto power-supply listings on PCPartPicker (all regions) and Tweakers.net, so you can judge PSU quality at a glance.
A solid badge indicates a strong match; a dashed Tier X? badge indicates
a likely match. Click for specifications, alternate identities and a
similarity score from 0 to 1. That score is not a probability of correctness.
Explicit generation conflicts are rejected; unspecified generations stay likely.
Warning
Manufacturer naming is inconsistent across the tier sheet, PCPartPicker and Tweakers (and those three disagree with each other). The matcher is good but false positives/negatives happen β always confirm on the official spreadsheet before buying. The match band and "other possible matches" list are there to make disagreement visible rather than hidden.
The easiest way is the official store listing for your browser β one click, with automatic updates. Prefer not to use a store? Manual and userscript options are below.
|
π¦ Get it for Firefox |
π’ Get it for Chrome |
- Firefox β Add to Firefox from Mozilla Add-ons (AMO).
- Chrome β Add to Chrome from the Chrome Web Store.
- Brave, Edge, Opera, Vivaldi & other Chromium browsers β install straight
from the Chrome Web Store link above β these browsers accept
Chrome Web Store extensions directly. Notes:
- Brave: open the Chrome Web Store link, click Add to Brave. If prompted, allow Chrome Web Store extensions (Brave enables this by default).
- Edge: open the link in Edge; the first time you may see a banner to Allow extensions from other stores β click it, then Add to Chrome β Add extension.
- Opera: install Install Chrome Extensions first, then use the Chrome Web Store link.
- Go to the Releases page.
- Download the signed
psutier-extension.xpifile. - Open Firefox, drag and drop the
.xpifile into the browser (or pressCtrl+O/Cmd+Oand select it) to install it. No extension manager required!
- Download
psutier-extension.zipfrom the Releases page and extract it. - Open
chrome://extensions,brave://extensions, oredge://extensions. - Toggle Developer mode on (top-right).
- Click Load unpacked and select the extracted folder.
- Install a userscript manager:
- Brave / Chrome / Edge (Chromium): install Violentmonkey (or Tampermonkey) from the Chrome Web Store.
- Firefox: install Violentmonkey/Tampermonkey from Add-ons.
- Brave/Chrome only β enable user scripts (required since Chromium tightened
Manifest V3): open the extension's Details, and turn on "Allow User
Scripts" if shown; on older builds toggle Developer mode on
brave://extensionsinstead. (One-time step.) - Download the latest
psutier.user.jsfrom the Releases page β your manager will offer to install it.
Tweakers' own custom CSS carries the tier badges with no extension or userscript manager at all β just enable the shared snippet:
βΆ Enable the snippet on Tweakers β toggle it on and reload the Pricewatch.
It's Tweakers Pricewatch only (no PCPartPicker) and a static snapshot of the tier list β new products / tier changes appear when the snippet is updated.
To (re)generate it yourself (or build a different variant), see
tools/README-tweakers-css.md:
- boxed (default, ~40 KB) β filled tier pills, matching the extension's look.
- lite (~37 KB) β colored tier letter only.
- popup β pills plus a hover spec popup, abusing
::beforecontent.
Finally, visit a PCPartPicker PSU listing or the Tweakers Pricewatch and look for the badges.
Google Sheet ββ snapshot.py --refresh βββΊ frozen CSVs + metadata + semantic diff
β review and commit
βΌ
tests/fixtures/sample_psu_data.json
β
βββ src/matcher.js (shared matching engine)
βββ src/adapters.js (site extraction)
βββ data/normalization_rules.json (naming rules)
βββ src/userscript.template.js (UI)
β
generate_userscript.py βββΊ psutier.user.js
β
build_extension.py βββΊ extension ZIP
β
test_suite.py --release βββΊ validation attestation
- Data source is the sheet's
gvizCSV export (stable columns, no HTML scraping, no third-party Python deps). - Matching (
src/matcher.js) tokenizes the product name and each candidate model and scores a weighted token overlap. It also uses the storefront's structured columns as signals, not just the name: wattage and form factor (ATX vs SFX) are hard filters, and efficiency disambiguates variants. When a name is too thin to score on its own (e.g. "NZXT C750" β just "c"), those signals resolve it by constraint (wattage + efficiency + form factor). Explicit model years, generations, revisions and named editions must agree; ambiguous identities are downgraded even when their tiers agree. The winning score is a similarity measure shown in the detail popup. This is the single source of truth β the userscript and the test suite run the exact same code. - There are no hardcoded per-product hacks. Naming quirks are fixed by editing data, not code (see below).
Edit data/normalization_rules.json:
aliasesβ rewrite incoming product names (e.g. ASUS"850G"β"850 gold").stripβ remove descriptors that differ across sources and never identify a model (ATX version tags, the80+prefix, β¦); applied to both sides.generic/noiseβ words that score low / are dropped.identityβ meaningful revision, variant and family vocabulary.thresholds/weightsβ match bands and scoring balance.
Identity qualifiers are checked before descriptors are stripped. Aliases must not erase explicit conflicting generations. Include wrong-model and forbidden alternate assertions when changing naming rules.
Add a case to tests/corpus.json, run npm test, done.
Add one entry to src/adapters.js:
{ id, match, selector, filter?, extract, insertBadge }, where extract(row)
returns { name, wattage, efficiency, formFactor, modular } (pull as many of
those from structured columns as the site exposes β the matcher uses them).
Prerequisites: Python 3, Node.js 20.19+ and uv.
npm ci
node node_modules/playwright/cli.js install chromium
python test_suite.py --release
python verify_artifacts.pyThe full gate validates frozen CSV provenance, lint/types, matcher contracts, reviewed identity benchmarks, parser/build failure handling, browser behavior, and the exact generated userscript and extension ZIP. It needs no live sheet or storefront requests. Initial dependency/browser installation and uv tool setup require network access. CI installs Chromium's system dependencies too.
For local iteration:
python test_suite.py --quick # skips browser checks; cannot attest a release
node tools/check.cjs # lint, types and offline JavaScript checks
node tools/check.cjs --browser
node tools/benchmark.cjs
node tools/benchmark.cjs --holdoutpython snapshot.py --refreshReview the frozen exports, tests/fixtures/sheet/diff.json, metadata and parsed
snapshot together. Check changed names, generations, tiers, duplicate identities,
conflicts and missing fields against the source rows. Update affected regression
expectations and reviewed benchmark labels from source evidence, not matcher
predictions. Dataset changes intentionally invalidate benchmark hash policies.
Run the full release gate, inspect its reports, and commit the complete snapshot
bundle and justified expectation changes before tagging a release.
python generate_userscript.py builds from the committed snapshot. --data PATH
selects alternative data for local investigation; the release gate always uses
the committed snapshot. Refreshing never publishes.
The curated corpus asserts identities, tiers, uncertainty and forbidden matches. Saved storefront coverage is informational; adding wrong matches cannot make a coverage gate pass. Adapter checks include real saved rows before and after badge insertion. Chromium tests cover row reuse/replacement, unknown generations, limited/unrated/tier filters, popups, responsive bounds, preferences and actual manifest injection. Targeted mutation checks verify that generation, ambiguity and wattage protections are exercised.
The 300-product reviewed sample is development evidence. A separate 50-product sample excludes its families and curated regression families. Reviews compare saved records with frozen sheet rows; they have not been verified by a human or manufacturer. Unresolved identities stay visible and are excluded from resolved-case precision. The frames are saved convenience samples, so neither coverage nor benchmark precision establishes a live-catalog error rate. See validation results and limitations.
node tools/live_capture.mjs --capture
node tools/live_capture.mjs --smokeLive captures go to reports/captures/ for review and never overwrite committed
fixtures. Smoke checks record the script hash, injection, runtime errors and a
popup interaction in reports/live-smoke.json: exit 0 means passed, 1 failed,
2 inconclusive (network, consent, challenges or missing listing selectors).
These checks are on demand and separate from deterministic CI. They do not
validate every returned identity. Use --headed, --channel=chrome|msedge or
--browser-path=... for a local installed browser.
CI and tagged releases run the same full offline gate. Releases build only the reviewed committed snapshot. Immediately before each publishing step, hashes and source/test inputs must still match the successful validation attestation. Signed Firefox packages, when present, must preserve the tested application files. This content comparison does not verify Mozilla's signature itself.
The manually dispatched snapshot-health workflow produces a candidate refresh artifact for review. It neither commits changes nor publishes a release.
If you find PSU Tier Badges useful, you can support development on Ko-fi. Contributions are optional and support maintenance of this extension and userscript. PSU ratings are provided by SPL's PSU Tier List, credited below.
- Data: SPL's PSU Tier List.
- PCPartPicker and Tweakers.net for the platforms this enhances.
Not affiliated with PCPartPicker, Tweakers, or the spreadsheet maintainers.


