Choose an extractor engine
Interrogate the page before writing selectors, and pick the cheapest engine that reads it reliably.
A binding configures one platform engine. The engine is Fruitful code that reads a page; the binding is your data that tells it what to read. Which engine you pick decides how stable the package is and what the route may declare.
The engines
| Engine | Reads | Use it for |
|---|---|---|
dom@1 | a browser snapshot | collections: lists of entries you select with CSS |
reader@1 | a browser snapshot | items: a whole article the platform reads into a webDocument |
media@1 | the URL | items: video and audio through the platform media pipeline |
rss@1, http@1 | a fetched body | declared today; their runtimes are the next slice |
The full table with what each emits is on Extractor engines.
Interrogate the page first
Before writing a selector, look at what the site already publishes. Capture the page once and read the capture's WARC and DOM, in this order:
- A feed or API the page advertises. A
<link rel="alternate" type="application/rss+xml">tag, or a JSON endpoint in the WARC that carries the same entries with stable ids. These are whatrss@1andhttp@1will read. Until their runtimes land, record the evidence (URL, response shape, id field) in the package notes and fall through. - Embedded structured data.
application/ld+json,__NEXT_DATA__, serialized store state, ordata-*attributes carrying ids and timestamps. Adom@1binding that reads attributes is more stable than one that reads visible text. - Visible DOM. Only then write selectors over rendered markup, preferring
data-testid, ARIA roles, and semantic elements over class names.
Collections use dom; items use the first-party bindings
A collection route needs an engine that feeds the transform, which today means dom@1. An item route that should be read whole uses a first-party binding instead of a package binding:
"bindings": [
{ "id": "front-page", "package": "com.ycombinator.news.binding.front-page@^0.3.0" },
{ "id": "reader", "package": "app.fruitful.binding.reader@^1.0.0" }
]app.fruitful.binding.reader, .video, and .audio are already in every registry. Pin them; never copy them into your definition.
What the engine allows on the route
Engines that read a snapshot open a browser, so their routes may declare login, load, ready, on, and scroll. Engines that never open the page reject all five. The registry enforces this at publish.
Reference: bindingDependency, Binding package.