For developers
OSLibrarian is one Cloudflare Worker in plain JavaScript with server-rendered HTML, backed by Cloudflare D1. Pages run no script except the passkey script on the sign-in and account pages. The source, tests and install steps are in the repository.
Open data on every library site
| Feed | Address | What's in it |
|---|---|---|
| Programs | /events.json | The library (under venue, the same shape as every OSCivic calendar, with its hours), links to the other feeds, and the next 90 days of programs: each date of a series as its own item with its series, local dates and times, offsets, room, who it's for, kind, how to sign up, price, whether cancelled and why, and each one's record |
| schema.org | /events.jsonld | The same programs as schema.org Event in a Library, each date of a series with its EventSeries |
| Library | /library.json | Address, hours, contact, time zone, accessibility details, rooms, booking address |
| Calendar | /events.ics | A calendar subscription; cancelled dates stay, marked |
| News | /feed.xml | RSS of upcoming programs |
| Search engines | schema.org on pages, /sitemap.xml, /robots.txt, /llms.txt | Library, Event and EventSeries with accessibility features |
| Records | /v1/records.json | Every published version of each program, each series and the library, with its provenance, under a Merkle root |
Every feed carries its provenance
The feeds and public pages are read from OSCivic core's keeper, through core's calendar module, not from the tables staff edit. Each program, each series and the library carry a record: its id, source, hash, when it became public and what it replaces. Dates, times, rooms, prices, cancellations, a series' days and changed dates, and the library's address, hours and accessibility details are relied-upon facts: changing one on something published needs a reason, and the reason and each change (from and to) are published with it. Titles and descriptions are stamped but need no reason. Drafts are never kept. A series is one record; its dates are worked out when a feed is read, and each date carries the series' record.
All feeds send Access-Control-Allow-Origin: *. None carries a requester's contact details. The README shows an example of events.json.
How it's checked
Every push runs the unit tests, then a walk-through of what a visitor, a room requester and staff do, including cancelling a story time date and adding a passkey, with axe-core WCAG 2.1 AA checks at desktop and phone width. After each deploy and every night, the walk-through runs against the demo library; a failure opens an issue.
Run it on your computer
Node.js 22: clone the repository (or download the source), then npm test, and follow "Run it on your computer" in the README to start a local copy with demo data.
Contributing
Pull requests are welcome. Database migrations only add; code more than one OSCivic project needs goes into OSCivic core first; every bug fix adds a test. See CONTRIBUTING.md.