Changelog

What changed in clndr.pro, newest first.

Also on docs.clndr.pro · RSS

  1. 1.2.0(latest release)

    Organization pages on your own website, and API keys for organizations

    • organizations
    • embed
    • api

    Embed & API, in every app. The page that used to be API keys is now Embed & API, and organizations have it too, under acme.clndr.pro/developers. Pick a booking page, choose inline, pop-up, floating button or a plain iframe, set the theme and an accent colour, and copy the code. Preview shows the widget the way your visitors will see it.

    Organization pages embed from the organization's own address. acme.clndr.pro/embed.js takes an organization page's slug as its link (link: 'demo'), or handle/slug for a member's own page, and the iframes live at acme.clndr.pro/embed/<page> and acme.clndr.pro/embed/<handle>/<page>. Bookings made in the widget are assigned exactly as on the page itself. Members-only pages can't be embedded, because they need a signed-in member; the widget says so instead of a bare "not found". The share dialog in an organization's app now gives embed code too. See Embed script.

    Organization keys. Admins and managers can make API keys that act for the organization: its own pages and every booking on them. @clndr-pro/react works with them unchanged (<BookingInline slug="demo" /> with the organization's publishable key), and GET /booking-pages/{slug} answers with the organization as userProfile. Bookings made with an organization key always need a slot the page offers, its publishable key leaves private pages out (they're for people with an access code), and confirming or cancelling one through the API sends the same emails as the Requests screen. A key stops working if the person who made it leaves the organization or stops being an admin or manager (401 API key is no longer active). Admins can revoke any of them, managers the ones they made.

    Members' own keys. Everyone in an organization can make keys for their own pages there, for example to put their work booking page on a personal site with the React components. They reach that member's pages and the bookings they take, and nothing of the organization's. Bookings made with them need an offered slot too, since their Meet links come from the organization's Google account.

    Fixes.

    • GET /booking-pages/{slug}/slots now returns the same slots the booking page shows, recurring busy events included. Before, it could offer a time that the booking then refused.
    • The organization's Settings, Organization and Home screens had no padding inside their sections. They do now.
  2. 1.1.0

    Organizations, each with its own app at its own address

    • organizations
    • booking
    • calendar
    • security
    • email

    Teams are gone. In their place, an organization gets its own clndr.pro at its own address, with its own accounts, booking pages and request queue.

    Create an organization from Organizations in the app. Pick a name and an address like acme.clndr.pro, and a work email and password for yourself. You land in the new app signed in as its owner, and your personal account is linked to it.

    Work accounts. People join by invitation: they get an email, choose a name, a handle and a password, and they're in. No devsforfun ID needed. Roles:

    • Admin: everything, including people, roles, settings and email.
    • Manager: organization pages, events and requests. Managers delete only what they created, and invite people as members.
    • Member: their own calendar, availability and booking pages, plus the directory and everyone's published pages.

    Organization booking pages live at acme.clndr.pro/<page> and are answered by the people you pick. With round robin, a booking goes straight to a free host, spread evenly. With assign by hand, it lands in Requests, where admins and managers see who's free at that time and give it to someone, confirming in the same step if they like. Hosts can take unassigned requests themselves. Members publish their own pages at acme.clndr.pro/<handle>/<page>, and can make a page members-only.

    Google Meet for everyone. Meet links and calendar events for an organization's bookings come from one Google account: the owner's by default, or an admin who offers their own. The guest and whoever takes the call are both invited.

    Your personal and work calendars, linked. Link a work account to your personal account (both sides confirm) and each calendar shows the other read-only, only to you: personal time as busy blocks in the work app, work events with titles in your personal calendar. Each side decides what leaves it: your personal account sets what the work app may see, and the work account sets what shows up at home. Anything shared blocks those times on booking pages on both sides.

    The organization's calendar. Admins and managers add events everyone sees, optionally emailing an invitation to all.

    Email from your own domain. Under Organization → Email, add your domain, put the DKIM records it lists in your DNS, and the organization's mail goes out from an address like bookings@acme.com through Amazon SES. Until then it comes from clndr.pro as "Acme via clndr.pro".

    Booking is stricter. Every booking is now checked on the server against what the page actually offers: the host's weekly hours, busy time (recurring events included), buffers and how far ahead. Private pages need their access code to book, not only to view. Deleted events no longer block times.

    Security. Closed several holes that let anyone with the public key read every user's email address, create meetings directly, read anyone's event titles or busy times, list private booking pages, guess access codes without a limit, or read and accept team invitations. Team-only booking pages became private pages.

    New accounts are open. Anyone with a devsforfun ID can sign up for a personal account again.

  3. 1.0.0

    app.clndr.pro, and the assistant on every page

    • assistant
    • calendar
    • booking
    • teams
    • api
    • design

    clndr.pro has version numbers now, and this is 1.0.0. Earlier releases were numbered after the fact, from the pull requests merged up to each one.

    New addresses

    • The app is at app.clndr.pro. Opening an app page on www.clndr.pro (/dashboard, /calendar, /login, …) redirects to the same page there. You'll sign in once more on the new address.
    • The REST API is at https://api.clndr.pro/v1. https://www.clndr.pro/api/v1 keeps working, so nothing you've built needs to change.
    • Booking pages, the embed and embed.js stay on www.clndr.pro. The docs stay at docs.clndr.pro.
    • New accounts are closed for now. Everyone who already has one signs in as before; anyone else is told so on the sign-in page.

    The assistant, on every page. Open it with Ask clndr in the header, or press ⌘J (Ctrl+J on Windows and Linux), from any page instead of only the calendar. It knows which page you're on, so "this booking page" or "this meeting" works.

    • It runs on Claude through the Anthropic API and picks a model per request: Haiku 5.5 for lookups and single changes, Sonnet 5.5 for plans that move several things at once. Opus 5.5 steps in only when a plan runs out of steps. Requests that only read can't change anything: that model gets no tools that write.
    • Replies render Markdown, so lists, tables, code and links arrive formatted.
    • Conversations are held on the server, and so is every change waiting for your approval. An approval only runs a change the assistant itself proposed; one made up in the browser, or sent twice, is refused.
    • Changes it makes show as a line you can undo. Reschedules come back as times you tap.
    • On desktop it docks to the right and the page makes room. On phones it opens full screen, stays above the keyboard and closes with a swipe down.

    Calendar

    • The grid fills the screen. The toolbar moved into the header; templates, import and export are in the ⋯ menu.
    • Month, week, 3 days, day and agenda. The view and date are in the URL, so back and forward work and links open where you left off. Phones start on agenda.
    • Month fits as many events per day as the cell allows. Week and day scroll to now and draw overlapping events side by side.
    • Click an empty slot to create an event; click an event for a quick view with join, edit, delete (with undo), approve and decline.
    • Keyboard: T for today, J/K or ←/→ to move, M/W/X/D/A for views, N to create, ? for the list. On touch, swipe to change the period.
    • Fixed: multi-day events that crossed the edge of the view were dropped, recurring events showed once, and event colours ignored the calendar's colour. The grid now uses your profile timezone, not the device's.

    Edits show up immediately. Pages keep what they've already loaded, so going back to one doesn't wait on the network. A change appears as soon as you make it and rolls back with a "Try again" if the save fails. Events check for edits made elsewhere: if an event changed after you loaded it, you get "This event changed elsewhere" with Reload or Overwrite, instead of quietly losing the other change.

    Every other page. One compact header, smaller controls with a mouse and 40px targets on touch, a bottom tab bar on phones and a sidebar that collapses to icons.

    • Dashboard: the next 7 days, today with a now-line, requests to approve inline, and your booking links.
    • Booking pages: one form for creating and editing, a Share dialog with the link and both embed snippets, analytics that read on a phone.
    • Availability: a weekly hours editor that works on touch, copies a day to the week and flags overlapping hours.
    • Meetings: grouped by day in your timezone; approve, decline, move and cancel from the list.
    • Guest booking pages: a month of open times loads at once, the guest's timezone is shown, and errors show on the page.
    • Teams: one dialog for team events, a members tab with roles and pending invitations.
    • Settings and API keys: one page each; a new key is shown once with the env var to put it in.

    Fixes

    • Guests far east or west of the host were shown another day's times.
    • New booking questions weren't saved when a page already had questions.
    • A failed save on availability could leave a set with no hours, and the assistant's bulk availability tools cleared every set.
    • New booking pages ignored "list on profile", "ask for a code" and "paused".
    • Managers couldn't edit their own team events, and saving a team event could drop its guest list.
    • Team invites: "already a member" never matched, duplicate invites were allowed, and the email match was case-sensitive.
    • Usernames could take app route names like settings or teams, which hid the booking profile.
    • The embed's theme option changed the host site's theme.

    API. Every /api route runs on one Hono app. v1 paths, request and response shapes, scopes and rate limits are unchanged; v1 404 and 405 responses now carry CORS headers too.

    Versions. The sidebar shows the version you're on next to What's new. This changelog, on docs.clndr.pro and at /changelog, covers every release back to 0.1.0, with an RSS feed at /changelog/feed.xml.

  4. 0.9.0

    Developer docs, slot dates that mean what they say, and a redesigned app

    • api
    • docs
    • design
    • booking

    docs.clndr.pro is live. Guides for the embed, @clndr-pro/react, @clndr-pro/sdk and the REST API, six tutorials (shadcn widgets, server actions, approvals, syncing bookings), an OpenAPI 3.1 spec at /openapi.json, and prompts you can paste into Claude Code. Every page is also Markdown at its own URL plus .md, indexed at /llms.txt, and there's an MCP server and a Claude Code skill: see Docs for AI tools.

    API: GET /booking-pages/{slug}/slots

    • date=YYYY-MM-DD now means that calendar day in the host's timezone. It used to be read as UTC midnight, so hosts west of UTC got the previous day's slots. Full ISO timestamps still work as before.
    • Slots that have already started are no longer returned, and days past the page's max_days_ahead return an empty list.
    • An unparseable date returns 400 instead of 500.

    API: POST /bookings

    • Bookings made with a publishable key must match a slot the slots endpoint offers right now: future, inside the host's hours, within max_days_ahead. Anything else is a 409. Secret keys can still book any time that doesn't overlap another booking.
    • A taken slot is now 409 (was 400), the guest-email limit 429 (was 400), and failures on our side 500 (were 400).
    • Bad emails, unparseable or reversed timestamps, and a responses that isn't an array get a 400 that names the field.

    Slots. A busy block that started inside a slot and ended with it (slot 9:00–10:00, meeting 9:30–10:00) was offered as free. Fixed for the API, the hosted page and the embed. Slots now come back sorted by start.

    Embed. https://www.clndr.pro/embed.js loads on third-party pages. It used to redirect to the sign-in page, so Clndr.inline, Clndr.modal and Clndr.floatingButton never ran.

    Dashboard. The API Keys page now names the real packages (@clndr-pro/sdk and @clndr-pro/react, not @clndr/*), shows an iframe embed snippet, tells you which env var each key belongs in, and links to these docs.

    The app, redesigned on Meridian

    • The dashboard is an agenda for the next 7 days instead of stat cards, with a callout when booking requests are waiting.
    • Meetings are grouped by day, and Approve and Decline say what the guest will get.
    • Booking pages are one list that works on phones, with a Live switch and Copy link on each row. Creating and editing a page share one form, with a Save bar that stays in view.
    • Availability is one row per day, with that day's total hours.
    • The sidebar is labelled and grouped, and remembers when you collapse it. Breadcrumbs show names instead of ids.

    Booking page. The meeting title leads, with the host, duration and time zone, and the times say which zone they're in. On pages that need approval, guests see "Request sent" instead of "Booking Confirmed!". The embed uses the same components. Your public profile shows your photo, and page descriptions there no longer show raw Markdown.

    Contrast and dark mode. Primary buttons had white text on amber (2.5:1, below WCAG AA); it's ink now (7.1:1). Inputs and switches no longer fade into dark backgrounds, and event pills on the calendar use ink or white, whichever reads better.

    Fixes. Analytics charts drew black bars. Settings showed an empty select for time zones outside its short list, such as Lisbon or Berlin. /booking/new threw a hydration error. The dashboard counted paused pages as active.

    Landing page. The hero shows someone asking the assistant to move a meeting, drawn with the app's own time rail.

  5. 0.8.1

    You stay signed in

    • auth
    • fix

    Sessions. You were signed out whenever your access token expired, overnight for example. Every request now renews an expired token from your refresh token, and open tabs renew it shortly before it expires and again when they wake up. If yours had already expired before this release, sign in once more; after that you stay signed in for as long as the refresh token lasts.

    Loading and errors. Pages show placeholders while they load and say so when something didn't load. The sign-in button shows that it's working.

    Terms and privacy describe what clndr.pro actually does and defer to the devsforfun policies. The support address, hello@devsforfun.com, is a link, next to the Grievance Officer and Contact pages. The footer links to Contact.

    Under the hood. Preview builds no longer need AI_TOOL_APPROVAL_SECRET. Without it, the assistant's approval route returns 503 and approves nothing.

  6. 0.8.0

    Meridian, a new calendar grid, and an assistant that can act

    • design
    • calendar
    • assistant

    Meridian. A new look for the app, the public pages and the embed: warm paper and near-black ink, amber as the one accent, Bricolage Grotesque headings, Geist text, and Geist Mono for times. A low horizon light sits behind the app. Dark mode has a switch in the user menu.

    Calendar

    • A new grid, built on FullCalendar. Drag an event to move it, drag either edge to change its length, drag across empty time to create one, and click an event for a quick view.
    • Calendars have names and colours, personal and team. Show or hide each one from the sidebar, and add one with the + next to My calendars.
    • Team calendars show up in your sidebar and on the main grid, and a team's own page uses the same grid.
    • A write to Google Calendar that fails is recorded and retried every 15 minutes. It used to fail silently.
    • The calendar fits the screen on phones, tablets and desktop, without the page itself scrolling.

    The assistant. Ask for what you want in plain language, from the calendar.

    • It reads your calendar (find events, check conflicts, availability, booking analytics), suggests new times from your real availability as cards you pick from, and makes changes: create, edit, move, cancel and delete events, cancel several at once, and email attendees.
    • It asks first before anything that cancels, deletes or emails someone, with a summary such as "This cancels 2 meetings and 1 personal event and emails 5 people". Every change is logged, and asking it to undo reverses the last one.
    • It also works on booking pages and their questions, bookings (approve and reject), availability, teams, settings and analytics. Actions that delete things or create and revoke API keys are built but switched off for now.
    • "Today" means your today: it gets the date and time in your timezone, not the server's.
    • Conversations are saved. Reopen an earlier one from the panel.
    • Replies stream in as they're written. The launcher snaps to a corner of the screen, the panel moves and resizes, and the calendar updates as soon as you approve a change.
    • Each request goes to a model for reading, changing or planning, through Vercel AI Gateway, with a fallback model for each and zero data retention. The reading tier has no tools that change anything.

    Fixes

    • Accounts created before calendars existed had no default calendar and couldn't create events.
    • Creating an event from month view hid the time picker.
    • A generated Meet link closed its dialog before you could see it.
    • The assistant's button was hidden by page containers, and a tap in Chrome on iOS didn't open it.
    • Every page scrolled about a sixth further than its content.
  7. 0.7.1

    Owner emails arrive again, and rate limits move to Postgres

    • email
    • api
    • fix

    Owner emails. Since the move to devsforfun ID, page owners weren't getting booking notifications. The owner's address was looked up in Supabase Auth, which no longer holds users, so it came back empty and the email was skipped without an error. clndr.pro now saves your email when you sign in and refreshes it every time.

    Email times. Emails show the meeting as one line, date and time range with the timezone, instead of separate When and Duration lines. Reschedule emails show the old start and end as well as the new ones.

    Rate limits. Limits run in Postgres, as an atomic fixed-window counter, instead of Upstash Redis.

    • API keys: secret keys get 300 requests a minute and publishable keys 120. A 429 carries Retry-After and X-RateLimit-* headers.
    • Bookings: 5 an hour per guest email address.
    • New API keys: 5 an hour per account.
  8. 0.7.0

    Sign in with devsforfun ID, a REST API, and a booking widget for your site

    • auth
    • google
    • api
    • embed
    • booking

    Sign in with devsforfun ID. One account for every devsforfun product. /login is a single button that hands off to devsforfun ID. clndr.pro no longer keeps passwords, so the register, forgot-password and reset-password pages are gone, along with the sign-up flags from 0.4.0.

    Google Calendar, through devsforfun ID. You link Google once, in devsforfun ID, and clndr.pro holds no Google tokens of its own.

    • A banner asks you to connect only when Google isn't linked or a calendar permission is missing.
    • Changes made in Google Calendar come back by webhook and update your calendar here.
    • Events you create, edit or delete here are written to Google. New events can repeat and can get a Meet link.
    • Approving or cancelling a booking updates its Google Calendar event. A booking waiting for approval gets its calendar event when you approve it.

    No double bookings. A booking is checked and saved in one database call, so two guests can't take the same slot. If the slot went in the meantime, the Google Calendar event made for it is cancelled.

    REST API. /api/v1/booking-pages and /api/v1/bookings, open to browsers through CORS. API keys come in two kinds: secret keys for your server and publishable keys for the browser, each with its own scopes. The API Keys page is back in the sidebar.

    Booking widget. /embed/<username>/<slug> is a booking page made to sit in an iframe on any site, and embed.js is a loader for it. The loader only worked on other sites from 0.9.0.

    Also. The phone sidebar closes when you pick a page or sign out. The /ai preview page is gone. Next.js 16.2.3.

  9. 0.6.1

    Email times in the host's timezone, and Markdown descriptions

    • booking
    • email
    • fix

    Email times. Emails printed times in the server's timezone, UTC, so a booking at 10:00 in India read "4:30 AM". Every email now uses the host's timezone: booking confirmations, owner notifications, reminders, reschedules, cancellations, and event invites, updates and cancellations. Hosts with no timezone set get UTC.

    Booked slots near midnight. The busy-time lookup cut days at UTC midnight, so a booking at 00:30 in India (19:00 UTC the day before) left its slot open. Days are now cut in the host's timezone.

    Markdown descriptions. Booking page descriptions take Markdown, with a Write and Preview editor. The public page renders headings, lists, links, images and tables.

    Shorter share links. Access-code links use ?c= instead of ?access_code=. Older links with ?access_code= no longer carry the code.

    Also. The booking page puts the host, page title and duration in one header above the calendar, with the same column order on every screen size. The landing page and footer were updated.

  10. 0.6.0

    Team event emails that say what changed

    • teams
    • calendar
    • booking
    • email

    Team event notifications

    • When you create a team event, choose who gets an email: everyone, the members you pick, or nobody. People outside the team can be added by email address.
    • An edit sends an update that lists what changed: title, description, location, start and end, all-day, Meet link, attendees. If only the attendee list changed, you choose whether to tell everyone, only the people added or removed, or no one.
    • Turn on Google Meet and the team event is created in Google Calendar, with a Meet link and invites for everyone on it. Deleting the team event deletes it there too.
    • Pick members from a searchable list with Select all, with each person's role next to their name.
    • Updates to personal events list their changes the same way.

    Look before you edit. Clicking an event or a team event opens its details, with an Edit button, instead of going straight to the edit form.

    Booking questions. Add, edit, reorder and remove the questions on an existing booking page. A removed question is kept for the bookings that already answered it.

    Privacy policy and terms at /privacy and /terms, linked from the footer.

    Fixes

    • Saving changes to a team event failed: fields that aren't database columns were sent along with the update.
    • The overlap check could miss events. It now compares start and end times directly, for events, meetings and team events.
  11. 0.5.0

    Google Meet links, attendees, and private pages you control

    • booking
    • calendar
    • google
    • fix

    Booking page controls

    • A third visibility, Private: the page needs an access code and has nothing to do with teams. Pages are now Public, Private or Team only.
    • Page is live turns a page off without deleting it.
    • Show on public profile keeps a page off /<username> whatever its visibility.
    • Show access code prompt: with it off, a private page looks like a page that doesn't exist.
    • A missing, paused or restricted page always says "Booking page not found". It used to tell signed-out visitors the page was private and ask them to sign in.

    Google Meet and attendees

    • Add a Meet link and attendees to an event or a team event. Attendees get an email invite with an .ics file. When you edit an event, choose who hears about it: everyone, only new attendees, or no one.
    • Auto-generate Google Meet link on a booking page gives each confirmed booking its own Meet link, included in the guest's confirmation email.
    • Meeting and team event details show the Meet link with Copy and Join.
    • Connecting Google Calendar from a dialog brings you back to that dialog instead of /calendar.

    Approve and reject ask first, and take an optional message that goes into the guest's email.

    Booked slots stay booked. A slot taken by a pending or confirmed booking was still offered, because the busy-time query read a column that doesn't exist (m.host_id) and returned nothing. Fixed. Rejecting a request frees its slot again.

    Event dialogs. A date and time picker replaces the browser's own: a calendar next to hour and minute lists. Moving the start keeps the event's length, and an end before the start resets to an hour after it. On phones and tablets the dialogs open full screen; on desktop the form is two columns.

  12. 0.4.0

    Team-only booking pages and access codes

    • booking
    • teams

    Team-only booking pages. A booking page can be public or limited to one of your teams. Team members who are signed in book as usual. Anyone else sees that the page is private, with a sign-in button. The team is optional: a page with no team is reachable only with an access code.

    Access codes

    • Generate a code for someone outside the team, valid for 1 to 100 days or until a date you pick. Codes look like ABCD-1234-EFGH-5678, or set your own: at least 12 characters, with at least 2 digits.
    • Share a link with the code in it, or the guest types the code under Enter access code on your profile page.
    • Wrong codes are limited to 5 tries per 15 minutes per IP address.
    • Revoke a code at any time. The list shows when each one expires and flags the ones with less than a day left.

    Bookings no longer fail when rate limiting is down. Bookings through access-code links failed in production: the Upstash Redis host didn't resolve, and the rate limiter threw before the booking was saved. The limiter now lets requests through when Redis isn't configured or can't be reached.

    Sign-up switches. Environment flags can close new sign-ups, including through Google, and hide the email and password forms, for an invite-only beta. Existing users can still sign in.

    Under the hood. Next.js 16.1.6. middleware.ts is now proxy.ts, as Next.js 16 requires.

  13. 0.3.1

    The person who creates a team is in it

    • teams
    • fix

    Teams. Creating a team adds you to it as an admin. That step ran with your own permissions, row-level security could reject it, and nothing checked, so the creator could end up outside their own team, which broke invites. It now runs server-side with the service role, and a failure is logged.

  14. 0.3.0

    Teams, with roles and shared events

    • teams
    • calendar

    Teams are back

    • Invite people to a team by email. Each member is an admin, a manager or a member.
    • Create, edit and delete team events. Events from every team you're in show on your main calendar.
    • Creating an event, personal or team, checks it against what's already on your calendar and flags overlaps.
    • Fixed: creating a team failed, team events hit a row-level security error, and team events were missing from the main calendar.

    Landing page and changelog. A new landing page with a waitlist form, a header and footer for the public pages, and a changelog at /changelog.

  15. 0.2.0

    Availability sets, and slots in your own timezone

    • availability
    • booking
    • fix

    Availability sets. Split your weekly hours into named sets and choose which set a booking page offers. A page offers all of your hours until you pick one.

    Booking fixes

    • Slots follow your timezone. Hours were read as UTC, so 14:00–16:30 set in India showed up as 19:30–22:00, and some days got slots they shouldn't have (a Saturday, for hours set Monday to Friday).
    • Guests can book from a public page. Booking failed with a row-level security error because it ran with the guest's session, and guests aren't signed in.
    • Google sign-in finishes when Google sends you back to the home page instead of the callback route.

    Hidden for now. The Teams and API Keys pages are off while they're being finished. The sidebar starts collapsed.

    Under the hood. React and Next.js 15 updated for security fixes, Vercel Analytics and Speed Insights added, and UUIDs come from pgcrypto instead of uuid-ossp.

  16. 0.1.0

    A working calendar, with booking pages

    • calendar
    • booking
    • availability

    The first version of clndr.pro. Sign in with email or Google.

    Calendar. Month, week and day views. Create, edit and delete events, and add attendees by email. Bookings sit on the calendar next to your events; click one for the guest's details.

    Booking pages. Each page has a duration, a buffer between bookings, how many days ahead guests can book, and your own questions for the guest. A booking is confirmed straight away, or waits on the Meetings page until you approve or reject it. Guests book at clndr.pro/<username>/<slug>, and clndr.pro/<username> lists your pages.

    Availability. Weekly hours. Booking pages offer slots inside them.

    Analytics. For each booking page, by day: views, bookings started, bookings completed, and the conversion rate.

    Early, and not finished yet: teams with a shared calendar and invites, API keys, event templates, importing from Google Calendar, and exporting your calendar as an .ics file.