Bulletin is a job board that runs end to end on Cloudflare's free tier: Astro rendering on Workers, D1 for storage, SQLite FTS5 for search. No ORM, no client-side framework, and no third-party service you are obliged to sign up for.
It is a working board, not a template of one. Postings are submitted through a public form, paid for or not, approved at an operator's desk, published with valid JobPosting structured data, and closed by a cron when their window runs out — all without you touching the database.
For the public. The board, with filters for remote type, employment type, location and tag, each of which is also its own indexable page. Full-text search over titles, companies and descriptions through FTS5. Company pages, and apply links that count their clicks, minus the bots.
For posters. A submission form that takes a free listing, a paid one, or both. Stripe Checkout with inline prices, so you never create products in the Stripe dashboard. A signed manage link to check on a posting and close it early — no account, no password.
For the operator. An admin panel with a submission queue, review and edit screens for postings and employers, and settings — listing length, prices, whether posting is open at all — changed without a deploy. It ships zero client JavaScript: every action is a form POST followed by a redirect, so a refresh never repeats one.
For agents. A read-only MCP endpoint with four tools that mirror the public routes: search the board, filter it, read one posting, and list the employers hiring.
On its own. An hourly cron that closes postings whose window has run out. A sitemap and robots.txt built per request from the database. Structured data on every posting, where CHECK constraints make the schema.org vocabulary a guarantee rather than a convention.
Two skins ship with it — letterpress newsprint, and a modern hiring page — and switching is a one-line edit in a single CSS file. A skin owns the palette, the type and the shape of every surface, including whether the board is a run of ruled columns or a stack of cards; components name nothing but tokens, so switching is never a hunt through them. Both skins ship light and dark, and two homepage layouts are also one line apart.
Every integration is optional and degrades explicitly: Stripe, Resend and Google's Indexing API are each off until you configure them. A fresh clone with no secrets typechecks, runs, and serves a complete board seeded with 40 postings across 12 companies. 232 tests run in workerd against a real D1, and ten guides in docs/ cover the parts that need a decision.










