Tabletop Time: A No-Login Scheduler Other People Build On

Christopher MelsonBuilder, Tabletop Time · Operational Architect
Core Design
Possession-based trust replaces authentication: device-local manager tokens and UUID magic links carry authority, with Telegram or Discord as optional recovery identities, so nobody ever creates an account
Integration Model
Third parties create events through a prefilled URL or POST /api/event, register a fromUrl callback, and receive CREATED, FINALIZED and CANCELLED webhooks carrying attendee and waitlist rosters
Live Example
gamethursday.win, an independent game-night site, hands event creation to Tabletop Time via a prefilled /new URL and receives finalization results at its own webhook endpoint, with attribution linking back

Key Takeaways

  • Tabletop Time (tabletoptime.us) is a scheduler built for one job: getting a tabletop group from "we should play soon" to a locked date with enough players, without anyone creating an account.
  • The origin is personal. My Magic: The Gathering group was dissolving, not from drama but from coordination failure. The general-purpose poll tools all wanted logins and felt like meeting software. So I built the tool I wanted.
  • The defining design decision is possession-based trust. There is no authentication anywhere in the product. Manager rights live in a device-local token, magic links restore them across devices, and Telegram or Discord are optional recovery identities, never requirements.
  • The scheduling logic is gamer-native, not meeting-native. Quorum thresholds, an "If Needed" vote, automatic waitlist promotion, and a campaign mode that locks a whole run of sessions at once. Doodle has none of these because meetings do not have minimum party sizes.
  • A free passion project ships a real developer API because an integration surface is the cheapest distribution there is. Any site can create events with a prefilled URL or a POST, register a webhook, and get the results back.
  • The proof it works is that someone else built on it. gamethursday.win routes its community's scheduling through Tabletop Time using exactly that surface, and did so without asking permission, exchanging credentials, or signing anything.

1. The Problem: Group Chat Is Where Game Nights Go to Die

Every recurring game night runs on the same failure loop. Someone posts "who's in for Thursday?" in the group chat. Four people react with a thumbs up, one says "maybe, depends on the kids' practice schedule," and two never answer. Thursday arrives, three people show up, and the game needs four. Repeat that cycle enough times and the group stops proposing dates at all, which is how a decade-old playgroup quietly ends.

The failure is not commitment. The people in that chat genuinely want to play. The failure is that a chat thread is a terrible data structure for the actual question, which is: across these candidate time slots, which one clears our minimum player count, and who exactly is in? That question has a shape. It has candidate slots, votes with three possible values rather than two, a quorum threshold, a capacity ceiling, and a decision moment after which the answer needs to be locked and pushed to calendars.

Scheduling tools existed, obviously. But the general-purpose ones are built for meetings, and it shows. They want an account before you can do anything, which is a real barrier when the person you need a vote from is the one who barely checks the chat. They treat every response as binary when game groups run on "I'll play if you need a fourth." And they have no concept of a minimum viable table, so they will happily declare a winner that two people can attend.

2. What Tabletop Time Is

Tabletop Time is a free, open source scheduler (github.com/mels0n/tabletop_scheduler) that treats game night as the first-class use case. The flow is deliberately short:

  1. A host creates an event: a title, candidate date and time slots, a minimum and maximum player count, an optional location.
  2. The host drops one magic link into whatever chat the group already lives in: Discord, Telegram, a text thread.
  3. Players vote on slots with three options: Yes, If Needed, or No. Nobody signs up for anything. Following the link is the whole onboarding.
  4. The system surfaces the winning slot, the first one that clears the minimum player count, and shows exactly who makes it viable.
  5. The host finalizes. The attendee list locks, capacity overflow lands on a waitlist, and everyone gets calendar output: Google Calendar links and an .ics file.
  6. If a confirmed player drops, the first person on the waitlist is promoted automatically. Nobody has to notice, chase, or re-poll.

There is also a campaign mode for the D&D case, where the question is not "when can we play once" but "lock the next six sessions." One voting round, multiple finalized slots.

Two properties sit underneath all of it. The hosted instance tracks nothing and events purge themselves within about a day of wrapping up, because a scheduling tool does not need a memory. And the whole product is self-hostable with Docker and SQLite for groups that would rather run their own, which is also the honest proof that the privacy posture is real rather than a landing-page claim.

