Skip to content
Back to news

Comparison pages, with a build check that fails when a claim goes stale

Four gateways, one typed fact table, a first-party source on every claim, and a sixty-day shelf life the build enforces.


/compare is live, with a page for OpenRouter, LiteLLM and Portkey and an essay on what a routing receipt is for. Comparison intent is most of this category's organic search, and Lobstack appeared in none of it.

The review it was meant to typeset was already wrong

The competitive notes behind these pages were two days old, and two of their load-bearing claims were false by the time we went to publish.

  • "The response tells you the model name and nothing else." OpenRouter now returns an opt-in openrouter_metadata object naming the routing strategy, a one-line summary of the decision, and the candidate endpoints it considered with a flag on the one it picked.
  • "No vendor exposes what the request would have cost on the model it did not choose." LiteLLM computes exactly that, with a published formula, a stated baseline, a warm-cache correction, the classifier's own cost subtracted, and a signed result that can admit routing lost money.

Both were true when they were written. Neither was true forty-eight hours later.

So the facts are data, and the build checks them

Every claim lives in src/lib/compare.ts with one first-party URL and a quote under fifteen words taken verbatim from that page — or negative: true for a negative we established by searching the vendor's own docs rather than by assuming.

scripts/check-compare.ts fails the build when a claim has no source, when the source's host is not the vendor's own, or when the whole set ages past sixty days. It runs in CI, which is what makes the page's claim about itself true. The pages are views over that structure, not prose anybody has to remember to update.

We do not characterise a competitor from memory, from a third-party listicle, or from a comparison table they wrote about themselves.

Every vendor page says where they are better

Each one carries a section headed exactly that, and the build check requires it to have at least two entries. A comparison with no such section is a brochure, and a reader can tell in one scroll. LiteLLM is free and open source and ships complexity routing; that is on the page in our own words.

The position that survives is narrower and still ours: the counterfactual belongs on the request that caused it, in the response the caller already has. LiteLLM's savings figure reaches the operator in a rollup, after the fact. OpenRouter lists candidates and prices none of them. Portkey returns four headers and none of them is money.

The first draft got us, too

It claimed our own cost comes back "header and stream frame". It does not. On a streamed response our headers are written before the provider has counted a token — the same constraint that keeps cost out of a header everywhere — and our own metering docs say so one click away. The pages now name the path.


All posts