From f887086bec1726d3001e35a49a2730e86a4c928f Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Tue, 18 Aug 2026 14:35:03 +0000 Subject: [PATCH 1/2] Sell the feed: an ad format for RSS, Atom and JSON Feed Every unit so far assumed a runtime we control the shape of -- a browser running ad.js, or a terminal printing text. A feed is neither. The document is built by somebody else's static site generator, spliced into a whose root element we did not write, and then kept for weeks by software that remembers what it has already shown. So `feed_item` is a new format rather than a new renderer for an old one, and three constraints drove it. **No namespaces.** The RSS fragment uses core RSS 2.0 elements only and the Atom fragment core Atom only. A whose prefix the publisher never declared does not make our item ugly, it makes their whole feed not well-formed -- every reader drops the entire document rather than the one element. That rules out the advertiser name in dc: and the logo in Media RSS, both nicer, neither worth an outage for every subscriber of every publisher carrying the unit. A test asserts no prefixed element can appear. **No CSS.** Readers strip ${renderFeedHtml(creative, clickUrl)}`; + } + // Native text link — a borderless, full-width single line. No image/box. if (creative.format === "text_link") { const body = creative.body diff --git a/lib/ads/feeditem.ts b/lib/ads/feeditem.ts new file mode 100644 index 00000000..3ec710d7 --- /dev/null +++ b/lib/ads/feeditem.ts @@ -0,0 +1,699 @@ +// Feed ads — a creative rendered as a syndication item. +// +// The consumer here is neither a browser nor a TTY: it is somebody else's RSS, +// Atom or JSON Feed document, being built by a static site generator, a CMS, or +// a directory like rssamplifier.com. So the unit is not a box with pixels, it +// is an *item* — a title, a link, a date, an identity, and a body — spliced +// into a river of real posts every ~10 entries. +// +// Three constraints drive every decision below, and none of them apply to the +// web or terminal formats: +// +// 1. **No namespaces.** A fragment is pasted inside a `` whose root +// element we did not write. If we emit `` or `` +// and the publisher's `` never declared that prefix, the document is +// not merely ugly — it is not well-formed, and every reader drops the whole +// feed rather than the one item. So the RSS fragment uses core RSS 2.0 +// elements only, and the Atom fragment uses core Atom elements only (which +// need no prefix: they inherit the default namespace from ``). +// +// 2. **No CSS.** Feed readers strip `