Time-slot generator

Bookable time slots generated from rules: daily ranges, every first Monday of the month, one-off and whole-day slots, with seats, bookings, blackouts and the host's busy time taken out, safe to book under load.

Released
October 16, 2026
npx skills add timerise-ai/time-slot-generator
Current release
v0.1.3
Reference docs
10
Non-negotiables
5
License
MIT

What problem does Time-slot generator solve?

Every booking system has a list of times a client can pick. Nobody types those times in one by one: they come from rules such as "every weekday from 9 to 5 in half-hour slots" or "a class on the first Monday of every month", minus whatever is already booked, closed or taken.

The list is the easy part. The hard part is what happens on the Sunday the clocks change, when the server runs in a different time zone from the shop, when a monthly rule meets a week that starts mid-month, or when two clients press "book" on the last seat in the same second. Get one of those wrong and a slot disappears for a day, shows an hour late, or is sold twice.

This skill gives your coding agent the slot engine, written by the engineers who build the one inside a booking platform: rules authored in local time and stored as exact instants, seats, bookings, blackouts, the host's busy time, shared resources and working hours taken out, one availability check for both the list and the booking, and the last seat counted again at the moment it is booked. You own the code, run it on Next.js on Vercel, with Supabase or Firestore, under your own accounts.

What does the skill build?

An agent with this skill builds one module for a Next.js App Router app, on your stack. For Time-slot generator that module consists of:

  • 1. Daily ranges
  • 2. Nth-weekday-of-month rules
  • 3. One-off and whole-day slots authored in local time and stored as UTC
  • 4. Seats
  • 5. Bookings
  • 6. Blackouts
  • 7. Host busy time
  • 8. Shared resources and working hours subtracted
  • 9. One availability map for listing and booking
  • 10. Capacity re-checked inside the booking transaction
  • 11. Slot IDs that stay stable for existing bookings

Where do the rules come from?

This skill was written by the engineer who builds the slot engine of a booking platform, and audited against the earlier implementation of that engine. The templates hold the properties a slot engine has to hold: every weekday of a monthly rule appears in any viewport; local days survive both DST changes; limits count from the strategy, not the requested week; output is the same under any process time zone; nothing the listing hides can be booked by ID; and on ordinary windows the slot IDs are the ones existing bookings already hold. A 23-test suite run under four process time zones states each one, and `references/provenance.md` has the record.

This module is the slot engine of a booking platform, written down by the engineer who builds it: strategy storage, slot generation, availability and the booking path, audited against the earlier implementation and rebuilt as plain TypeScript served from Next.js route handlers, on Firestore or Supabase/Postgres. The earlier implementation was a long-running API server on a document database, and it had already been through one hardening pass: true-UTC storage with a read-time normalizer, local-calendar weekday and month bucketing, bounded listener caches, and a single generation per booking. The audit ran that engine against DST, far-from-UTC and viewport cases. On ordinary windows the templates produce the same slot IDs and instants as the earlier implementation, which the differential check in testing.md confirms.

The ledger separates what the audit changed, what was kept on purpose, and what has not run in production yet.

  1. Fixed in the templates

    • PERIODICITY dropped every weekday but the first when cut short Candidates were produced one weekday at a time, all Sundays of the month and then all Mondays, and generation returned at the first date past the cutoff. A one-week view returned only the Sunday. The same early exit fired on end.dateTime, on the booking window and on slotsLimit, so it also reached the booking path. Shipped: each month's dates are merged and sorted before emitting (generators.md).
    • A local day was skipped on DST transitions Days were advanced by adding 24 hours to an instant. When "now" was late in the evening before a 23-hour day, the next step landed two local days later; on a 25-hour day the same date came up twice and inflated slotsLimit counts. Shipped: iteration over YYYY-MM-DD local dates.
    • DAY_RANGE slots were 24 hours on 23- and 25-hour days The day slot ended at start + 24h, that is at 01:00 or 23:00 local on transition days, leaving an hour uncovered or double-covered. Shipped: slots run to the next local midnight.
    • Output depended on the server's time zone Local strings were parsed with new Date('...T09:00') (process zone) and weekdays read with getUTCDay() on a "zoned" Date (correct only in a UTC process). The earlier implementation ran in a UTC process, so it was latent; any other deployment or a developer laptop got different slots. Shipped: Intl-only helpers (timezones.md) and a suite run under four process zones.
    • slotsLimit and daysLimit counted from the viewport The count began at the viewport start, so "the first 10 slots" differed per requested week, and a slot shown in a later week was absent from the booking-path generation. Shipped: limits count from the strategy's first bookable slot.
    Show 6 more
    • The pinned strategy zone was never read Strategies stored their authoring timeZone, but generation used the project's current zone, so changing it reinterpreted every strategy. Shipped: strategy.timeZone ?? service.timeZone.
    • External busy time was converted twice or with the wrong zone Blocks stored both a wall-clock field and a UTC field; generation converted the wall-clock field with the project zone. Events stored as true UTC were shifted by the project offset; events from a calendar in another zone were off by the difference. Shipped: blocks are UTC instants only (availability.md).
    • Working hours compared clock strings "00:00" sorts before "17:00", so a slot ending at midnight passed 08:00 to 17:00 hours. Shipped: instants on the slot's local start date, with next-day closing.
    • Working hours applied to the listing only The booking path looked IDs up in a map built without the working-hours filter, so a slot hidden from the listing could be booked by ID. Shipped: one buildAvailability for both paths.
    • Malformed time strings became midnight An unparseable time either fell back to 00:00 or produced an invalid date and no slots, with no error either way. Shipped: strategy-time-invalid at write time.
    • A limit of zero produced one slot The limit was checked only after a slot had been yielded, so slotsLimit: 0 gave one slot while the documentation promised none; a stored null likewise stopped the strategy after its first slot. Shipped: 0 yields nothing, null means no cap.