3. Why It Exists

I have been playing tabletop games my whole life, and the build was triggered by watching my own group hit the failure loop described above. The tools I tried first all had the same two defects: they required my least-online friend to create an account, and they felt corporate, like being invited to a stand-up rather than a game.

The design goal that fell out of that experience was specific: the cost of participating had to be zero. Not low. Zero. One tap on a link, three buttons, done. Everything else in the product is downstream of taking that constraint seriously, including the part that usually makes people flinch: there is no login system at all.

There is no venture money behind it and no plan for any. It runs on the same principle as the rest of my side projects, which is that the best way to keep a skill honest is to ship something real with it, the same reason the homelab build notes on this blog exist.

4. The Core Design Decision: Possession, Not Accounts

Removing login is easy to say and uncomfortable to build, because accounts are how software normally answers three questions: who is allowed to manage this event, how does a person get their access back on a new device, and how do you recognize the same person twice. Tabletop Time answers all three with possession instead of identity.

Management rights are a token, not a role. When you create an event, your browser stores a manager token locally. Holding the token is what makes you the host. There is no user record to look up because there are no users, only events and the devices that hold their keys.

Recovery is a magic link, not a password reset. The obvious failure mode of device-local tokens is "I created the event on my laptop and I'm at work on my phone." The answer is a UUID magic link that re-establishes possession on the new device. Telegram and Discord slot in here as optional recovery rails: connect the event to the group's existing chat bot and your identity there can regenerate access, because you have already proven you are you by being inside the group's channel.

Recognition is optional and additive. A vote can bind a Telegram or Discord id, which is what lets a profile view assemble your events across devices. But a player who never links anything is a first-class citizen forever. The system degrades gracefully all the way down to "anonymous person with this browser," and every feature that can work at that level does.

This is a real trust-model tradeoff, not a free lunch. Possession-based systems trade away non-repudiation and account recovery guarantees in exchange for zero-friction entry. For a payments product that trade would be reckless. For "can Thursday work for six nerds," it is exactly right, and choosing trust machinery proportionate to what is actually being protected is a judgment call I care about professionally as much as personally. It is the same instinct as right-sizing any operating model: the control has to earn its friction.

5. Why a Free Tool Ships a Developer API

The less obvious decision is that a small free scheduler exposes a documented integration surface at tabletoptime.us/developers. Most side projects never do this. The reasoning is worth spelling out, because it is a strategy decision dressed as a technical one.

A scheduling tool is plumbing. Plumbing wins by being embedded, not by being visited. The people best positioned to embed it are other builders: the person running a league site, a club's homepage, a community Discord with its own web presence. Every one of them who wires Tabletop Time in becomes distribution that a zero-marketing-budget product could never buy. The API is not a feature for users. It is the growth model.

The surface is event-centric REST, and it inherits the product's trust model wholesale, which means the thing every third-party developer dreads, credential onboarding, simply is not there. No API key, no OAuth application, no partner form. The core of it:

EndpointWhat it does
POST /api/eventCreate an event. Accepts an optional fromUrl callback address for lifecycle webhooks.
GET /api/event/:slugRead event state: slots, votes, participant counts, status.
POST /api/event/:slug/voteCast or update a vote, optionally binding a Telegram or Discord identity.
POST /api/event/:slug/slot/suggestLet an attendee propose a new time slot.
POST /api/event/:slug/finalizeLock one slotId, or an array of slotIds in campaign mode.
DELETE /api/event/:slug/participant/:idDrop a player. Triggers automatic waitlist promotion on full, finalized events.
GET /api/event/:slug/icsCalendar export.

Two conveniences matter more than the endpoint list. First, deep-link prefill: a site can skip the API entirely and send a user to tabletoptime.us/new?title=...&minPlayers=3&maxPlayers=8 with slots pre-populated, which turns "integrate a scheduler" into "construct a URL." Second, lifecycle webhooks: whatever address arrives in fromUrl gets a POST when the event is CREATED, FINALIZED (with the full attendee and waitlist rosters, and a campaign flag for multi-session events), or CANCELLED, with retries every 5 minutes for up to an hour. Create with a callback, receive the outcome. That pair is the entire integration contract.

