# feedthejoe.com The personal site of **Joseph W. Anady** — software engineer, retired U.S. Army Sergeant First Class (1st Infantry Division, Iraq), founder of ThatDeveloperGuy, a service-disabled veteran-owned firm. It is also a working recommender. The list of work reorders itself against what you actually read, and it shows you why. ## What is unusual about it **The ranking is the lighting.** Every entry carries an illumination value derived from its current rank, and the stylesheet spends it on colour, weight and size at once. The model's opinion arrives as light rather than as a number. Nothing is ever removed — an entry it has set aside is dimmer, not gone. **It shows its working.** Every row exposes the four terms that produced its score, including the penalty. Recommenders do not usually let you see this. **Nothing leaves your machine.** No cookies, no account, no telemetry, no server call. Session state lives in `sessionStorage` and is discarded when the tab closes. There is no endpoint to send anything to. **Semantics are precomputed.** Item embeddings are generated at build time with Transformers.js and ship as a 25 KB int16 sidecar, so the browser needs no model to use the feed. ## The algorithm A faithful reduction of the published mechanics of TikTok's ranker to a corpus of a few dozen items with no server: | Signal | Weight | Web analogue | |---|---|---| | completion | 1.00 | dwell ÷ estimated read time | | rewatch | 0.85 | returning to something already read | | share | 0.70 | copying the link | | expand | 0.55 | opening the full piece | | save | 0.35 | explicit save | | contact | 1.20 | reaching the contact surface | | **skip** | **−0.60** | scrolling past faster than reading allows | ``` score(i) = w₁·Thompson(Beta(α,β) per topic) ← exploration, cold start + w₂·cos(interest, item) ← semantic match + w₃·freshness(i) − w₄·fatigue(i) ← recency, anti-repetition ``` Selection is Maximal Marginal Relevance, so a confident model still cannot collapse the feed into a single topic — the characteristic failure of a small-corpus recommender. Completion is measured against estimated read time rather than in raw seconds, so a long item cannot win by being long. Dwell does not accrue while the tab is backgrounded. Skips carry real negative weight: a model that only learns from positive signals drifts toward whatever it happened to show first. ## Architecture ``` src/core/ pure functions — no clock, no I/O, no DOM, no global random src/ports/ contracts only; imports nothing src/adapters/ the impure edge: fetch, storage, DOM observation src/ui/ rendering; no business logic src/app/ composition root — the only place wiring happens ``` The arrow never points from `core/` outward. That is enforced mechanically by `dependency-cruiser` on every `npm run verify`, not by convention. Because the ranker is pure and its randomness is injected, a given `(corpus, state, config, nowMs, seed)` always produces the same order — which is why the ordering itself can be a test fixture. ## Build and verify ```bash npm run verify # lint, architecture, cycles, tests node build/extract-corpus.mjs .source content/corpus.json node build/embed-corpus.mjs content/corpus.json content/embeddings.bin node build/build.mjs # -> dist/ ``` The build content-hashes the asset tree, subsets the variable font to the glyphs actually used (643 KB → 46 KB, both axes preserved), and pre-compresses every text asset with zopfli for nginx `http_gzip_static`. ## Licence MIT for the code. Prose and the body of work are © Joseph W. Anady. Archivo is licensed under the SIL Open Font License.