03 / Product · Platform · Theatre tech
Impresario
The operating system for the small stage: a multi-tenant box office and production platform for 50 to 300 seat theatres.

Summary
A community or off-Broadway theatre with 200 seats runs on the same infrastructure as a Broadway house, minus the budget and the staff. Impresario is one product that covers the whole loop: sell the ticket, run the show, keep the patron. It started as the ticketing system for Threshold Theatre Collective's first production, built against a fixed opening night, and grew from operating it live into a multi-tenant platform where every theatre gets its own branded box office, its own Stripe account, its own sending domain, and the backstage tools no ticketing vendor ships.
Context
Ticketing platforms take a cut of everything, including comps, cash at the door, and the free preview for the board. Per-ticket fees are opaque: patrons see a service charge the theatre cannot explain and often eats part of. Everything backstage lives somewhere else, cast contact sheets in a doc, conflicts in a spreadsheet, rehearsal calls in a group text, patron emails in a mailing list nobody has cleaned in years. And the box office volunteer on opening night needs a check-in tool that works when the lobby Wi-Fi does not. Threshold hit all of this at once when it needed to sell tickets for Jekyll & Hyde, and the options for a small theatre were enterprise-priced or unusable. So I built it.
What I built
- A public box office per theatre: branded ticketing site on their own domain or a free subdomain, show pages with calendar, cast and creative bios, content warnings, ADA information, and structured data for search. Checkout with general-admission tiers, discount codes, comps, waitlists, guest purchase, refunds, and exchanges
- A mobile-first admin console for people doing this between a day job and a tech rehearsal: analytics, shows and performances, orders, check-in, attendance, refunds, patrons, and settings
- Patron CRM and lifecycle marketing: ticket buyers, waitlist signups, and company members roll up into one patron record with lifetime value and tags. Visual segments (superfans, lapsed 90 days, comp-only, first-timers) feed campaigns and automated emails: post-show thank-yous, win-backs with a generated one-use code, new-season announcements
- Backstage, the part no ticketing vendor ships: company roster, cast conflicts, a rehearsal and call-sheet builder that cascades block times, and a subscribable company calendar
- Show night: one-tap check-in with an offline queue to IndexedDB that reconciles when connectivity returns, PIN-gated so a volunteer can run the door from their own phone without an admin account
- Per-tenant integrations: each theatre connects its own Stripe account, verifies its own sending domain through generated SPF, DKIM, and DMARC records with per-record polling and a one-click handoff to their web person, and optionally attaches its own mailing-list audience with encrypted credentials
- Email branded by audience: messages to patrons and company members wear the theatre's brand, account and platform messages wear Impresario's, and every link resolves to the tenant's own domain
Screens



Screenshots use a demonstration theatre with invented productions, patrons, and dollar figures. No real customer data appears.
How it works
01
Host
The marketing site, the product host, and every theatre's ticketing domain are one React application. A host classifier resolves the request to an organization.
02
Tenant
Branding, navigation, email sender, and Stripe account all follow from that resolution. Row-level security scopes every table to the organization.
03
Checkout
One fee formula in one shared module, imported by the front end and the edge functions, so the quote, the charge, and the settlement never drift.
04
Show night
PIN-gated check-in with an offline queue, so a dead lobby signal does not stop the house from opening.
05
Patron
Buyers, waitlists, and company members roll up into one record. Segments feed campaigns and lifecycle emails in the theatre's own brand.
Detail
The theatre keeps face value, exactly
This was the hardest product decision and the clearest differentiator. The patron sees a single line item covering card processing and the platform margin. The theatre receives the printed ticket price, and comps and manually recorded cash sales carry no fee at all. The engineering consequence is that a single fee formula has to be authoritative in five places: the client-side quote, the server checkout session, webhook fulfilment, refunds and exchanges, and the settlement report. It lives in one shared module imported by both the front end and the edge functions. An earlier version had the client estimate and the server compute independently; they drifted by cents, and cents are exactly what a treasurer notices.
Outcome
It sold the tickets and ran the door for Threshold's first production, and Threshold now runs on it as the first tenant on its own domain. Impresario is in private beta with theatres onboarding onto their own Stripe accounts and sending domains. Shipped and in use: ticketing, checkout, refunds and exchanges, waitlists, reminders, check-in, patron CRM, segments, campaigns, lifecycle automations, backstage scheduling, and per-show branding. On the roadmap: reserved-seating charts, bulk patron import, season subscription packages, and accounting exports.
0
Fee formula, authoritative in five places
0
Platform fee on comps and cash sales
0
Kinds of host served by one deployment
What I would highlight
Tenant resolution as a first-class concern: two production domains serving different things from one deployment forced host classification into its own tested module rather than scattered location checks. Row-level security recursion, solved with a security-definer helper that returns the caller's accessible show IDs, a pattern reused across the schema. Idempotency everywhere money moves, because Stripe and cron both retry. And self-serve onboarding for non-technical admins, because the artistic director should be able to set up a sending domain without calling anyone.
My role
Founding team of two: I own product and engineering, my co-founder owns brand and design. I designed and built the platform, and I operated it live for a production, which is where the product scope came from.
Stack
- React
- Vite
- TypeScript
- Tailwind
- Postgres
- Row-level security
- Edge functions
- Stripe Connect
- Resend
- Mailchimp
- IndexedDB