Book a seat. It's yours.
Community theater ticketing. Book your seats here. The box office checks reservations on the same backend — what you see is what they see. No double-booking, no confusion at the door. Seats are inventory; Dillo treats them that way.
The permissions are the app. This is the whole data model — schema.ts, the first of the app's three files (its import line, not shown, brings these names in from "create-dillo/schema"):
// The schema the live backend serves today (span2/live-schemas filing, re-verified at deploy).
export default schema({
Performance: table({
capacity: integer().min(1).max(500),
showId: relation('Show'),
startsAt: string().datetime(),
theaterId: relation.team(),
}).permissions({ view: anyone, edit: owner }),
Rental: table({
assignee: relation.user().optional().nullable(),
item: string().min(1).max(120),
theaterId: relation.team(),
}).permissions({ view: roles('actor', 'owner', 'volunteer'), edit: roles('owner', 'volunteer') }),
Reservation: table({
guest: string().min(1).max(120),
performanceId: relation('Performance'),
seats: integer().min(1).max(8),
theaterId: relation.team(),
}).permissions({ view: roles('box', 'owner'), edit: nobody }),
Show: table({
summary: string().min(1).max(500),
title: string().min(1).max(160),
}).permissions({ view: anyone, edit: owner }),
});