Skip to content

Case study

A studio that books itself, and runs itself between shoots

Ottora rents six setups by the hour and runs a content operation on the same cameras and the same people. The booking page and the operations system are one thing, so the website can only sell what is actually free.

Client
Ottora Studio
Industry
Podcast & content studio
Location
Abu Hamour, Doha
Services
Full-Stack · Booking · Admin Dashboard · Access Control
A studio that books itself, and runs itself between shoots — lead image

01 · The challenge

One set of cameras, three businesses competing for it

Ottora Studio is a content studio in Abu Hamour with six bookable setups, and it earns in three ways that fight each other: hourly studio rental, off-site shoots, and monthly content retainers. All three draw on the same cameras and the same people. The website sold studio hours from a hardcoded number that knew nothing about whether a camera was on an off-site job that afternoon, the content operation ran entirely outside the system on messages and memory, and a rate change meant editing seven places by hand. The risk was not a slow page. It was selling an hour the studio could not deliver.

02 · Objectives

What we set out to do

  • Let a customer book, pay for, reschedule and manage their own studio time without a message to anyone.
  • Make it impossible for two jobs to be promised the same camera.
  • Put the content operation, the floor and the money in one place instead of three chat threads.
  • Keep the whole thing runnable by four partners and one operator, with no back office.
  • Give each partner and the operator exactly the screens their job needs, and enforce it in the database rather than the menu.
  • Replace the finance spreadsheet without asking the person who keeps it to give it up.

03 · Discovery

How we found the real problem

Two facts shaped everything. The first: availability is not a calendar question, it is an inventory question. A room can be free while the camera that makes it useful is out on a shoot, so any answer computed from room bookings alone will eventually oversell. The second: the retainer business, which is the largest of the three, was the one with no system at all — briefs, scripts, approvals and posting schedules lived in WhatsApp, and nobody could say what was owed this month against what had been sold. We also measured the boring thing first. Every database round trip from Doha costs about 300 milliseconds, because the database is in Sydney; a page that made four of them in sequence spent more than a second waiting before it drew anything.

04 · Strategy

The plan we committed to

Build the operations system first and let the website read from it, rather than building a nicer booking page on top of a guess. Everything a customer sees is a view of the same tables the floor works from: the hourly rate comes from the room record, not the page; the number of cameras the site will sell is the number of owned units not already allocated; a held slot expires by itself. Then work outward in phases, each one closing a way the business could quietly lose money — availability, then the shoot day, then the content pipeline, then the ledger. The rule throughout: if a rule matters, it lives in the database as a constraint, not in the application as a check somebody might forget to call.

Ottora — the public booking page: a month calendar with Fridays greyed out, and the hourly slots for the chosen day, drawn from the same tables the floor works from
Ottora — the public booking page: a month calendar with Fridays greyed out, and the hourly slots for the chosen day, drawn from the same tables the floor works from

Availability is an inventory question, not a calendar question. A room is only free if the camera that makes it useful is free too — so the website asks the database, not a number in the page.

The approach, in two lines

05 · Design

The decisions behind the screens

The public site is a catalogue, not a calendar: a visitor picks the setup that suits what they are filming, sees its rate, and only then meets a date and a time. Six setups, each with its own page, priced by the hour and bookable between 10:00 and 23:00 every day. Discounts are computed rather than negotiated, so a longer booking is cheaper without anyone asking: a quarter off at six hours, fifteen per cent at three, and fifteen per cent on a new customer's first three bookings. The account area gives a returning customer their upcoming, subscription and past bookings, and a reschedule that does not need a phone call. Inside, the dashboard is built for the room it is used in — the floor view is a phone screen, one session at a time, thumb-sized controls for arrival, an extra hour, an added camera and payment collected.

How we approach Design & Development

Ottora — the six-setup catalogue behind the booking page, each setup carrying its live hourly rate
Ottora — the six-setup catalogue behind the booking page, each setup carrying its live hourly rate

06 · Development

What we built it on

