A booking page you host yourself, with no per-seat fee.
Slot Keeper is the open-source scheduling page for one person or a small team. Set your weekly hours and it offers only the times you are really free, in each visitor's own time zone, then sends the invitation, a reminder, and a link to cancel or reschedule. Below, try the slot finder with your own hours and a pasted calendar. Everything on this page runs in your browser, so nothing is uploaded.
Try the slot finder
The server uses this exact code. Weekly standups from the sample block Monday and Wednesday at 10:00 New York time and keep that time across daylight saving. Slots are measured from the moment you load the page.
Why someone would use this
| Today | Catch | Slot Keeper |
|---|---|---|
| Calendly, SavvyCal, Acuity, Zoho Bookings | Priced per seat per month; invitee details live with them; reminders, buffers and multiple event types sit on paid tiers | Your server, unlimited event types and bookings, buffers, notice, reminders, no seat fee |
| Cal.com and other open-source schedulers | Full platforms: a database, a build, integrations to configure, real operations work | One Node process and one JSON file; deploys in a click |
| Back-and-forth email, "what times work?" | Slow, easy to double-book, nobody reminds the other side, time zones get muddled | One link; only free times; invitation, reminder and reschedule link included |
Honest limits: one host per booking page (no round-robin or team routing), it reads your calendar's busy time but does not write to it (subscribe to the bookings feed), no video-room creation (paste your meeting link), no payments, no mobile app, one admin key. Recurring events use the common rules (daily, weekly with days, monthly, yearly with count or end date); rarer rules count only their first occurrence and the admin page says so.
Run your own copy
Fork the repository, open https://render.com/deploy?repo=<your fork URL>, and Render builds it in your account with a generated admin key. Or docker compose up anywhere, or Fly.io with the steps in the repository. Add your calendar's secret iCal address as BUSY_ICS_URL and your Resend key to start sending invitations. Nothing runs on the author's accounts.
git clone https://github.com/Duncan-Haywood/oss-monorepo cd oss-monorepo/ventures/slot-keeper ADMIN_KEY=$(openssl rand -hex 16) COMPANY_NAME=Acme node server.mjs
Questions
Why not just use Calendly, Cal.com or SavvyCal?
Those are polished and the right call if you need teams with round-robin routing, payments, workflows and a mobile app. Calendly and similar tools charge per seat per month for the features beyond a single basic link, and your invitees' details live on their servers. Slot Keeper is one small Node server in your own account: unlimited event types and bookings, your calendar's busy time respected, invitations with calendar files, reminders and a cancel or reschedule link, with no seat fee. If you are one person or a tiny team that mostly needs a booking link, it covers the job.
How does it know I am busy elsewhere?
Paste your calendar's secret iCal address (Google Calendar, Outlook and Apple Calendar all offer one) into BUSY_ICS_URL. The server reads it every five minutes and never offers a time that overlaps an event, including recurring events, all-day events and different time zones. If the feed cannot be read it keeps the last good copy and warns you on the admin page. It reads busy time only; it does not write to your calendar, so subscribe to the bookings feed it gives you to see bookings there.
Does it handle time zones and daylight saving?
Yes. Your weekly hours are in your zone and each invitee picks theirs; times shift correctly across daylight-saving changes, and a time that does not exist on the spring-forward day is never offered. The demo on this page uses the same code as the server.
How are invitations and reminders sent?
Through your own Resend account with your verified sending domain. It starts in dry-run mode: bookings are saved but no email is sent until you set DRY_RUN=false with RESEND_API_KEY, MAIL_FROM and HOST_EMAIL. Each confirmation carries a calendar file the invitee's app adds to their calendar, and cancelling sends a cancellation file that removes it. A reminder goes out once, a day ahead by default.
Can invitees cancel or reschedule?
Yes. Every booking gets a private link. Rescheduling keeps the old time until the new one is confirmed and then cancels it, so nobody is left with nothing. Only the person who booked, with the right link and email, can change it.
What does it store?
Event types, and each booking's name, email address, optional note and time, in one JSON file you control. IP addresses are held in memory only for rate limiting. Set RETENTION_DAYS to delete old bookings. You are the operator and responsible for your privacy notice and data-protection duties.
Part of the self-hosted SaaS stack: 27 open-source tools you run yourself.