Contributing to Slop Filter
September 20, 2026 ยท View on GitHub
Thanks for helping. Right now we are looking for three kinds of contribution:
- New social media sites. YouTube is next, and old.reddit.com is open. Anything with a feed works.
- Better recognition of AI-written posts. A tell you noticed, turned into one question, or a sharper version of a question we already ask.
- Making it more efficient. Fewer tokens, fewer requests, faster results, same accuracy.
For anything else, open an issue first so we can talk about it before you build it.
Set up
- Fork and clone the repo.
- Open
chrome://extensions, turn on Developer mode, click Load unpacked, pick the folder. - Open the extension's options and paste your TypeSafe API key.
- Run the tests:
node --test(Node 20 or newer).
There is no build step and there are no dependencies. Please keep it that way.
Using a coding agent? Point it at SKILL.md. It covers setup and every kind of change below.
Make a change
- Branch from
main. - Make one focused change.
- Add a line under
## [Unreleased]inCHANGELOG.md. Leave the version numbers alone. The maintainer sets them at release. - Run
node --test. - Click "Reload extension" on the options page, then reload your open tabs. Reloading the tab alone keeps the old code running.
- Open a pull request. Say what you changed, which sites and flag modes you tried it on, and what you could not check. Add a screenshot or a short clip for anything visual.
Commit titles follow feat:, fix:, docs:, chore:.
New sites: add an adapter
A site is one adapter in src/sites/<site>.js. Copy src/sites/linkedin.js. The contract is in docs/development.md.
- Inspect the live site first. Prefer stable hooks (
data-testid,role, id-like attributes) over class names. extractruns often. Keep it cheap, and returnnullfor anything that is not a scorable post.- Add a
content_scriptsentry inmanifest.json, and asrc/sites/<site>.cssonly if the bar or the collapse needs a layout fix. - Some sites restrict extensions that change their pages. Say so in the adapter's notes in
docs/development.md.
Better recognition: add or sharpen a tell
A tell is one entry in QUESTIONS in src/model.js.
- One narrow judgment per question. "Does it open with praise?" is good. "Does it sound like AI?" is not.
- Jev reads the words as written. Name the exact pattern, give two or three example phrasings, and use
criteriawhen the line between yes and no is subtle. - Set
needsParent: trueif it only makes sense for a reply. - If plain code can detect the pattern exactly, add it to
CODE_FEATURESinstead. If it needs judgment about meaning, make it a question. Word lists flag normal writing. - Give it a modest starting weight in
DEFAULT_WEIGHTS. The tests fail if a feature has no weight. - In the pull request, show it working: the output of
node scripts/try.mjs "post text" "text it replied to"on a few posts it should catch and a few it should leave alone. Paraphrase the posts or use your own. Do not paste other people's posts with their names.
Make it more efficient
Every post costs one request to Jev. The cost is input tokens: the post text plus every question. Output tokens are free.
- Good targets: shorter question wording that scores the same, skipping questions that cannot apply, not scoring the same text twice, fewer wasted requests on posts the user never sees, faster first result on page load.
- Show the numbers.
node scripts/try.mjsprints the input tokens for one post. Give before and after, on the same posts. - Accuracy comes first. If a change touches a question's wording, show that its answers did not move on a few posts it should catch and a few it should leave alone.
- One request per post, with every question in it, is on purpose. Jev answers all the questions in a request in parallel, so splitting them up costs more and is slower.
House rules
- State on a site's own post element goes in
data-xaf-*attributes, never classes. X rewrites a post's class list on every hover. Classes are fine on elements the extension creates. - Shared CSS must not assume a tag name.
- Constants at the top of each file, no magic strings, small functions.
- The API key and all network calls stay in
src/background.jsandsrc/jev-client.js. The page never sees the key. - Never commit an API key. Never commit an exported
labels.json: it holds other people's posts and handles.
Report a bug
Open an issue with:
- The site and the flag mode (Collapse, Animated, Dim, Badge).
- The version shown at the top of the options page.
- Any
[xaf]warnings from the page console. - What you expected and what happened.
Never paste your API key into an issue.
License
Slop Filter is MIT licensed. By contributing, you agree that your contributions are licensed under the same terms. The bundled Fredoka font is under the SIL Open Font License, in assets/fonts/fredoka-OFL.txt. The icon is under the Flaticon license, in assets/icons/ATTRIBUTION.txt.