Read the full record in provenance.md ›

What are the 5 rules the module never breaks?

Every module built from this skill holds these, whoever builds it. The same list is in the skill's README and SKILL.md, so the agent reads it before it writes a line.

  1. Never change the slot ID input.

    md5("<utcStartISO>;<duration>;<strategyId>") is the identity every client and every booking holds; a different input orphans them all. A test pins the format.

  2. Never infer "overnight" from end before start.

    A reversed range is far more often a typo than a night shift, so an overnight window needs overnight: true. The validation test refuses 17:00 to 09:00 and accepts the explicit overnight window.

  3. Never generate without a horizon.

    maxHorizonDays and maxSlots cap every strategy, since one with no end would otherwise generate until 2038. A test stops a strategy at a 10-day horizon, then at maxSlots, and expects truncated only in the second case.

  4. Never filter availability in the listing only.

    The listing and the booking path read one buildAvailability map, so an ID cannot book what the listing hides. Both entry points in service.ts call the same computeAvailability, and a test resolves booking IDs against that map.

  5. Never count a host's booking of this service as host busy time.

    It already subtracts seats as a BOOKING; blocking on it as well hides a slot that still has room. Both stores exclude the service from the host query, and SlotStore.listBusy states the rule.

When should you use it, and when not?

Use it for

  • Generating bookable slots from rules: "Monday to Friday 09:00 to 17:00 every 30 min", "first and last Friday of each month 18:00 to 20:00", "whole days, weekends only", "this one Saturday 10:00 to 14:00".
  • Showing availability: capacity per slot, minus bookings, blackouts, a host's other commitments, shared rooms or equipment, and outside working hours.
  • Booking slots by ID with a capacity re-check that holds under concurrent requests.
  • Fixing slot code with time-zone bugs, or moving one off wall-clock-as-UTC storage.

Not for

  • Booking screens, a walk-up terminalInsteadbooking-kiosk
  • Public scheduling links per host, calendar sync, e-mail invitesInsteadcalendar-scheduling-links
  • Ticketed events on one date, deposits, no-show holdsInsteadbookable-events
  • Invoices for bookingsInsteadinvoicing
  • Calendar recurrence (RRULE, iCalendar event series)Insteadrrule or the calendar provider's API

How do I install it?

One command. The skills.sh CLI installs the skill into every skills-compatible agent it finds.

$ npx skills add timerise-ai/time-slot-generator

Claude Code

Invoke with /time-slot-generator

Codex CLI

Invoke with $time-slot-generator

Gemini CLI

Invoke with /skills

Name the agents instead with -a, for example npx skills add timerise-ai/time-slot-generator -a claude-code -a codex. Or clone the repository into your agent's skills folder. Nothing in it is agent-specific.

What is inside the repository (13 entries)
  • SKILL.mdEntry point: trigger, architecture, adaptation contract, critical facts, hard rules, quick start, reference directory
  • references/adaptation.mdHost prerequisites, seam contract, rename table, integration points, order of work, the non-negotiables
  • references/strategy-model.mdStrategy types, bounds, limits, types, validation
  • references/timezones.mdUTC and wall clock, the DST policy, Intl helpers, the legacy normalizer
  • references/generators.mdThe engine, slot identity, horizon, cost
  • references/availability.mdBookings, blocks, resources, working hours, the service entry point, the booking path
  • references/supabase-backend.mdSchema, RLS, the store, book_slots
  • references/firestore-backend.mdCollections, indexes, the store, the transaction capacity check
  • references/nextjs-routes.mdThe server client, the listing and booking route handlers, error codes, environment
  • references/testing.mdThe suite, running it under four time zones, the differential check
  • references/provenance.mdThe audit ledger: fixed, kept deliberately, designed here
  • evals/prompts.md with what an operator types, and one file per agent eval run
  • .github/workflows/agent-eval.ymlRuns the agent evals on every published release