Webflow for the public site and Next.js on Vercel for the dashboard, with one Supabase project underneath both: Postgres, Auth, Storage, twenty-two Edge Functions and pg_cron. The public pages talk to Postgres directly through the anon key under row-level security, so there is no bespoke API to keep in step. Equipment is modelled as individual units with an exclusion constraint on their allocations, which means the database itself refuses to hand the same camera to two jobs; the website's camera cap is a query against what is genuinely free. Checkout posts to Sadad, Qatar's payment gateway, with a server-signed form, and a server-to-server webhook is the source of truth rather than the browser's return trip. Time slots are held for two minutes while a customer decides and pending bookings expire after fifteen, so an abandoned checkout releases itself. Sessions are verified locally against a cached key set instead of a network call, and the serverless functions were moved to Sydney to sit beside the database — the Doha-to-Sydney hop is now paid once per page rather than once per query.

Six of Ottora's 79 tables — rooms, time slots, bookings, equipment, units and allocations — with the two exclusion constraints that make a double booking impossible
Six of Ottora's 79 tables — rooms, time slots, bookings, equipment, units and allocations — with the two exclusion constraints that make a double booking impossible

07 · The admin dashboard

Sixteen screens, one for every job in the building

The public site is the part customers see; the dashboard is the part the studio lives in. It runs on the same database, so a booking made on the website at midnight is on the floor view at nine with nobody copying it across. Every date is computed on Qatar days rather than UTC, the week starts on Sunday, and the screens used standing up were designed for a phone first. Each module answers one question someone on the team asks every day.

  • Overview — the day and the month at a glance, with bookings and consultation requests on one calendar.
  • Today — the floor view: who has arrived, an extra hour, an added camera, payment taken, session closed, one thumb-sized control at a time.
  • Bookings — upcoming, today and history, searchable across registered customers and guests, with bookings taken by phone or in person added by an admin.
  • Calendar — one week on a grid, layered by rooms, equipment, off-site shoots and people, with every view a link that can be shared.
  • Equipment — every unit on one schedule, checked out and back in, requested by an operator and approved by an admin, beside the full asset register.
  • Content — the nine-stage board, one tab per retainer client plus one for the studio's own channels, with quotas and approval gates.
  • Requests — consultation and podcast enquiries, scored on arrival and filtered on the server.
  • Pipeline — sales deals by stage, read column by column, and honest about it when a column is too long to show whole.
  • Clients — one list across registered customers, walk-in guests and clients added by hand, which the data keeps as three different kinds of record.
  • Retainers — monthly content contracts and their billing cycles.
  • Operators — who is assigned where, and their next sessions.
  • Payments — every card payment with a test-or-live filter and a page per order, beside the cash and card taken on the floor.
  • Finance — the ledger, cash on hand, runway, receivables and a six-month trend.
  • Notifications — a bell with an unread count, and the page behind it.
  • Analytics — bookings and revenue by day, charted on Qatar days, with empty days shown as empty rather than skipped.
  • Access control — staff, roles, invitations and blocked accounts.

08 · Access and control

Everyone sees exactly what their job needs, and the database enforces it

Four partners, an operator on the floor and customers on the website all use the same tables, so who can see and change what could not be a matter of which menu items are hidden. Every rule below is enforced twice: the page checks the role before it renders, and Postgres row-level security, switched on for every one of the database's seventy-nine tables, checks it again on every read and write. Hiding a link is manners; the policy is the lock. We proved it the direct way, impersonating each kind of account against the database and counting the rows each one could see, before and after the policies were rewritten.

  • Super admin — the only role that can change the system itself: inviting staff, setting roles and blocking an account. The access control screen is theirs alone.
  • Admin — every operational screen and action: bookings, clients, retainers, payments, operators and the approval of equipment requests. No system-level changes.
  • Operator — the floor, the calendar, the equipment schedule and the content board. They can request kit but not approve it, and the payment, client and contract screens send them back to the dashboard even when the address is typed in directly.
  • Finance is a flag, not a role. The CEO carries it; the other partners, admins included, do not — and an admin without it gets zero rows from the ledger even when asking the database directly.
  • Receipts sit in private storage that only a finance-flagged account can open, through a link that expires.
  • Operators see a retainer client's brand name, which they need to plan a shoot, through a narrow database function that does not open the contract and its terms.
  • Customers read their own bookings and their own payments and nothing else. The floor view sees only what has been collected against each booking, never the payment records behind it.
  • Talent never log in; they are records an admin manages.
  • Notifications follow the same line: people get the items assigned to them, and admins get the exceptions.
  • The finance tool that runs outside the dashboard signs in as the person using it, never with a master key, so the rules still hold when nobody is looking at a screen.
