{"slug": "calnode-vs-calrs-vs-tymeslot-three-self-hosted-answers-to-calendly", "title": "Calnode vs. calrs vs. Tymeslot: three self-hosted answers to Calendly", "summary": "Calnode launched as an Apache-2.0 self-hosted Calendly alternative distributed as a single Go 1.26 static binary with an embedded SQLite database, requiring no Redis, Postgres, or separate API server. Calnode ships a REST API with 88 endpoints, HMAC-signed webhooks configurable via API, a native MCP server built on the official Go SDK with stdio and Streamable HTTP transports, and optional first-party LiveKit video rooms with recording and an AI notetaker exposed as MCP tools and webhooks. The project positions itself against cal.com, which it says spans 500k+ lines of TypeScript across roughly 100 packages and needs a 4 GB+ image with Redis, Postgres, and an API server, while Calnode runs from a single docker run command on a $5 VPS.", "body_md": "**A lean, self-hostable scheduling engine that lives in your AI stack.**\n\nCalnode is a Calendly-style booking app — with **first-party video meetings,\nrecording, and AI notetaking** built in — shipped as a **single Go binary** with an\nembedded **SQLite** database: no Redis, no Postgres, no separate API server, no\nmulti-gigabyte image. It's API-first, webhook-native, and built for a world where\nagents do the booking. Self-host the whole thing on a $5 box; nothing is paywalled.\n\nCalnode runs for pennies on a small VPS — it's a single static binary serving a SQLite file, so there's almost nothing to pay for.\n\n`Apache-2.0` · `Go 1.26` · `single static binary` · `SQLite + Litestream`\n\nKick the tires — one command, no config:\n\n```\ndocker run -p 3000:3000 -v ./data:/data ghcr.io/calnode/calnode:latest\n# → open http://localhost:3000\n```\n\nThe whole app — booking pages, admin UI, SQLite — in one container, with data in\n`./data`. With no encryption key set it runs on an ephemeral one (fine for a look;\nstored credentials won't survive a restart). **Deploying for real** — HTTPS, a\npersistent encryption key, backups — see **[Deploy for real](#deploy-for-real)** below,\nor the full **[DEPLOY.md](https://github.com/Calnode/calnode/blob/main/DEPLOY.md)**.\n\n- **One binary, one file.** Pure-Go SQLite (no CGO) compiles to a fully static\nbinary.`docker run` it, or drop it on a VPS. No external services to orchestrate\n(built-in video, if you turn it on, is the one add-on — it needs a LiveKit server).\n- **Meetings built in.** Optional first-party video rooms (LiveKit) as a booking\nlocation — guests join in-browser, no app or account. Recording lands in your own\nLitestream backup bucket (no extra storage to provision); an AI notetaker turns each\ncall into a transcript + notes, exposed as MCP tools and webhooks. The one add-on:\nvideo needs a LiveKit endpoint (Cloud or self-hosted).\n- **API-first, agent-ready.** A full REST API (88 endpoints) with API keys and**HMAC-signed webhooks configured *via API*** — script every booking action from\nClaude, ChatGPT, n8n, or curl. Plus a native**MCP server** built into the binary\n(official Go SDK; stdio + Streamable HTTP) so agents get first-class booking tools.\n- **Modern, no bloat.** Go backend + a SvelteKit 5 admin app; public booking pages\nare server-rendered Go templates for instant first paint and a tiny payload.\n- **Correct by construction.** DST-safe time handling (UTC instant + IANA name),\na transactional double-booking guard, and native-API calendar free/busy (never\nstale`.ics` feeds).\n- **Yours.** Instance-per-tenant by design — one deployment is one isolated\nworkspace, your data, your calendar credentials. No shared multi-tenant database.\n- **Easy to extend.** A clean Go codebase with`sqlc` -generated queries — not a\n100-package monorepo. Add an endpoint without spelunking.\n\nThe default open-source scheduler is a SaaS monolith. Calnode is the opposite.\n\n|  | cal.com | Calnode | \n|---|---|---|\n| **Codebase** | 500k+ LOC TS across ~100 packages | Lean Go + one SvelteKit app | \n| **Runtime deps** | 4 GB+ image; needs Redis **+** Postgres**+** API server | One static binary + a SQLite file | \n| **Database** | Postgres (+ Redis) | SQLite (WAL) + Litestream point-in-time backup | \n| **Webhooks** | UI-only | **API-first** , HMAC-signed, per-webhook payloads | \n| **AI / agents** | None | REST API + webhooks **+ a native MCP server** (stdio + HTTP) | \n| **Video & recording** | Third-party links (Zoom / Meet) | **Built-in in-browser rooms + recording + AI notes** (self-hosted LiveKit) | \n| **Deploy** | Orchestrate several services | `docker run` one container | \n| **Isolation** | Shared multi-tenant DB ( `org_id` everywhere) | Instance-per-tenant — isolation is the default | \n| **Licence** | AGPL-3.0 | **Apache-2.0** , nothing paywalled for self-host | \n\n*(cal.com figures reflect its public footprint; see the the design docs for the full rationale.)*\n\nIf you're weighing self-hosted schedulers and you want **small, fast, scriptable,\nand AI-ready** over feature-maximal, Calnode is built for you.\n\nEverything a human can do, an agent can do — over the API today:\n\n```\n# Find slots and book, with an API key\ncurl -s \"$BASE/v1/event-types/intro-call/slots?from=2026-06-16&to=2026-06-20&tz=Pacific/Auckland\" \\\n  -H \"Authorization: Bearer $API_KEY\"\n\ncurl -s -X POST \"$BASE/v1/bookings\" -H \"Authorization: Bearer $API_KEY\" \\\n  -H 'Idempotency-Key: 9f3c…' -H 'Content-Type: application/json' \\\n  -d '{\"event_type_slug\":\"intro-call\",\"start_at\":\"2026-06-17T21:00:00Z\",\"name\":\"Alex\",\"email\":\"alex@example.com\",\"timezone\":\"Pacific/Auckland\"}'\n```\n\nWire booking lifecycle events (`booking.created` / `.rescheduled` / `.cancelled`)\nto n8n / Make / your own service with HMAC-signed webhooks — all configured through\nthe API, not buried in a UI.\n\n**Native MCP server.** A Model Context Protocol server is compiled *into* the binary\n(official Go SDK), exposing eight first-class tools — `list_event_types`,\n`get_event_type`, `get_available_slots`, `create_booking`, `get_booking`,\n`reschedule_booking`, `cancel_booking`, `list_bookings`. The MCP tools call the same internal services as\nthe REST API (no parallel code path), so booking side effects — calendar events,\nconfirmation emails, webhooks, reminders — fire identically.\n\nTwo transports:\n\n- **stdio** for local agents — run`calnode mcp` (logs to stderr, JSON-RPC on stdout).\n- **Streamable HTTP** at`POST /mcp` for remote agents. Calnode is its own**OAuth 2.1\nauthorization server** (dynamic client registration + PKCE), so an agent adds the\nserver by URL and clicks**Connect** → signs in with the workspace's Google/Microsoft\nlogin → approves a consent screen — no pre-shared key. A`cno_` API key also works\n(`Authorization: Bearer <key>` ) for scripts.*(The Connect UX needs HTTPS — it shines\non a deployed instance.)*\n\n```\nUser:  \"Book a 30-min call with Wynne next week — I'm in Auckland.\"\nAgent: get_available_slots(\"intro-call\", \"2026-06-16\", \"2026-06-20\", \"Pacific/Auckland\")\n       → presents options → create_booking(…) → returns confirmation + meeting link\n```\n\n**Conversational booking — in the booking page itself.** Beyond agents, the booking page\n(and the embed widget) ships an optional **\"Book by chat\"** assistant: a visitor types\n\"free Tuesday afternoon or next week\" and it resolves real availability and books — the\ndeterministic engine still computes the slots (the model never invents times), and the\nassistant only ever sees free/busy windows, never your calendar contents. **Bring your own\nmodel** — any OpenAI-compatible endpoint (a hosted model or one you run yourself); off by\ndefault, with the standard calendar always there as the fallback.\n\n**Connecting Claude (remote / HTTP).** In Claude (claude.ai or Desktop) →\n**Settings → Connectors → Add custom connector** → enter `https://<your-instance>/mcp`\n→ **Connect** → sign in → **Allow**. Custom connectors need a paid Claude plan; the\nserver must be on HTTPS. *Local stdio alternative (any plan):* point an MCP client at\nthe `calnode mcp` subcommand via its config file — no OAuth, runs against the local DB.\n\n**Permissions.** MCP tools are **role-scoped**, mirroring the rest of the app: an\n**owner/admin** acts across the whole workspace, a **member** sees and manages only\nbookings they host. (The stdio subcommand is the local operator → full access.) Booking\n*creation* and availability are the public booking surface, open to all. Roles are fixed\n(owner / admin / member); configurable RBAC is intentionally out of the lean core.\n\n```\ndocker run -d -p 3000:3000 \\\n  -e BASE_URL=https://booking.example.com \\\n  -e CALNODE_ENCRYPTION_KEY=\"$(openssl rand -hex 32)\" \\\n  -e CALNODE_RECOVERY_SECRET=\"$(openssl rand -hex 32)\" \\\n  -e DATABASE_URL=sqlite:///data/calnode.db \\\n  -v calnode-data:/data \\\n  ghcr.io/calnode/calnode:latest\n```\n\n**Pinning a version.** `:latest` follows the newest tagged release; `:edge` tracks\n`main`. For reproducible deploys, pin a release — `:0.1` (tracks patches within the\nminor) or an exact `:0.1.0`. See [releases](https://github.com/Calnode/calnode/releases).\n\nOpen `/` → it redirects to `/admin/` and walks you through first-run setup (create\nthe owner account, connect a calendar, add an event type). Put a TLS-terminating\nproxy in front that forwards the original `Host` header.\n\n**Full guide → [DEPLOY.md](https://github.com/Calnode/calnode/blob/main/DEPLOY.md)** (env vars, Railway step-by-step, custom\ndomains, Resend email, Google & Microsoft OAuth, Litestream backups, troubleshooting).\n\n**Shipped**\n\n- Event types with per-type duration, location, custom questions, custom email copy\n- DST-correct availability (working hours, day-of-week rules, date overrides)\n- Team routing: **fixed · round-robin · collective · priority**\n- **Google Calendar & Microsoft 365 / Outlook** — native free/busy conflict checks\nbehind one provider abstraction; auto**Google Meet / Teams** links, minted only\nwhen the host's connected calendar matches the platform (else a manual link is used)\n- **Sign in with Google or Microsoft** (OAuth), email + password, or**passwordless magic-link**\n- **CalDAV calendars** — iCloud / Fastmail / Nextcloud via app-password (free/busy + event write-back)\n- Public booking + self-serve **reschedule/cancel** via signed manage links\n- HTML branded email (logo, banner, business name, size/opacity) with add-to-calendar links\n- REST API (88 endpoints) + API keys; **HMAC webhooks** with per-webhook payloads + delivery log\n- **Native MCP server** (10 tools incl. meeting notes + transcript; stdio via`calnode mcp` + Streamable HTTP at`/mcp` )\n- **Conversational booking** (\"Book by chat\" on the booking page + embed widget; BYO-LLM, off by default)\n- **Paid bookings** — Stripe Checkout (pay-then-book: the slot is held, confirmed on the payment webhook, auto-refunded on cancel)\n- **Zoom** — per-host OAuth; a Zoom-located booking mints a meeting under the assigned host's account\n- **Built-in video meetings (LiveKit)** — in-browser rooms as a booking location (no app or account for guests); host controls (end-for-all, hand-off**and reclaim** host, attendee screen-share toggle),**meeting recording** straight to your own**Litestream backup bucket** (the same one\nyou already use for DB backup — no extra storage to provision) with in-app downloads,**recording consent** (notice + consent-or-leave), and an**AI notetaker** (Deepgram transcript → LLM notes). Headless-consumable: MCP`get_meeting_notes` /`get_transcript` +`recording.completed` /`transcript.ready` /`notes.ready` webhooks. BYO LiveKit endpoint (Cloud or self-hosted); configured in Settings → Video — see[docs/VIDEO.md](https://github.com/Calnode/calnode/blob/main/docs/VIDEO.md)\n- **9 languages** on every booker-facing surface - booking page, manage/reschedule page,\nembed widget, all four emails, and the calendar invite:**English · Spanish · French ·\nCanadian French · German · Italian · Portuguese · Dutch · Swedish** . Picked from`Accept-Language` with a footer switcher and an operator-set fallback language; the\nbooker's choice is stored on the booking, so reminders arrive in the language they\nbooked in. Adding a language is adding one JSON file - no code change.*(The admin UI and the built-in video room are\nEnglish-only. Non-English translations are machine drafts without native review -\ncorrections by PR are very welcome.)*\n- Embeddable booking widget (Shadow-DOM web component; inline + popup)\n- Members, roles (owner/admin/member), email-token invitations\n- `Idempotency-Key` on booking creation; transactional double-booking guard\n- Envelope encryption at rest (secrets sealed with a KEK; recovery escrow)\n- Optional analytics: `<head>` code injection +`window.dataLayer` events (GTM/GA4)\n\n**On the roadmap**\n\n- OpenAPI spec · `/metrics` · multi-domain (one instance, many hostnames)\n\n- **Backend:** Go 1.26 · pure-Go SQLite (`modernc.org/sqlite` , CGO-free → static binary) ·`goose` migrations\n- **Admin UI:** SvelteKit 2 / Svelte 5 · Vite 8 · Tailwind 4 · shadcn-svelte (embedded at compile time via`go:embed` )\n- **Public pages:** server-rendered Go`html/template` + vanilla JS (no framework runtime)\n- **Durability:** SQLite WAL + optional Litestream replication (S3/R2) for backup & point-in-time restore\n- **Background work:** in-process job queue on the same DB — reminders, webhook delivery, calendar reconciliation. No broker.\n\nA few load-bearing decisions (full detail in the the design docs):\n\n- **The DB is the source of truth; external calendars are a projection.** A booking\nexists once it's committed locally; syncing to Google is a retryable side effect.\n- **Time = UTC instant + IANA timezone name** , never a fixed offset — availability\nresolves to UTC per-date so DST shifts never corrupt a slot.\n- **Single process, no external services.** Durability comes from Litestream, not a\nsecond datastore. (The one exception is optional built-in video: it talks to a\nLiveKit server — Cloud or self-hosted — only when you enable video.)\n- **Instance-per-tenant.** Each install is one workspace; isolation is a feature,\nand the self-host and cloud codepaths are identical.\n\nCalnode's backend is small enough to fit entirely in one LLM's context window —\nmost scheduling software (cal.com included) can't say that. **[AUDIT.md](https://github.com/Calnode/calnode/blob/main/AUDIT.md)**\nturns that into a self-serve check: a copy-paste scanner block (govulncheck, gosec,\ngitleaks across full history, SBOM, semgrep — all neutral, standard tooling you run\nyourself), an adversarial LLM prompt-pack for your own coding agent, and\n**[a claims → verification manifest](https://github.com/Calnode/calnode/blob/main/audit/claims.yaml)** mapping every security\nclaim we make to exactly how to check it in the source. Not a certification — a\ndue-diligence accelerator.\n\nSelf-hosting is free forever — `docker run` it and you own the whole thing. If you'd\nrather not run it yourself, **[Orchestratr](https://calnode.com/services)** — the team\nbehind Calnode — will deploy and operate it for you:\n\n- **Production deployment** on your infrastructure — VPC, private cloud, or bare metal\n- **SSO** (SAML / OIDC) integrated with Okta, Entra ID, or Google Workspace\n- **Calendar, Zoom & CRM integration** wired into your existing stack\n- **Migration** off Calendly / cal.com, plus bulk user & team provisioning\n- **Training & ongoing support** for your ops and IT teams\n\nBuilt for regulated and mid-to-large orgs that need Calnode on their own infrastructure,\nfully integrated. → [calnode.com/services](https://calnode.com/services)\n\n[Apache-2.0](https://github.com/Calnode/calnode/blob/main/LICENSE). The full scheduler is self-hostable, and nothing previously\nfree is ever paywalled.\n\nThe **code** is Apache-2.0; the **\"Calnode\" name and logo** are not — see\n[TRADEMARK.md](https://github.com/Calnode/calnode/blob/main/TRADEMARK.md) (use the code freely; name your fork something else).\nContributions are accepted under a [CLA](https://github.com/Calnode/calnode/blob/main/CLA.md) so the project can stand behind every\nline and keep its future licensing options open — see [CONTRIBUTING.md](https://github.com/Calnode/calnode/blob/main/CONTRIBUTING.md).", "url": "https://wpnews.pro/news/calnode-vs-calrs-vs-tymeslot-three-self-hosted-answers-to-calendly", "canonical_source": "https://github.com/Calnode/calnode", "published_at": "2026-09-29 01:38:16+00:00", "updated_at": "2026-09-29 01:47:32.320056+00:00", "lang": "en", "topics": ["ai-agents", "agent-protocols", "ai-tools", "developer-tools", "ai-products"], "entities": ["Calnode", "cal.com", "LiveKit", "SQLite", "Litestream", "SvelteKit", "Go", "Claude"], "also_reported_by": [], "alternates": {"html": "https://wpnews.pro/news/calnode-vs-calrs-vs-tymeslot-three-self-hosted-answers-to-calendly", "markdown": "https://wpnews.pro/news/calnode-vs-calrs-vs-tymeslot-three-self-hosted-answers-to-calendly.md", "text": "https://wpnews.pro/news/calnode-vs-calrs-vs-tymeslot-three-self-hosted-answers-to-calendly.txt", "jsonld": "https://wpnews.pro/news/calnode-vs-calrs-vs-tymeslot-three-self-hosted-answers-to-calendly.jsonld"}}