Calendo:我如何在 Cloudflare Workers 上以無框架、無建置步驟打造 Calendly 替代方案
I built a Calendly alternative on Cloudflare Workers with no framework and no build step
作者獨自以 Cloudflare Workers、D1 和原生 HTML、CSS、JavaScript 開發排程應用程式 Calendo,並於上週以 AGPL 開源;專案沒有使用框架或建置步驟。儀錶板的 AI agent 透過與按鈕相同的函數執行操作,公開預約則使用欄位驗證表單,避免 AI 填錯電郵或預約時間。專案設有每日 AI 訊息用量上限,並有約 1,200 項單元測試。
This year I built Calendo, a scheduling app like Calendly, by myself. Last week I open-sourced it under AGPL. Here is how it's built and what I learned.
The setup
Everything runs on Cloudflare Workers. The database is D1, which is SQLite. The frontend is plain HTML, CSS and JavaScript. There is no React, no bundler and no build step. You edit a file and deploy.
I chose this for three reasons:
- Cost. The Workers free tier covers a lot of traffic. Serving a user costs me a fraction of a cent a month, so core scheduling can be free.
- Nothing to break. No framework upgrades. Code I write today will still run in two years.
- Easy to read. Any developer (or AI coding tool) can open a file and understand it.
The trade-off is more manual DOM code. For a solo project it has been worth it.
The AI agent
The dashboard has an AI agent. You can type "make a 30-minute intro call, Tuesday to Thursday afternoons, on Zoom, with a 15-minute buffer" and it does it.
The key decision: the agent calls the same functions the dashboard buttons call. Each action (create event type, change availability, cancel a booking, and so on) is a tool the model can use. So the agent can't do anything a user couldn't do by clicking, and every rule and check runs the same way.
An early lesson: don't let the AI handle exact data on the public booking side. A small model I tried made up email addresses and booked the wrong times. So for invitees, booking is always a normal form with validated fields. The AI is only used where a mistake is cheap and easy to see.
Keeping AI costs under control
Since the product is free, AI spending must have a ceiling. Each user gets a daily allowance of AI messages, stored in a small D1 table keyed by user, day and kind. One upsert per message counts and checks it at the same time. When the count passes the limit, the agent replies with a clear message instead of calling the model.
A demo that saves nothing
I wanted people to try a booking page without signing up. The demo page at calendo.dev/demo runs the full booking code path, including slot checks, and stops just before the database insert. No emails, webhooks or calendar calls go out. There's a test that books on the demo page and then checks that the bookings table is still empty and that no network calls were made.
Two Cloudflare surprises
- Exports from the main module matter. Cloudflare treats every export of the Worker's entry file as an entry point. If you export a plain constant from it, the Worker won't start, and normal unit tests can't see that. Now a test checks that the entry file only exports functions.
- Tests that pass locally can time out in CI. A test that sends 30 chat messages passed on my Mac but went over the 5-second timeout on GitHub's runners, which blocked a deploy. Deploys only run after CI passes, which is exactly what saved me there.
Testing
There are about 1,200 unit tests, plus an HTTP smoke test and browser tests. Many tests run the real schema.sql on an in-memory SQLite database (Node's built-in node:sqlite), so the SQL itself is tested, not a mock.
Try it
- Demo, no signup: https://calendo.dev/demo
- Hosted, free: https://calendo.dev
- Code: https://github.com/ravikant0909/calendo
I'd love feedback, especially on whether an AI agent is actually useful for something like scheduling.
來源:DEV Community · dev.to