The licensing boundary is deliberately social rather than technical: the API is free for non-commercial community projects, with a visible "Powered by Tabletoptime.us" attribution link, and commercial use needs a written agreement. No enforcement middleware, just a clear norm, which is proportionate for the same reason the trust model is.

6. The Proof: What gamethursday.win Built

The reason I trust the reasoning in the previous section is that it stopped being a theory. gamethursday.win is an independent site built for a recurring Thursday game night, with its own branding, its own front door, and its own idea of how its community should feel. What it did not want to rebuild was scheduling mechanics, so it wired in Tabletop Time using exactly the surface described above.

The integration is compact enough to describe completely. When a member kicks off scheduling, the site takes its own event data (title, description, minimum and maximum players), constructs a prefilled tabletoptime.us/new URL, and appends a fromUrl pointing at its own endpoint, /api/integrations/tabletoptime/webhook, plus a correlation id so it can match the callback to the right internal record. The user lands on Tabletop Time with the event already built, the group votes through the normal magic-link flow, and when the host finalizes, the roster comes back to gamethursday.win's webhook. The site also carries a "Powered by Tabletop Time" card linking back, which is the attribution requirement working exactly as intended.

One Integration, No Credentials: the gamethursday.win Flowgamethursday.winBuilds prefilled /new URL:title, players, descriptionRegisters callback:fromUrl = .../tabletoptime/webhookPowered by Tabletop TimeTabletop TimeEvent created, prefilledGroup votes via magic linkYes / If Needed / NoHost finalizes the slotuser sent to prefilled /new URLwebhooks: CREATED, FINALIZED, CANCELLEDFINALIZED carries the attendee and waitlist rostersNo API keys. No OAuth. No partner onboarding.The contract is a URL out and a webhook back.
The whole integration is a prefilled URL in one direction and lifecycle webhooks in the other. gamethursday.win keeps its own identity and front door; Tabletop Time does the scheduling mechanics underneath.

I want to be precise about why this example matters more than a testimonial would. Nobody coordinated this with me before building it. The integration surface, the webhook retry behavior, and the attribution norm were all designed in advance for a consumer I could not see, and then a real one showed up and used them as designed. For anyone who designs systems for a living, that is the only test of an interface that counts: it worked for someone who never attended your design meetings.

7. The Professional Lesson Hiding in a Game-Night Tool

I write here mostly about operational architecture at enterprise scale, and Tabletop Time is about as far from a regulated-markets integration program as software gets. But the reason I keep building small products like this is that they force the same disciplines with none of the institutional cover.

The trust model had to be argued from what is actually at stake, not copied from convention. The integration contract had to be small enough to describe in two sentences, because no third-party developer owes a side project their afternoon. The licensing boundary had to be enforceable by norms, because there is no legal department. Every one of those is a scaled-down version of a decision I have made at $100M+ program scale, and the small version is in some ways harsher: when the entire adoption budget is "one tap on a link," you find out immediately whether your friction was earning its keep.

Is Tabletop Time free?

Yes. The hosted instance at tabletoptime.us is free, there are no ads and no tracking, and the code is open source. If you want full control, you can self-host it with Docker. Donations exist for people who want the hosted instance to keep running, and that is the entire business model.

Do my players need to install or sign up for anything?

No. Players follow a link and vote. That is the whole flow. Linking a Telegram or Discord identity is available for people who want cross-device sync and profile history, but it is never required.

Can I use the API for my own community site?

Yes, that is what it is for. Non-commercial community projects can use it freely with a visible "Powered by Tabletoptime.us" attribution link, the way gamethursday.win does. Commercial integrations need a written agreement first. The developer documentation lives at tabletoptime.us/developers.

What does the webhook integration actually require on my side?

One endpoint that accepts a POST. Pass its address as fromUrl when creating an event (or in the prefilled /new URL) and you will receive lifecycle callbacks for creation, finalization with the full roster, and cancellation, with automatic retries every 5 minutes for up to an hour if your endpoint is briefly down.

Original content published on chris.melson.us