relatinator 3.3 · MIT

Find related posts when your site builds.

relatinator scores your documents against each other with BM25 or TF-IDF. It runs in Node.js, the browser, and Cloudflare Workers, and its only dependency is a stemmer. astro-relatinator hooks it into Astro content collections, so a related posts list is one getRelated call.

pnpm add relatinatorpnpm add astro-relatinator
related.tsBUILD TIME
import { createModel } from "relatinator";

const model = createModel(posts);
model.findRelatedScored("science-books-space", { limit: 3 });
  1. 0115 Mind-Expanding Science Books for Your Summer Reading List84.09cosmicspaceunivers
  2. 0214 Fascinating Science Books to Curl Up With This Autumn67.15universlatestphysic
  3. 0310 Groundbreaking Science Books to Welcome the Spring Season63.38spacephysicrodriguez

See why a post ranked where it did

findRelatedScored gives you the scores. explainRelated shows which words earned them, so you can check a strange match instead of guessing.

explain.ts
model.explainRelated("science-books-space", "science-books-autumn");
  • univers · 6.67
  • latest · 3.81
  • physic · 3.73
  • dark · 2.83
  • us · 2.35

Works with Astro content collections

getRelated("posts", entry, { limit: 3 }) reads the collection when the page renders. It works with static output and with on-demand rendering.

const related = await getRelated("posts", entry,
  { limit: 3 });
return related;

Topics from a fixed list

classify(topics, text) matches text against topic descriptions you write. You don't train anything or ship a model file, and the text never leaves your process.

const topics = [{ tag: "space", description }];
const best = classify(topics, text);

How scoring works

  1. 01 · Tokenize

    Lowercases the text, removes elisions, splits on anything that isn't a letter or digit, drops stopwords, and stems what's left with Porter2.

  2. 02 · Weigh

    Indexes the documents once and weights each term with BM25 or TF-IDF.

  3. 03 · Score

    Adds up the weights of the query terms that a document contains.

  4. 04 · Rank

    Drops the query document, excluded documents, and anything that scored zero. Sorts the rest by score, keeps input order for ties, and returns as many ids as you asked for with limit.

Read the full rules →

Compatibility

Targetrelatinatorastro-relatinator
Node.js22.12 or later22.12 or later
BrowsersYesNo, it runs at build time or on the server
CloudflareWorkersThe Cloudflare adapter, with prerendering in workerd
AstroNot needed6 and 7
Astro outputNot neededStatic output and on-demand rendering
EmDashNot needed1.x (1.0 or later), as an optional peer dependency
Module formatES modules only, with type filesES modules only, with type files