ProjectsClient project

SetHub — the system behind a film studio in Los Angeles

Set Hub in Downtown LA rents out sixteen sets under one roof, a rooftop above the city and a stage with a vintage Mercedes. We built the studio its entire system — a CRM, a website with online booking and payment, a guest account and two apps — and bookings from every channel now land in one database.

  • Next.js 16 · TypeScript
  • PostgreSQL · Prisma 6
  • Stripe · payments and subscriptions
  • Expo · iOS and Android
  • Gmail · Google Calendar

By the numbers

4booking channels in one database: Peerspace, Giggster, the studio’s website and direct
19space calendars the system fills, moves and clears on its own
2mobile apps from one codebase — for the team and for guests
43database tables, 49 migrations and 74 test files

The problem

The studio rents out nineteen spaces through four channels — Peerspace, Giggster, its own website and direct — and each one comes with its own emails and its own calendar. What held them together was a spreadsheet kept by hand. A booking for the whole studio and a booking for one set inside it lived in different Google calendars, and nothing stopped a platform from selling the whole studio on top of a set that was already taken: the platform simply couldn’t see that booking. Website payments came in, but nowhere did it say what exactly had been paid for. A mistake here isn’t a typo in a spreadsheet — it’s two film crews at the same door.

What we built

Peerspace and Giggster emails turn into bookings on their own

A script in the studio’s mailbox forwards new platform emails every five minutes, and they’re parsed by rules, not AI. An enquiry is not a booking: “booked” creates a paid booking with the amount, the platform fee and the studio’s payout; a change notice moves the booking that already exists; each payout is matched to its booking by guest and amount. A booking records itself only from an email that passes DMARC and was read in full; anything else waits for a person in Capture, flagged in red. A clash that arrives by email isn’t rejected, because the platform has already sold it — it becomes an urgent task for today.

Nineteen calendars, one source of truth

The source of truth is the SetHub database; the 19 Google calendars are a “busy” board read by the website, Peerspace and Giggster. Booking the whole studio closes all 16 sets inside it, any set closes the studio, and the rooftop and the car stage only close themselves. The studio’s script places, moves and removes events every minute, with no phone numbers, emails or amounts in them. Events the platforms add themselves aren’t duplicated: SetHub appends its own block to them. A clash is a refusal everywhere — in the form, in Capture, in the app and in AI commands.

Capture: a text, a photo, a document or a voice note becomes a draft

Whatever is sent in by hand — a text, a photo of a receipt, a PDF, a voice note to the Telegram bot, a request from Make or Zapier — goes into one queue and waits for confirmation. Plain text and Word files are read by rules, without AI: date, time, amount and deposit, contacts, space, source, staff member and known client, with the guesses highlighted. The model is only needed for what isn’t text: voice, photos and scans. The same message from the same person within ten minutes returns what was already created instead of a duplicate.

Booking on the website: the slot is held while the guest pays

Guests pick a set, a day and a time from live availability, calculated from every channel’s bookings. “Book now” creates a tentative booking and holds the slot for 35 minutes: the free-or-not check and the write happen under a database lock, so two guests can’t take the same hour. Then comes Stripe Checkout; a signature-checked webhook confirms that exact booking, and a timer releases holds that go unpaid. The server does the pricing: 10% off from 4 hours, 15% from 8, a full day at a fixed price, add-ons and cleaning. If something is booked in the middle, the booking splits around it: noon to 4 with 2–3 taken becomes 12–2 and 3–5 for the price of one booking, and the break isn’t billed.

Guest emails: the door code, a day ahead

Right after booking, the guest gets a confirmation: the booking, the price breakdown, the studio rules and a PDF receipt — without the door code. A day before, a reminder arrives with the code, the floor and a video of how to get in; book less than a day ahead and it all comes in one email. Moving the booking moves the reminder, and cancelling removes it. Emails go out from the studio’s own mailbox, up to 1,000 a day with guests first, and codes are wiped from the queue the moment they’re sent. The film crew gets a signed link with the time, the address, how to get in and “add to calendar” — and once the shoot is over, “That’s a wrap”.

Guest account: no password, with perks and memberships

Sign-in is a six-digit code by email, valid for ten minutes with five attempts. Inside are the guest’s own bookings, “book again” with the same set, hours and add-ons, a PDF receipt and a calendar event. The discount grows with every visit; a membership is a Stripe subscription with hours each month, and there are hour packs and gift cards: the 16-character code is stored only as a hash, and the card never expires, as California law requires. After the shoot comes a five-star rating email; the link to leave a Google review is shown to everyone who rates, not just the happy ones, because asking only for good reviews is against Google’s rules.