Recent releases

  1. v0.1.3October 16, 2026

    From scoring the prompt-1 agent eval runs against 0.1.2. No template changed.

  2. v0.1.2October 16, 2026

    Fix release, from scoring the dispatched prompt-1 agent eval runs against 0.1.1.

  3. v0.1.1October 16, 2026

    Security fix release, from scoring the prompt-1 agent eval runs against 0.1.0.

What do I tell my agent?

Say what you need in your own words; the skill supplies the how. These are starting points, and the ones we tested say how it went.

  1. Our studio books classes and private sessions from weekly opening hours, like weekdays 9 to 5 every 30 minutes and the first Saturday of each month. Add an API to this Next.js app on Supabase that lists the free times for a service and books one, without overbooking when two people take the last spot.

  2. Our booking times are an hour off after the clock change, and the week view sometimes only shows Monday. Fix how this app generates its time slots so it is right in every time zone our customers are in.

    Firestore
  3. Audit our availability code: customers can book times that the calendar does not show, and staff who are busy with another service still appear free.

How does it do in each agent?

We install the skill into an empty Next.js app, give the agent one of the prompts above and no further help, then type-check, build and run the tests it left behind. Nothing is fixed by hand before the checks, and a failing run is published like a passing one. The procedure and every result are public, and the first prompt runs again before each release.

  • Gemini CLI0.64.0

    gemini-3.8-flash

    Built, checks pass
    Our studio books classes and private sessions from weekly opening hours, like weekdays 9 to 5 every 30 minutes and the first Saturday of each month. Add an API to this Next.js app on Supabase that lists the free times for a service and books one, without overbooking when two people take the last spot.
    Typecheck: passBuild: passTests: pass
    Time
    3 min
    Changed
    19 files, +3,384 lines
    Stack
    Supabase
    Skill
    v0.1.3
    Run
    Oct 16, 2026

    Result file ›Agent log ›

    What we saw

    Rubric 8/8, scored from the final summary and the tool counts. It ran the copy command: two write_file calls and 120 lines written by its own tools, against 17 calls and over 2000 lines in the earlier runs. The handover is complete and the 23 shipped tests are counted apart from three in lib/slots/studio.test.ts. It still names the guard at line 29 of a route the command wrote with the guard at line 31, so its line numbers are its own count and were weaker evidence of drift in the earlier runs than those notes assumed.

  • Codex CLIcodex-cli 0.163.0

    gpt-6.1-sol

    Built, checks pass
    Our studio books classes and private sessions from weekly opening hours, like weekdays 9 to 5 every 30 minutes and the first Saturday of each month. Add an API to this Next.js app on Supabase that lists the free times for a service and books one, without overbooking when two people take the last spot.
    Typecheck: passBuild: passTests: pass
    Time
    2 min
    Changed
    21 files, +3,370 lines
    Stack
    Supabase
    Skill
    v0.1.3
    Run
    Oct 16, 2026

    Result file ›Agent log ›

    What we saw

    Rubric 8/8, scored from the transcript. It ran the quick start's copy command, then changed only the suite's node:test import and the test script; its final git status shows no other change to a template. Three tests of its own sit in lib/slots/service.test.ts, and the handover names the schema, both variables and the guard at route.ts:31.

  • Claude Code2.1.301

    claude-opus-5-5

    Built, checks pass
    Our studio books classes and private sessions from weekly opening hours, like weekdays 9 to 5 every 30 minutes and the first Saturday of each month. Add an API to this Next.js app on Supabase that lists the free times for a service and books one, without overbooking when two people take the last spot.
    Typecheck: passBuild: passTests: pass
    Time
    2 min
    Changed
    20 files, +3,356 lines
    Stack
    Supabase
    Skill
    v0.1.3
    Run
    Oct 16, 2026

    Result file ›Agent log ›

    What we saw

    Rubric 8/8, scored from the final summary. book_slots is left as shipped, both packages come from npm, the 23 shipped tests are reported apart from three of its own in lib/slots/studio.test.ts, and the handover names supabase/schema.sql, both server-only variables and the guard at app/api/bookings/route.ts:31.

How long does it take, and what does it cost?

We quote this module per project. The price depends on what it has to connect to. The path to a number is short and free:

  1. Step 1

    Brief

    Tell us what the module must connect to. Takes minutes, in a chat.

  2. Step 2

    Prototype in 48 hours

    A clickable prototype of your system and a quote, at no cost.

  3. Step 3

    Build and handoff

    One project price. Source code, documentation and IP are yours.

Two ways to get Time-slot generator

Build it yourself

Install the skill. Your own agent builds the module.

  • MIT licensed, no strings
  • Runs in Claude Code, Codex CLI and Gemini CLI
  • The same rules our engineers build by
$ npx skills add timerise-ai/time-slot-generator

Build it with Timerise

Send a brief. We build Time-slot generator into a system you own.

  • Clickable prototype and a quote within 48 hours, free
  • One project price, no subscription, no commission
  • Source code, documentation and IP handed over
3 years of support included.

Generated from the skill's own files at commit bb2cc36. Every rule above links to where the repository says it. All skills