Case studies · Shree Gowri Shankara

One date, three businesses, zero drift: replacing a wedding hall's paper register

A Kannada-first booking, payment and receipt system that runs Shree Gowri Shankara Kalyana Mantapa from first enquiry to final receipt, with no server to maintain.

Client
Shree Gowri Shankara Kalyana Mantapa, Hanur, Karnataka
Domain
Venue and event operations, weddings
Status
Live in production
Problem
Dates, advances, balances and three businesses' receipts kept in a handwritten register
Timeline
Live from July 2026 · receipts and pricing reworked September–October 2026
Stack
Next.js 16 · React 19 · TypeScript · Firebase Auth + Firestore · Vercel
The staff dashboard's Command Center: events left this month, amount yet to be received, booked dates for next month, and this month compared with this financial year.
The Command Center staff open every morning. (Names and amounts replaced with sample values.)

It's wedding season. A family pays an advance at the desk. Before they leave, someone has to check the register to make sure the date is free, write a receipt for each of three businesses with the right number from each book, and remember what is still owed on the day of the event. Then do it again for the next family.

Shree Gowri Shankara Kalyana Mantapa is a traditional wedding hall in Hanur, Karnataka. Tavra Labs built the system that replaced its handwritten register: a bilingual public website that takes enquiries, and a staff dashboard that turns each enquiry into a booking, records every payment and prints numbered Kannada receipts. This is how it works, and why it's built the way it is.

The problem: why the register fails

A paper register is a good record of what happened. It is a poor guard against what shouldn't happen.

  • A date can only be sold once, but the register can't warn you when you are about to sell it twice.
  • One event, three businesses. The venue and two service partners bill each event together, and each needs its own receipt in its own number series.
  • Money arrives in parts. An advance at booking, the balance on the event day, and that balance is often paid a little short.
  • Numbers restart every April. Receipt serials run per Indian financial year.
  • Kannada first. Staff work in Kannada, and receipts must be printed in Kannada.
  • Prices change between seasons, but a booking must keep the price it was sold at.

Every one of these is a rule staff carried in their heads and enforced with a pen. The job was to move those rules into software, where they hold even on a busy day.

The constraints we accepted

  • No server to run. A small business with no IT staff shouldn't own a backend. The browser talks to the database directly, and database rules are the access control.
  • Kannada first. Dashboard, public site and printed receipts are in Kannada. Only Advance, Balance, Invoice and GST stay in English.
  • Paper stays the reference. Receipts print on A4, and the old register can be back-entered.
  • Two kinds of staff. Admins handle money. Executives check dates and work enquiries, nothing more.
  • Money adds up to the rupee on every receipt, every time.

Architecture

One Next.js app on Vercel serves both the public site and the staff dashboard. There are no API routes and no server actions: every read and write goes from the browser to Cloud Firestore through the client SDK, and Firestore's security rules decide what each person may do. Staff sign in with Google; the public enquiry form writes without signing in, but only in a shape the rules accept.

Shree Gowri Shankara platform architecture In the browser: the public site, the staff dashboard and printable Kannada receipts. Vercel serves the pages but runs no backend code. The public site writes enquiries and the dashboard reads and writes bookings, both through Firestore security rules into Cloud Firestore. Staff sign in with Firebase Auth using Google. Photos come from Cloudinary. BROWSER · PHONE OR DESKTOP Public siteKannada-first · English toggle · enquiry form Staff dashboardbookings · payments · receipts · enquiries Printable receiptsKannada · A4 · browser print Security rulesallow-list · roles · schema Cloud Firestorethe only backend Firebase Auth · Google Vercel: serves pages Cloudinary: photos enquiry
There is no backend to run. Vercel serves the pages, the browser talks to Firestore, and the security rules decide who can read or write what.

The data model is small. A booking holds its dates, a frozen price snapshot and a running payment summary; payments and receipts sit underneath it. Enquiries, staff-blocked dates, configuration and one receipt counter per financial year complete it.

The availability calendar for October 2026, with a legend for open, selected, booked, internal block and past dates, and a list of upcoming events on the right.
The availability calendar: bookings and staff-blocked dates on one view. Staff pick free dates here to start a booking.

Key decisions and trade-offs

No backend over an API server

Options
Run an API server in front of the database, or let the browser talk to Firestore under security rules.
Choice
No backend. The rules are the access control, kept in the repo as one file.
Why
Nothing to patch, scale or pay for, and every permission is auditable in one place.
Cost
Every guarantee must be expressible as a rule or a client-side transaction. We built a Telegram notifier with server code, then removed it to keep the app server-free.

Status derived, not stored

Options
Store a status field and update it, or work it out from the facts each time.
Choice
One function derives the status from payments, balance and event date.
Why
"Balance Pending" can't go stale, and every screen agrees.
Cost
Queries can't filter on a derived status directly.

Freeze prices per booking, with a version

Options
Price receipts from current settings, or snapshot prices onto each booking.
Choice
A versioned price snapshot, saved when the booking is created.
Why
Changing prices never rewrites a receipt already issued.
Cost
Two versions of the receipt maths live side by side.

One write path for money

Options
Let each screen write payments, or route every payment through one function.
Choice
One function validates each payment and updates the booking's payment summary in the same transaction.
Why
Dashboards read one summary instead of adding up payments, and totals can't disagree.
Cost
Discipline: nothing may write a payment any other way.

The hard part: one payment, three receipts, one number series

