A general-purpose benchmark host on Cloudflare Workers + D1. Publishers upload benchmark data on a schedule; visitors review benchmarks from publishers they choose to trust. smplmark does not validate the truth of the data, only its shape.
The v1 benchmark is scheduler-latency: each scheduler is a target that POSTs a
bare-timestamp beacon; skew_ms (how far past the top of the minute the beacon arrived) is
computed on read from the timestamp. See design notes for the full model.
- Stack: Cloudflare Workers + D1 (serverless SQLite), TypeScript, Hono for routing, json-logic-js for derived metrics, uPlot for the chart. No build step for the static UI.
- API: JSON:API (
application/vnd.api+json), singular resourcetype, parent refs as bare id attributes (norelationships).snake_casepaths and fields.
npm install
cp .dev.vars.example .dev.vars # local admin-stub token for `wrangler dev` (gitignored)
npm run cf-typegen # generate worker-configuration.d.ts from wrangler.jsonc
npm run db:migrate:local # apply migrations to the local D1
npm run db:seed:local # seed the smplkit account + scheduler-latency benchmark + demo data
npm run dev # wrangler dev — http://localhost:8787Then open:
http://localhost:8787/— home (data-driven "Recent benchmarks" grid)http://localhost:8787/benchmarks— published benchmarkshttp://localhost:8787/benchmarks/scheduler-latency— the data-driven benchmark page (Overview, Data, Methodology, Publisher tabs). The Data chart defaults to the last 24h UTC; the seeded demo data is dated ~2026-07-01T10:00–12:00Z, so pick "Last 30 days" (the widest range) to view it locally.http://localhost:8787/about— about smplmark
The seed creates two targets with fixed local-only ingest secrets (never use these in production — real secrets are generated server-side and returned once):
| scheduler | ingest secret | run id |
|---|---|---|
| scheduler-a | dev-secret-scheduler-a |
run-scheduler-a |
| scheduler-b | dev-secret-scheduler-b |
run-scheduler-b |
Post a beacon (empty body — the server stamps created_at):
curl -X POST http://localhost:8787/api/v1/runs/run-scheduler-a/samples \
-H "Authorization: Bearer dev-secret-scheduler-a"Read it back (JSON, then CSV):
curl "http://localhost:8787/api/v1/samples?filter[created_at]=[2026-07-01T00:00:00Z,2026-07-02T00:00:00Z)&filter[target]=tgt-scheduler-a"
curl -H "Accept: text/csv" "http://localhost:8787/api/v1/samples?filter[created_at]=[2026-07-01T00:00:00Z,2026-07-02T00:00:00Z)&filter[target]=tgt-scheduler-a"npm test # vitest (unit + integration, via @cloudflare/vitest-pool-workers)
npm run test:coverage # with coverage gates
npm run typecheck # tsc for the worker + the node-context configCoverage gates: 90% global (lines/branches/functions/statements) with 100% on the pure
modules (src/query, src/logic, src/serialize, src/auth/secret.ts).
All under /api/v1. Config writes are gated by an admin-stub (Authorization: Bearer $ADMIN_TOKEN);
public reads expose only published benchmarks and their targets/runs/samples.
| Method | Path | Auth | Notes |
|---|---|---|---|
POST/GET/GET{id}/PATCH |
/benchmarks |
admin-stub / public | list is published-only; filter[key], filter[account] |
POST/GET/GET{id}/PATCH |
/targets |
admin-stub / public | POST returns the plaintext secret once in meta.secret; filter[benchmark], filter[key] |
POST/GET/GET{id}/PATCH |
/runs |
admin-stub / public | filter[target], filter[key] |
| POST | /runs/{id}/samples |
target secret | ingest; empty body OK; uniform 401 on any failure |
| GET | /samples |
public | required filter[created_at] (max 30-day window); optional one of filter[run]/filter[target]/filter[benchmark]; Accept: text/csv for CSV |
This repo builds and tests entirely locally with no Cloudflare account. To deploy to
www.smplmark.org:
npx wrangler login(authenticate to the Cloudflare account).npx wrangler d1 create smplmark— copy the returneddatabase_idintowrangler.jsonc(it ships with a placeholder00000000-…).npx wrangler d1 migrations apply smplmark --remote.- Seed production structural data (an account + benchmark + targets). Do not ship the dev
secrets; create targets via
POST /api/v1/targetsand capture each returned secret once. - Set the admin-stub token as a secret:
npx wrangler secret put ADMIN_TOKEN. Until this is set, the config-write endpoints are locked in production (env.ADMIN_TOKENis undefined). It is deliberately not a committed var — a public token would let anyone modify config. npx wrangler deploy.- Attach the custom domain: add
"routes": [{ "pattern": "www.smplmark.org", "custom_domain": true }]towrangler.jsoncand redeploy (requiressmplmark.orgto be an active zone in the account).
migrations/0001_init.sql D1 schema (5 tables + indexes)
scripts/seed.sql local dev seed (generated)
public/ static UI (served by the Worker; uPlot vendored under vendor/)
src/
index.ts app.ts worker entry + Hono app (routes + static-asset fallthrough)
types.ts errors.ts domain row types + JSON:API error mapping
http/ envelope, error rendering, body parsing, content negotiation, admin mw
query/ range grammar, 30-day window, pagination, SQL predicates (pure)
logic/ json-logic evaluator + minute_offset_ms + compute-on-read merge (pure)
schema/ sample_schema validation/parsing (pure)
serialize/ row -> JSON:API resource, samples -> CSV (pure)
data/ D1 access (the only layer touching env.DB)
auth/ secret gen/hash + L1 ingest cache
routes/ benchmarks, targets, runs (+ ingest), samples
- Compute-on-read is the rule. Raw samples store only what was given;
skew_msand every other derived value are computed when the sample is read, fromsample_schema.derivedexpressions. The stored row commits to no interpretation. - Uniform 401. Every ingest-auth failure (missing/malformed/unknown secret, run/target mismatch) returns a byte-identical 401, to avoid leaking that a secret's shape was valid.
- Hot path. Ingest never calls out; a warm isolate authenticates from an in-memory
positives-only cache of
secret_hash → target, falling back to one indexed D1 read. - Deliberately deferred (v1): account signup / real tenant auth, private-read auth, windowed
aggregation (coverage / percentiles / downsampling), secret rotation,
DELETEon config resources. The data model already carries the multi-tenant hooks (account_id,visibility).