Enquiries, tasks and deadlines — without the chat threads

Every enquiry gets an SH-xxxx number and moves through stages: new, talking, awaiting deposit, confirmed, completed or lost; the attention level is calculated, not stored, and the manager’s queue is built by the same rule. Task deadlines and assignees are set by the owner and the manager; staff can’t change a deadline, only ask to move it with a date and a reason, and that rule lives on the server, not in the form. Reminders come an hour before, when a task is overdue and every morning on studio time. Notifications arrive as an email digest, browser push, Telegram and phone push straight through Apple and Google, and a task can be closed with a button right in the notification.

Four roles, with permissions checked by the server

The owner sees everything. The general manager sees operations and the business’s money, but not the owner’s personal expenses. The client manager sees clients, bookings with amounts and enquiries, without the studio’s income and costs. Staff see tasks, the schedule and Capture, and no money at all: the app sends them the day without amounts, payments, source or guest contacts. A single roles module is checked by the pages, the server, the mobile API and the 26 commands for AI assistants — ChatGPT and Claude connect over MCP with OAuth sign-in, and no command deletes anything. Changing a password or disabling an account kills sessions, phone keys and AI access.

Two apps from one codebase

“Set Hub Team” is for staff: it opens with Face ID or a fingerprint, screenshots are blocked, the key lives only in that phone’s keychain and client data only in memory. The “Today” widget and the lock screen show the time and the space without guest names or amounts, and Capture opens with one tap from Control Centre. “Set Hub” is for guests: booking on a time tape, finding a set from a reference photo, the rooftop’s golden hour from the NOAA formula and the forecast, and “how to get in” behind Face ID — it works even in a basement with no signal. Both are built and tested on the iPhone simulator and the Android emulator; publishing to the App Store and Google Play is the next step.

Screens

Nineteen spaces, each with an hourly rate. To the system they are 19 places with their own calendars: booking the whole studio closes all 16 sets inside it
Nineteen spaces, each with an hourly rate. To the system they are 19 places with their own calendars: booking the whole studio closes all 16 sets inside it
Every set has its own page: photos, size, capacity, studio rules and booking right there on the page
Every set has its own page: photos, size, capacity, studio rules and booking right there on the page
The discount, the gear package and the add-ons are put together by the server: the browser only sends the guest’s choices
The discount, the gear package and the add-ons are put together by the server: the browser only sends the guest’s choices
Live availability: the calendar counts bookings from every channel, and times are always Los Angeles time, wherever the guest is
Live availability: the calendar counts bookings from every channel, and times are always Los Angeles time, wherever the guest is
Lights, gimbals, a camera — added to the booking with one tap; hourly items are charged by the booked hours, single items by quantity
Lights, gimbals, a camera — added to the booking with one tap; hourly items are charged by the booked hours, single items by quantity
The site footer
The site footer

Technology

Next.js 16 and TypeScript; PostgreSQL through Prisma 6: 43 tables, 49 migrations and 74 automated test files. Permissions live in a single roles module checked by the pages, the server actions, the mobile API and the AI commands — a hidden button doesn’t count as protection. Time is always studio time in Los Angeles: bookings, deadlines, month boundaries and reminders are compared with the studio’s “now”, not the server clock. The old spreadsheet was migrated in full: every record keeps its original row, and whatever didn’t match is reviewed on a separate reconciliation screen. The team interface is in English and Russian; the guest side, in English.

Payments run on Stripe Checkout and subscriptions, with a signature-checked webhook. Email and calendars run through a Google script in the studio’s mailbox and Google Calendar via a service account — no middlemen like Make. Voice, photos and PDFs are read by OpenAI; plain text, by rules. Push goes straight to Apple and Google, and browser push uses VAPID with no third-party libraries. The apps are Expo and React Native with a shared core: widgets, Live Activity, an Android quick-settings tile and a Swift module that brings up “how to get in” as the guest walks up to the studio.

Bookings coming in from several channels?

Tell us where your orders come from and where they get lost, and we’ll start with what hurts most. At Set Hub it was the platform emails and the calendars; everything else grew around them. You can open the studio’s website right now: at the bottom of every page is our signature, “Site by ProfiLab”.

WhatsApp