Open-source appointment scheduling. Self-host in minutes.
Booking pages, calendar sync, video rooms, and automated emails — on your server. Built on Elixir/OTP so it keeps running while you're not looking.
Tymeslot is a scheduling platform you deploy yourself. Connect your calendars, set your hours, share a booking link — and it handles the rest: video rooms generated at booking time, confirmation emails with .ics attachments, configurable reminders, reschedule and cancel flows, and webhook notifications when anything changes.
Single Docker container. PostgreSQL included. Built on Elixir/OTP — designed to run unattended without falling over.
No tracking pixels. No analytics pipeline. No data leaving your server.
Evaluating alternatives? See how Tymeslot compares to Calendly.
docker run --name tymeslot \
-p 4000:4000 \
-e SECRET_KEY_BASE="$(openssl rand -base64 64 | tr -d '\n')" \
-e PHX_HOST=localhost \
-v tymeslot_data:/app/data \
-v tymeslot_pg:/var/lib/postgresql/data \
youruser/tymeslot:latestOpen http://localhost:4000 — your scheduling platform is running. For SMTP, TLS, and reverse proxy setup, see the Docker guide.
- No double-bookings — every connected calendar is checked at the moment of booking, not on a schedule; one conflict anywhere blocks the slot everywhere
- Availability that reflects reality — working hours per day, date-specific overrides for holidays, and vacation blocks without touching a calendar
- Buffer time — pad before, after, or both, per meeting type (0–120 min)
- Booking window — nobody schedules six months out without your permission (1–365 days)
- Minimum notice — enough lead time that you can actually prepare (0–168 hours)
- Timezone-aware — 90+ cities, DST handled correctly, browser-detected on the booking page
| Provider | Auth |
|---|---|
| Google Calendar | OAuth 2.0 with automatic token refresh |
| Microsoft Outlook / 365 | OAuth 2.0 with automatic token refresh |
| CalDAV | Username / password |
| Nextcloud Calendar | CalDAV |
| Zimbra | CalDAV |
| Radicale | CalDAV |
Connect as many calendars as you have. Assign each meeting type to whichever calendar it belongs in. If an integration goes down, you get an email — you won't find out from a missed meeting.
| Provider | Notes |
|---|---|
| Google Meet | Auto-generated via OAuth |
| Microsoft Teams | Auto-generated via OAuth |
| MiroTalk P2P | Self-hosted open-source WebRTC |
| In-Person / Phone | Location/phone in email, no link |
| Custom link | Static or dynamic URL |
Each meeting type picks its own provider — a sales call can use Meet while an internal sync uses MiroTalk.
Works with whatever you already use for identity:
- Email/password with verification flow
- Google OAuth, GitHub OAuth
- Generic OAuth 2.0 / OIDC — Keycloak, Authentik, Okta, Azure AD, or any standards-compliant provider
- Registration and password auth can each be disabled independently — SSO-only and closed deployments are first-class. See Configuration.
Email — responsive MJML templates, .ics attachment on every outgoing email:
- Booking confirmation — organizer and attendee
- Reminders — configurable count and timing (minutes/hours/days before), per meeting type
- Cancellation and reschedule notices — both parties, via signed guest links
- Integration health alerts — you hear about a broken calendar before your bookers do
Telegram — booking, cancellation, and reschedule alerts to your phone. Use a shared bot or configure a personal one per user.
Webhooks — HMAC-signed HTTP POST on meeting_created, meeting_cancelled, and meeting_rescheduled. Plug it into n8n, Zapier, Make, or your own backend.
- Attendees book without an account — name, email, timezone, optional message, done
- Every confirmation includes signed cancel and reschedule links — no login, no support ticket
- Attendees can propose a new time; the organizer gets notified and confirms
- Calendar events write on booking, update on reschedule, cancel on cancellation
Drop a <script> tag on any page and pick your embed style:
| Mode | Description |
|---|---|
| Inline | Renders the booking widget inline on the page |
| Popup modal | Full-screen overlay triggered by any element |
| Floating button | Fixed-position widget anchored to a corner |
| Direct link | Personal booking URL (/:username/:meeting-type) |
Embeds are signed (6-hour token expiry) and domain-locked — your widget, only on your site.
- Two themes — Quill and Rhythm, both with dark mode
- Accent color — override the brand color to match your identity
- Backgrounds — solid, gradient, image, or video, with presets if you'd rather not choose
- Four languages — English, German, Ukrainian, French, browser-detected with manual override
- White-label — strip Tymeslot branding entirely (Pro, cloud only)
Security is structural here, not bolted on after the fact:
- OAuth tokens and API credentials are AES-encrypted at rest — they never appear in logs as plaintext
- Rate limiting on every public endpoint: booking, auth, and embed
- No third-party analytics, tracking pixels, or outbound data of any kind
- CSRF on all forms, HMAC signatures on webhook payloads, signed tokens on embeds and guest links
- Optional reCAPTCHA v3 and honeypot fields on all public forms — see Configuration
Dashboard
Booking Page
Embed Widget
| Method | Guide | Notes |
|---|---|---|
| Docker | README-Docker.md | Recommended for most self-hosters |
| Cloudron | README-Cloudron.md | One-click install, automatic updates |
| Railway | Deploy → | One-click, no server management |
| Cloud | tymeslot.app | Managed, zero setup |
Key environment variables for self-hosted deployments.
Required:
| Variable | Description |
|---|---|
SECRET_KEY_BASE |
Generate with openssl rand -base64 64 |
PHX_HOST |
Public hostname for URL generation |
Access control:
| Variable | Default | Description |
|---|---|---|
REGISTRATION_ENABLED |
true |
Set false to close sign-ups |
PASSWORD_AUTH_ENABLED |
true |
Set false for OAuth/SSO only |
Spam protection (optional):
| Variable | Default | Description |
|---|---|---|
RECAPTCHA_SITE_KEY |
— | Enables reCAPTCHA v3 |
RECAPTCHA_SECRET_KEY |
— | Pair with site key |
RECAPTCHA_SIGNUP_ENABLED |
false |
reCAPTCHA on signup |
RECAPTCHA_BOOKING_ENABLED |
false |
reCAPTCHA on booking |
For the full configuration reference (SMTP, database, OAuth provider credentials, etc.), see the Docker guide.
Set REGISTRATION_ENABLED=false to close sign-ups without taking the app down — useful for invite-only or single-user deployments. When disabled, the sign-up page is hidden and OAuth registration is rejected; existing users continue to log in normally.
Set PASSWORD_AUTH_ENABLED=false to hide the email/password form entirely and require OAuth or OIDC. Direct POST /auth/session requests are rejected with an error. Existing users with passwords can still sign in via OAuth if configured.
Report security vulnerabilities via the contact page.
| Layer | Technology |
|---|---|
| Language | Elixir 1.19 / OTP 28 |
| Web | Phoenix 1.8 · Phoenix LiveView 1.1 |
| Database | PostgreSQL 14+ · Ecto SQL |
| Background jobs | Oban |
| Frontend | Tailwind CSS · Alpine.js · ESBuild |
| Swoosh · MJML | |
| Deployment | Docker · Cloudron |
| Tymeslot | Calendly | |
|---|---|---|
| Open source | ✅ ELv2 | ❌ |
| Self-hosting | ✅ Free forever | ❌ Not available |
| Data ownership | ✅ Your infrastructure | ❌ Their servers |
| No tracking | ✅ | ❌ |
| Unlimited event types | ✅ Free tier | ❌ 1 on free plan |
| Calendar providers | 6 | 3 |
| Webhooks | ✅ Free tier | ❌ Paid only |
| SSO / OIDC | ✅ Free tier | ❌ Enterprise only |
| Telegram notifications | ✅ Built-in | ❌ |
| White-label | ✅ €5/mo | ❌ $16+/user/mo |
Free — self-hosted or cloud. Full feature set, all integrations, unlimited bookings, no credit card required.
Pro — €5/month (cloud only). White-label branding, priority support, early access to new features.
Self-hosting is always free. No feature restrictions, no licensing fees, ever.
See CONTRIBUTING.md for local setup and the PR process. Bugs and feature requests go in Issues.
Elastic License 2.0 — free to use and self-host; commercial redistribution requires a separate agreement.
Built by Luka Karsten Breitig · Diletta Luna OÜ · Tallinn, Estonia
Built with Elixir, Phoenix, and LiveView