When a family pays, the money belongs to three businesses. The system has to decide how much goes to each, print a receipt for each, and give each receipt the next number in this financial year's series, without ever printing a duplicate or skipping a number.

How one payment becomes three receipts An advance is split by a fixed ratio, rounded to 500-rupee steps and capped at what each business is owed, into a receipt for the venue, partner A and partner B. A balance pays the venue's electricity first, then splits the rest by what each business is still owed. A short payment is recorded as a discount and closes the booking. All receipts are issued in one transaction that checks for duplicates and takes the next financial-year serial. Advance received Split by a fixed ratiorounded to ₹500 stepscapped at what each business is owed Balance received Electricity to the venue first Rest split by what eachbusiness is still owed, capped Paid short?shortfall = discount, booking closes Venue Partner A Partner B Onetransactionduplicate check+ FY serial +1 one receipt per business numbered per financial year
Every payment fans out into one receipt per business. The parts always add up to the rupee.

The split

The advance is divided by a fixed ratio between the three businesses, rounded to ₹500 steps so receipts carry round figures, and capped at what each business is actually owed. Whatever rounding leaves over goes to the last business, so the parts always add up to exactly what was paid. The balance works differently: the venue's electricity charge is paid first, then the rest is shared in proportion to what each business is still owed. If the family pays a little short, the shortfall is recorded as a discount and spread across the businesses, and the booking closes.

The numbers

Each receipt has a deterministic id built from the booking, the receipt type and the business. Issuing it runs in one Firestore transaction: check that the receipt doesn't already exist, take the next serial from this financial year's counter, and write both. If two phones press "Generate" at the same moment, one wins and the other finds the receipt already there. No duplicate is printed and no number is skipped or reused.

History that doesn't move

The third business joined after the system went live. A dated rule keeps bookings made before then on the split they were sold under, and the versioned price snapshot keeps their line items intact. Old receipts reprint exactly as they were first issued.

A booking's detail page: a payment summary showing total paid, charges and balance, the advance paid and payment count, contact details, and an Advance Receipt button.
A booking's payment summary, kept in step with every payment by the single write path. (Sample values.)

Enquiry to receipt: the lifecycle

Most bookings start on the public site. The enquiry form is Kannada by default, with an English toggle, and the database rules check its shape before accepting it: an Indian mobile number pattern, field sizes and a server timestamp.

The public website's hero in Kannada: the venue's name, a short description, and buttons to send an enquiry or call.
The public site, Kannada by default.
The enquiry form on a phone, in Kannada: name, phone number with +91, preferred date, guest count, event type and an optional message.
The enquiry form on a phone.

From there, an enquiry moves through a short pipeline: new → called → marked for booking → converted, or not interested with a required reason. An executive can call back and hand an enquiry to an admin; only an admin creates the booking, which links back to the enquiry it came from.

A booking is saved either as a draft, with no advance, or confirmed, with the booking and its advance written in one atomic batch so a failed save can't leave a date held with no money recorded. Once the event date arrives with money still owed, it shows as Balance Pending. The balance payment makes it Completed; a cancellation, with a reason, releases the dates.

The code also refuses what shouldn't happen: an advance as large as the total, a balance above what's owed, and any payment or receipt on a cancelled booking.

The monthly bookings register for October 2026: booking IDs, party names, event dates, advances and a 'Booking confirmed' status for each, with a ledger panel for the selected booking.
The monthly register that replaced the paper one. (Sample names and amounts.)

Security, and what we'd do differently

With no server, the security rules carry all of the access control:

  • Staff must be on an allow-list and have a verified email.
  • Only admins can write money: payments, receipts and prices.
  • An admin can't demote or delete themselves, so the venue can't lock itself out.
  • The public enquiry form is schema-checked by the rules, not just by the form.

Two things we'd tell you about before you asked:

Double booking isn't atomic yet. The check for a taken date reads before it writes, and staff-blocked dates are enforced by the calendar rather than the database. With two admins this holds in practice. The fix, a per-date lock document created in the same transaction and made create-only in the rules, is designed and is the next step. It isn't live yet.

Tests are thin. Only the pricing and receipt maths has an automated check. Turning this into a platform means tests around payments and receipt numbering first.

Results

We haven't measured time saved or bookings handled, so we won't put numbers on it. What changed is easy to describe:

  • Income-tax filing got easier. Every rupee has a numbered receipt per business, in one series per financial year, so year-end filing comes from the system instead of the register.
  • One place for the record. Bookings, payments, receipts, enquiries and blocked dates live in one system instead of a register and loose receipt books, and the old register can be imported.
  • Numbers the register couldn't give. The Command Center shows this month against this financial year (bookings made, booked value, money collected) and what is still outstanding.
  • Roles that match the desk. Admins handle money; executives check dates and follow up enquiries.

From one venue to a platform

Most of what makes this work isn't specific to one hall. The single payment write path, race-safe receipt numbering, the capped splitter, price snapshots, derived status, the enquiry pipeline, the availability calendar and the role model all carry over.

What's specific today (the three businesses, the pricing formula, wedding fields, Kannada copy and branding) lives in code. The path to the Tavra venue booking platform is to move those into configuration first, then add resources and time slots, then run many venues on one system.

It fits wedding, banquet and community halls as it stands. Auditoriums need time slots; guest houses, studios and turfs need room or hourly inventory and online payment.

What this means for your venue

Money that always adds up, history that never changes, no server to babysit, and software in your staff's language. If you run a venue or any booking-led business, talk to us about running on the platform, or about a build of your own.

Talk to an engineer →   Visit shreegowrishankara.in ↗