Build your run of show backwards from when the night ends

Answer when it ends and how long each part takes; the platform derives setup, doors, showtime and teardown for you — and stores them in UTC.

Owned by Host / Promoter · 17 steps · about 16 minutes

Why this exists

The application form used to ask for five timestamps: setup start, doors, main start, main end, teardown end. Hosts got them wrong constantly, and always in the same way — not because they did not know their own night, but because nobody plans a show forwards. You know the curfew. You know how long your headliner plays. Everything else is arithmetic somebody was being asked to do in their head, at midnight, on a phone.

So the builder asks the questions you can actually answer — when does it end, how long is the headliner, how long are the openers, how long is clean-up, how long is setup, how early are doors — and walks the schedule backwards from the end. Five timestamps still get stored. You just stop being the one computing them.

The midnight rule — read this twice

An event day is not a calendar day. The platform defines the day for a date as local 6am to 6am, so an end time before six in the morning belongs to the next calendar date. Saying "Saturday the 14th, ends at midnight" therefore means Sunday the 15th at 00:00 — which is what you meant — and the backwards walk lands setup on Saturday evening.

Concretely, with a two-hour headliner, 45 minutes of openers, doors 30 minutes early, two hours of setup and an hour of clean-up:

  • Setup starts Sat 14 Mar, 6:45 PM
  • Doors Sat 14 Mar, 8:45 PM
  • First act Sat 14 Mar, 9:15 PM
  • Music ends Sun 15 Mar, 12:00 AM
  • Teardown ends Sun 15 Mar, 1:00 AM

One night, two calendar dates, and that is correct. The preview labels every row with its own day for exactly this reason, and the card carries an ends after midnight badge so nobody has to notice it on their own.

Local in, UTC out

Every time you see is the venue's wall clock — not your phone's. A host applying from New York for a Los Angeles room types Los Angeles times, and the browser is never asked what time it thinks it is. What gets stored is UTC. In the worked example above, all five stored instants fall on 2026-03-15 in UTC, including the setup that happens on Saturday evening locally. That is not a bug and you will see it on staff screens: the stored date and the local date are allowed to disagree.

The derivation runs on the server, once. The page has no timezone logic of its own — it collects your answers, posts them to a preview endpoint, and draws whatever comes back. A second implementation in the browser would drift from the first, and it would drift precisely on daylight-saving weekends and midnight crossings, which is where being wrong actually costs something.

Pinning: the escape hatch, not the default

Every derived row has an edit button. Use it and that row is pinned — it stops being computed, keeps the exact time you typed, and is marked with a pin in the run of show. The other rows keep deriving around it. A pin is reversible from the same button, which then reads reset.

Pins exist because reality has load-ins that start at 2pm for a 10pm show, and no duration answer expresses that. They are not the way to use this feature. A pinned row that puts the schedule out of order is refused with a message on that row, and the offer to undo your pins rides on the error itself.

Before you start

  • No account. The application form is public.
  • A date for your event, and honest answers about how long each part takes.
  • The venue's timezone is shown on the form. Everything you type is in that clock.

Practise with

PersonaEmailPasswordNote
host_promoterhost@club.test host123owns the seeded applications, including one entered through the guided builder
venue_managermanager@club.test manager123reads the stored run of show on the application review page
adminadmin@club.test admin123owns the derivation trace and the timezone health check

Steps 1–12 — Host / Promoter

