Study-room finder for ANU libraries

A shared study-space finder for the Menzies, Hancock, Chifley and Law libraries (81 spaces, all bookable 24/7). Book a one-hour slot; a booker can offer spare seats on a shareable booking and others can join. The problem it targets: a room booked for four is often used by one, and nobody else can tell or ask.

Status: all three tiers are built. You can browse real availability, book a one-hour slot and cancel it. Bookings are checked on the server (clashes, daily limits, the 14-day window, no past bookings) and stored in SQLite. A booker of a space with 2+ seats can offer spare seats, choosing how many they use and whether their name is shown (private by default, so others see “A student”). Others join directly and can leave; joins never count toward the daily limit, can’t overlap your own bookings, and can’t exceed capacity. “Open seats now” lists shared bookings with room across all libraries.

Tier 3: a joiner can check in, and the details panel shows “N joined · M checked in” live. Instead of joining, someone can ask the booker; the booker accepts (which joins them) or declines from the inbox, and can switch requests off per booking (pending ones are declined). My bookings lists requests still waiting for an answer, and the Check in button appears only once check-in is open. The inbox holds in-app notifications (requests and answers, joins, leaves, check-ins, a joined booking being cancelled) with a live unread badge. A requester never learns a private booker’s name, and messages never carry it. Changes and inbox pings arrive over server-sent events, which never carry who booked or whose inbox changed: a client asks /api/unread for its own count. Shared bookings carry a static “seats aren’t guaranteed” note.

Login is a fake demo login (u1000001-u1000005, password equals the username). It is not ANU sign-in.

What good looks like here

Enforced by spec/ and CLAUDE.md: route and accessibility invariants. Judgement calls: the visual design and the shared-pool assumption for booths.

Demo assumptions

Cut

Cut from Tier 3: marking single messages read (only “mark all as read”).

Also cut from the whole app: email and push, real SSO, maps, recurring bookings, admin tools, timers and auto-release of unclaimed seats.