Who opens what: every dashboard module against the customer, operator, admin and super-admin roles, and the finance flag that stands apart from them
Who opens what: every dashboard module against the customer, operator, admin and super-admin roles, and the finance flag that stands apart from them

09 · Pipeline

Where the enquiries go

The content operation runs on a nine-stage board, from needs planning through script, shotlist, filming and edit to posted, with per-client monthly quotas showing what was sold against what has actually been delivered. Client approvals are gates rather than reminders: a script or a final cut waits on one open request, and if it goes unanswered for twenty-four hours the system chases it by itself and tells an admin. Equipment requests from an operator escalate to every admin if nobody decides within a day. Staff get a morning digest at seven, and nothing at all on a day with nothing on it. Enquiries arrive through a consultation form that scores them before anyone reads them, and podcast work is request-and-approve rather than instant checkout, because the studio wants to say yes deliberately.

How we approach Sales Pipeline

Two of the eighteen mailers rendered from the real templates: a customer's booking confirmation, and a staff member's 07:00 morning digest
Two of the eighteen mailers rendered from the real templates: a customer's booking confirmation, and a staff member's 07:00 morning digest

10 · Payments and finance

From checkout to the ledger, without retyping a riyal

Checkout posts to Sadad with a form signed on the server, and the server-to-server notification is what marks a payment paid; the browser's return trip only shows the customer the result. Webflow cannot receive that return, so a small function catches it and hands the visitor on to a page that waits for the verdict. Cash and card taken on the floor are recorded from the Today view against the booking they paid for, so the day's collections sit beside the card payments. Behind it is a ledger with accounts, categories and recurring costs that post themselves every night, and a finance dashboard that draws cash, runway, receivables and the trend from one database call instead of seven — which matters when every call is a round trip to Sydney. The CEO kept his spreadsheet: the ledger imports it and exports back to it, six months of history landed and reconciled to the sheet within a riyal of rounding, and the importer was tested against a deliberately messy workbook, which is how it caught Excel dates arriving with day and month swapped, and rent being read as income.

From checkout to a confirmed booking: the signed form to Sadad, the server-to-server webhook that is the source of truth, the browser's separate return trip, and cash taken on the floor
From checkout to a confirmed booking: the signed form to Sadad, the server-to-server webhook that is the source of truth, the browser's separate return trip, and cash taken on the floor

What the system does, every day

6 setups
Bookable by the hour, 10:00 to 23:00 every day, priced from the room record rather than the page.
Zero
Double-bookings the system will accept. Overlapping equipment is refused by a database constraint, not by a check the code could forget.
15 minutes
After which an unpaid booking releases its own slot, so an abandoned checkout never holds the calendar.
9 stages
From needs planning to posted, with client approval gates that chase themselves after twenty-four hours.
16 modules
In one admin dashboard, each opened only to the roles whose work it is.
0 rows
What an admin without finance access gets from the ledger, even querying the database directly.

These describe the system we built. The studio's commercial figures stay private — the point of this study is the machine, not the takings.

Built with

  • Webflow
  • Supabase Postgres
  • Row-level security
  • 22 Edge Functions
  • pg_cron
  • Next.js 14 App Router
  • TypeScript
  • Tailwind + shadcn/ui
  • Vercel
  • Sadad payments
  • Cloudflare Turnstile

Keep reading

Next project

Full-StackLocal SEOAI VisibilityCommunity pharmacy

Bushra Pharmacy

From 2 indexed pages to 980+, and 475 patient enquiries in 60 days — without building a shopping cart.

Read the case study
Full-StackBilingualSEOAI VisibilitySteel fabrication

Masas Trading & Contracting

From a placeholder page to a 104-page bilingual site in 14 days, built to be found by procurement teams and AI assistants.

Read the case study

Selling time you might not be able to deliver?

If your availability lives in someone's head, we'll put it in a system your website can read. Tell us how the bookings come in today.

15 minutes · A clear plan · No pressure