their manual →
  1. 1
    Open the application form and scroll to the run-of-show section. Read its one-line lede: it names the timezone every answer on this form is in.
    /host/apply intake
    Expected result Six questions and an empty run-of-show card that says it will fill in once you answer.
    Watch out for That timezone is the venue's, not your device's. If you are applying from another city, do not mentally convert — type the times the night actually happens at.
  2. 2
    Set the event date first. The whole derivation hangs off it, and until it is set the preview stays empty however many other answers you give.
    /host/apply intake
    Expected result The date field accepted; the card still empty.
    Watch out for This is the date the night starts in the ordinary sense — the Saturday, not the Sunday you go home on.
  3. 3
    Answer Event ends at. There are three presets — Midnight, 10pm, 8pm — plus Other… for an exact time. This is the anchor: every other row is computed backwards or forwards from it.
    /host/apply intake
    Expected result The question collapses to a summary chip showing your answer.
    Watch out for Choosing Midnight on a Saturday means Sunday 00:00. You are not saying the night ends 24 hours ago — the day-rollover rule handles it, and the preview will show you the Sunday label on that row.
  4. 4
    Answer the four duration questions: Headliner set length and Clean-up time are required; Opener time (all openers together) and Doors before first act are optional. Setup time is required too.
    /host/apply intake
    Expected result Each answered question collapses; the next unanswered one is highlighted.
    Watch out for Openers is the total for all of them, not each. And setup is measured back from doors, not from showtime — two hours of setup with doors 30 minutes early puts your load-in two and a half hours before the first act.
  5. 5
    Watch the run-of-show card fill in as you answer. It posts your answers to the public preview endpoint and renders the five rows it gets back, each with its local time, its day label and its UTC instant.
    Expected result Five rows, the gaps between them, a total duration, and any badges.
    Watch out for The preview writes nothing and needs no application — it is a pure calculator, and it is rate limited per IP. If it is unavailable the form still submits: the server re-derives from the same answers, so a missing preview costs you the picture, never the schedule.
  6. 6
    Read the badges under the card. Ends after midnight tells you the night crosses a date. Setup before the event date tells you your load-in starts on the previous day. A clocks-change weekend gets its own badge, and each row starts showing its timezone abbreviation.
    Expected result Badges that describe your schedule in words, not just colours.
    Watch out for A midnight-or-later finish also raises a late-night suggestion. That is advice about a contract clause, not a validation error — nothing here blocks you.
  7. 7
    If the clocks change during your night, the form asks one extra question: that wall-clock time happens twice, which one did you mean? Pick the earlier or the later.
    Expected result The fold question appears only when it is genuinely ambiguous.
    Watch out for A time that does not exist at all — the hour that is skipped when clocks go forward — is refused with a suggestion of the next valid time. There is no silently-rounded answer here, because 2:30am on that Sunday is not a moment.
  8. 8
    Pin a row you cannot express as a duration. Press edit on it, type the exact local time, and save. The row gains a pin marker and its button becomes reset.
    /host/apply intake
    Expected result That row keeps your time; the others keep deriving around it.
    Watch out for A pin that puts the schedule out of order — teardown before the music ends — is refused on that row, and the last good run of show stays on screen dimmed rather than vanishing. The message carries an undo for all your pins, which is the fastest way out.
  9. 9
    Finish the rest of the form and submit. The server re-derives your schedule from the same answers and stores five UTC instants.
    Expected result A 201 and the thank-you page.
    Watch out for Two submit modes exist and they are chosen by what you send. Answering the guided questions uses the derivation; posting five explicit timestamps uses the old direct path. Sending both is a 422 telling you they conflict — it will not guess which one you meant.
  10. 10
    Read the run of show back on the thank-you page. This is the stored schedule, projected into the venue's clock — the same rows staff will see.
    /apply/thanks/{app_id} intake
    Expected result Your five moments, with their day labels.
    Watch out for Check the day labels one last time here. A schedule that reads 'ends Sunday' when you meant Saturday afternoon is trivial to fix now and awkward to fix after a manager has already read it.
  11. 11
    If staff ask for more information, the emailed edit link reopens the form with your schedule loaded back into the guided questions.
    /apply/edit/{token} intake
    Expected result The builder, pre-answered, with your existing times reproduced exactly.
    Watch out for One thing does not survive the round trip: the split between headliner and openers. The reverse mapping resolves it as the whole programme being the headliner with no openers, because that reproduces your five stored instants byte for byte. Re-split it if you care about the distinction.
  12. 12
    Save the edit. The schedule is re-derived and re-stored from whatever the questions now say.
    /api/intake/public/applications/{app_id} PUT intake
    Expected result The application returns to under review with an updated card in the staff channel.
    Watch out for Timeline answers never prefill from a previous application, and they never count toward the red confirm gate on returning-host autofill. Every night gets its own schedule, deliberately.

Steps 13–14 — Venue Manager

their manual →

Reviews the stored schedule on the application, in the venue's clock, before approving it.

  1. 13
    Open the application and read the run of show in the timeline panel. It is rendered in the venue's timezone, with the same day labels the host saw.
    /admin/intake/{app_id} intake
    Expected result Five rows plus the badges, matching the host's screen.
    Watch out for The date on the application and the date on the stored setup time are allowed to differ by a day, in both directions. Before you query it with a host, check whether you are reading a UTC instant next to a local clock — that difference is the feature working, not a typo.
  2. 14
    Scan the board for midnight-crossing nights. The seed deliberately ships one — Midnight Cassette — entered through the guided builder with a midnight end, so the board always has a crossing row to look at.
    /admin/intake intake
    Expected result An application whose schedule spans two dates.
    Watch out for Late-night nights carry contract consequences. Noticing the crossing at review time is what lets you check the right rider is on the paperwork.

Steps 15–17 — Admin

their manual →

Owns the derivation trace and the timezone health check when a schedule looks wrong.

  1. 15
    When a schedule looks impossible, replay the derivation with the same inputs. The trace prints which rollover branch was taken, how the local time was resolved, and every step in both projections.
    Expected result A full derivation trace, answering 'why is setup on the 13th'.
    Watch out for There is also a built-in fixture table of known cases. If it reports any failures, the model itself is broken, not the application in front of you — that is a much bigger problem and a much shorter conversation.
  2. 16
    Render exactly what the UI would show for a stored application, and check the stored instants round-trip through the reverse mapping.
    /debug/intake/timeline-render/{app_id} intake
    Expected result The projected rows plus a round-trip verdict.
    Watch out for If the round trip fails, do not edit the application to 'fix' it — the stored instants are the truth and the inference is the derived view. Editing would overwrite good data with a bad guess.
  3. 17
    If every schedule in the platform is suddenly in UTC, check whether a timezone database is present in this container.
    Expected result A yes/no answer and which resolver answered it.
    Watch out for This is a real deployment failure mode on slim base images: with no timezone data, local time silently becomes UTC and nothing raises. This endpoint exists so the silence is diagnosable in one click.