Structured job data as infrastructure

Discover once. Monitor forever. Repair automatically.

whitecontext turns any company's careers page into a monitored, structured job feed. A model writes a custom scraper for the page exactly once. After that, monitoring is deterministic, cheap, and self-healing.

One engine, three jobs

The discover / replay / repair split is the whole idea. The model only does the hard, page-specific work once; everything that runs on a schedule is trusted and deterministic.

01
Discover

What it does

Point whitecontext at a careers page and a model writes a custom Playwright scraper for that exact page — selectors, pagination, per-job detail extraction.

Why it matters

Every careers page is different. Instead of a brittle one-size-fits-all parser, each page gets a scraper shaped to its own markup, so the structured output is accurate from the first run.

Under the hood

The model self-tests the scraper it writes in an isolated sandbox, runs it against the live page, and checks the parsed jobs before the scraper is ever bound. Discovery happens once per page.

02
Monitor

What it does

A trusted, deterministic engine replays the bound scraper on a schedule, diffs the result against the last run, and records every job that opened or closed.

Why it matters

Monitoring is the part that runs thousands of times. Keeping it deterministic means it is cheap, predictable, and auditable — no model in the hot path, no token cost per check.

Under the hood

Each run produces a clean set of structured jobs plus a diff: new postings, closed postings, and edits. History is retained, so you can answer when a role opened and when it disappeared.

03
Repair

What it does

When a page redesign breaks the bound scraper, whitecontext detects the failure, marks the source, and re-runs discovery to write a fresh scraper.

Why it matters

Careers pages change without warning. Repair turns a silent breakage into a self-healing event, so the feed keeps flowing instead of going stale or wrong.

Under the hood

Breakage is a signal, not an outage: a structural mismatch or an empty parse against a non-empty page triggers re-discovery automatically, and the new scraper is self-tested before it replaces the old one.

Every posting, as the same structured record

Whatever a careers page looks like, the output is the same typed shape. Per-job detail extraction goes past the listing and reads each posting's own page, so fields like the full description, salary when disclosed, and employment type come through populated.

Because monitoring is deterministic, the record for a given role stays stable across runs — you get a real diff of what changed, not a re-parse that drifts.

job.schemaJSON
{"external_id": string  // stable id from the source ATS"title": string  // role title"url": string  // canonical posting link"location": string  // city / region / remote"department": string  // team or function"employmentType": string  // full-time, contract, …"salary": string | null  // when disclosed"description": string  // full posting body"posted": string  // ISO date the role went live}

Three ways to read the feed

The same monitored data is available as a dashboard for people, a REST API for systems, and an MCP server for agents.

GUI dashboard
Add companies, watch the feed fill in, and inspect every monitored source, its last run, and its diff history — no setup beyond a sign-in.
dashboard
app.whitecontext.dev/dashboard
REST API
Pull structured jobs and run history straight into your own systems. JSON in, JSON out, paginated and filterable by source, location, or date.
rest
curl https://api.whitecontext.dev/v1/jobs \
  -H "Authorization: Bearer $TOKEN" \
  -G --data-urlencode "company=acme"
MCP server
Expose the same feed to your agents as tools. An LLM can list monitored companies, fetch live openings, and read a job's full detail through MCP.
mcp
{
  "tool": "list_jobs",
  "arguments": {
    "company": "acme",
    "location": "remote"
  }
}

Built on Cloudflare, end to end

The whole system runs on Cloudflare's platform — edge compute for the surface, isolated sandboxes for the risky part, and managed storage for the data.

Workers
The API, dashboard, and MCP server all run at the edge as Workers — one deployment, global reach, no servers to keep warm.
Isolated Sandboxes
Discovery runs untrusted, model-written scraper code inside isolated Sandboxes, so generation and self-testing never touch your data or ours.
D1 + R2
Structured jobs and run history live in D1; full run artifacts — DOM, generated code, the session, the verdict — are kept self-contained in R2.
Scheduled monitoring
Deterministic replay is driven on a schedule, so every monitored source is re-checked and diffed without a model in the loop.

Even "no jobs" is a signal

Every monitored source resolves to one of a few explicit states, so an empty feed is never ambiguous. You always know whether a company is quietly not hiring or whether something needs attention.

bound
scraper works and is replaying on schedule
no_openings
a real careers page with zero open roles
no_careers
no careers page could be found for the company
broken
the bound scraper failed and repair is queued

See it on your companies

Add the companies you care about and watch the engine discover, monitor, and repair a structured feed for each one.