@mrfinch/booking
Real-time booking for Convex, as a component.
- ROLE
- Author & maintainer
- RELEASE
- v0.4.2 · published on npm
- API
- Typed queries & mutations
- HARDENED FOR
- Timezones · DST · midnight
@mrfinch/booking is a Convex component for booking rooms, equipment, people, pooled quantities, and combinations of them. Mount it in your app and call typed functions for resources, schedules, availability and bookings. It owns the inventory; your app owns access control and booking policy.
Why it exists
I first used Cal.com while building Jumper. As the booking flow grew, I wanted its state and availability checks to live in the same database as the rest of the app. A studio session can need a room, equipment and an engineer together; reserving only part of that would leave the band with a booking it cannot use. That became the reason to build my own engine and, later, extract it as a Convex component.
Getting it out of the app took a few attempts. My first monorepo package worked locally and broke on deploy: aliasing Convex's function builders got in the way of its static analysis. Moving to the official component template fixed that.

Install
import { defineApp } from "convex/server";
import booking from "@mrfinch/booking/convex.config";
const app = defineApp();
app.use(booking);
export default app;What is inside
Exclusive inventory uses a bitmap of 96 fifteen-minute slots per resource and day; pools track quantities. That keeps availability checks bounded by the days a booking spans. Weekly schedules support multiple time windows and date overrides. The host combines them with booking policies such as notice periods and buffers.
Reactive presence shows other visitors which slots someone is considering. The final booking mutation checks and reserves inventory atomically: that is what prevents conflicting bookings. A room plus two microphones plus an engineer either commits together or not at all. Provisional bookings, confirmation, cancellation and rescheduling share the same inventory model.
Transactional email goes through the Resend component mounted inside Booking. Apps can use the built-in templates or provide an optional, typed renderer through an internal Convex query. The app supplies the subject, HTML and plain text; Booking keeps responsibility for delivery. Without a custom renderer, the standard templates still work.

"It has no access to your ctx.auth, no access to process.env, and no opinion about users."From the docs, on what the component knows about your app
Where it runs
The engine grew out of Jumper. Its published npm package now powers the intro-call booking on this portfolio: a dedicated Convex backend, Berlin working hours with a break between two daily windows, private cancel and reschedule links, and guest notifications. On convexbooking.dev, anyone can try the public sandbox against data that resets every hour.
Version 0.4.2 adds the optional app email renderer. This site uses it for its own dark, textured email design. Changing that design now takes a portfolio deployment, without changing or republishing the component. The package also has regression tests for timezones, daylight-saving transitions, midnight boundaries and competing inventory reservations.

What is still missing
Two-way calendar sync is still missing, so an owner's external appointments do not yet block availability. The component handles individual bookings; recurring leases remain app-level logic in Jumper. It was submitted to the Convex component directory on 22 September 2026. Payments and identity stay in the host app on purpose.