Case study - From checkbox chaos to a live registration system
Bon Odori is a two-day Japanese culture festival in Vilnius with ten bookable workshops, several capped, several paid by direct bank transfer. We replaced an open checkbox spreadsheet with an automated registration backend that enforces capacity, manages a waitlist, and sends branded confirmation emails, with real-time seat counts live on the festival's website.
- Client
- Bon Odori Japanese Culture Festival, Vilnius
- Service
- Registration systems, Backend automation, Google Workspace integration, Next.js development
The challenge
Bon Odori is a two-day Japanese culture festival in Vilnius built around a full program of hands-on workshops — calligraphy, sumi-e painting, sashiko stitching, ikebana, bookbinding, and more — each led by an independent facilitator with a dedicated page on the festival website.
The previous registration process was a single Google Sheet with checkboxes: anyone could mark themselves down for any workshop, with no cap on numbers, no distinction between time slots, and no way to handle the workshops that carried a fee. Payment for paid workshops was a separate complication entirely — facilitators are paid directly, by bank transfer, into their own accounts, not the festival's. There was no automated way to reserve a seat against a pending payment, release it if the payment never came, or notify the next person waiting.
As the festival grew from a handful of open workshops to ten distinct bookable sessions across two days — several of them capped, several of them paid — the checkbox sheet stopped being a viable system.
The solution
We designed and built a self-contained registration backend on Google Workspace, wired directly into the festival's existing Next.js website, with no new software for the client to learn day-to-day beyond a spreadsheet they already knew.
- Structured intake, one form per session. Each of the ten bookable sessions — including workshops that share a facilitator but run at different times, like Inga Eičaitė's three separate emakimono, kakejiku, and yotsume-toji sessions — got its own Google Form, feeding its own tab in a shared response sheet. A master "Workshops" tab holds the capacity, schedule, and pricing for every session in one place, so the client manages the whole program from a single source of truth rather than ten disconnected spreadsheets.
- Automatic capacity and waitlist enforcement. A Google Apps Script backend watches every incoming form submission in real time. It checks the session's remaining capacity, confirms the seat immediately if space is available, or places the registrant on a waitlist automatically if it is not. When a confirmed spot frees up — through cancellation or an expired payment hold — the script promotes the next person off the waitlist and emails them without anyone on the team touching the sheet.
- A payment hold built for bank transfer. Because paid workshops are settled by direct bank transfer to each facilitator rather than through a payment gateway, there is no instant confirmation to hook into. We built a hold pattern instead: a paid registration reserves the seat immediately, generates a unique reference code for the bank transfer, and gives the registrant a two-day window to pay. A daily automated sweep checks every pending registration against that deadline, expires the ones that were never paid, frees the seat, and promotes the next waitlisted registrant — all without manual reconciliation, beyond the client marking a payment as received once it lands.
- Branded, automatic email at every step. Every registration outcome — confirmed, waitlisted, payment reminder, promoted from the waitlist — triggers a transactional email through Brevo, sent from the festival's own verified domain rather than a generic no-reply address. Bank details and the reference code are included automatically for paid sessions, so the client never drafts these emails by hand.
- Live seat counts on the website itself. The registration backend also exposes a small public JSON endpoint reporting live seat availability for every session. The festival's Next.js site — a fully static export, with no server running at request time — reads that endpoint client-side, so each workshop page shows real-time seats-remaining and automatically swaps its call to action to "join the waitlist" once a session fills, without a rebuild or redeploy.
- Registration placed where the decision happens. Rather than a single generic "register here" button bolted onto each page, every bookable session got its own registration card, placed directly after the paragraph describing that specific workshop. On pages covering multiple sessions from one facilitator — such as the emakimono page, which actually covers three separate bookable workshops — visitors see three distinct cards, each with its own schedule, price, and live seat count, positioned exactly where the relevant description ends.
How it fits together
- Intake. Google Forms — one per bookable session, feeding a shared Google Sheet.
- Source of truth. A single "Workshops" master tab: capacity, schedule, pricing, per-session status.
- Backend logic. Google Apps Script — capacity checks, waitlist promotion, payment-hold expiry, a daily automated sweep.
- Email. Brevo transactional API, sent from the festival's verified domain.
- Public data. A lightweight Web App endpoint returning live seat counts as JSON.
- Website. Next.js (static export) — a client-side component fetches live seat data and renders per-session registration cards inline with each workshop's description.
The outcome
The client now runs a ten-session festival program — mixing free and paid workshops, single and multi-slot facilitators — from one spreadsheet and zero manual capacity tracking. Every registrant gets an immediate, branded confirmation; every paid seat is protected by an automatic hold and release cycle; and every workshop page on the website reflects real seat availability without anyone editing the site itself. What began as an unlimited checkbox list is now a system that scales with the festival's program, not against it.
Work done
- Registration backend on Google Workspace with Google Apps Script logic
- 10 Google Forms unified into one shared response sheet with a "Workshops" source-of-truth tab
- Automatic real-time capacity and waitlist enforcement
- A bank-transfer payment-hold model with unique reference codes and a daily automated sweep
- Brevo transactional emails sent from the festival's own domain
- A public JSON API endpoint with live seat data
- Next.js website integration — registration cards inline with each session's description
- bookable sessions
- 10
- registration channels unified
- 1 sheet, 10 forms
- payment types supported
- 2 (free / bank transfer)
- manual steps for the client after setup
- ~0
Looking for something similar for your event or business?
The Bon Odori registration system is an example of what an event looks like without manual seat tracking and lost bank transfers. Every event or business has its own specifics, so we can adapt a similar system personally — integrations with other payment methods, extra notification channels, or custom registration logic.