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

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.

“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

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.

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.

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

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.

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

