Two business types share this booking system: service and clinic. They run the same code — services, appointments, staff assignment, packages — and the clinic type relabels the interface to appointments, patients and treatment courses, because a dental practice and a nail salon have the same booking problem in different words. Choosing the type changes the vocabulary and nothing structural: a separate clinic product would drift from the service one within two releases.
A service is a duration and a price you set
The catalogue is a list of services, each with a duration and a price. The duration is not decoration — it is what makes a diary of appointments meaningful, because a ninety-minute treatment and a fifteen-minute trim occupy different amounts of the same day. Customers browse the shop's public page, pick a service and book it; that page section is contributed by the Service module itself, built from the same shared UI kit as every other module, so it looks native rather than bolted on.
Booking, and the confirmation the shop presses itself
An appointment request carries a name, a phone number, a date, a time and a note. It arrives pending, and the shop confirms it. The pending count is one of the live badges on the business console dashboard, refreshed every few seconds alongside active orders, tables calling staff and pending leave — so a business running several modules has one place where everything waiting on a human is counted.
The confirmation step is not friction for its own sake. A booking system that auto-accepts anything the calendar has room for will take the appointment whose technician is not in that day, and the eleven o'clock that only works if the ten o'clock runs short. Making acceptance a human act keeps the shop's own knowledge in the loop, and gives the customer a definite answer rather than a slot that quietly moves. A shop that would rather take people in the order they walk in than at a booked time runs queue tickets instead, from the same console.
Each appointment can be assigned to a staff member. That single field turns a list of bookings into a working day: it answers who is doing this, it lets a returning customer be given back to the same person, and it feeds the customer history, so the shop knows which of its people the regulars come back for.
Packages and prepaid courses: N sessions, valid N days
Prepaid work is its own model rather than an ordinary sale. A package is either a course of N sessions valid for N days, or a membership valid for N days. Customers buy it and redeem a session at a time; a "my packages" tab shows what they hold and what is left. That remaining count is the record, kept on the same backend as the appointments that consume it, not on a stamped card in a wallet.
Buying a package is also one of the qualifying transactions in the review-eligibility view, so a course customer can review the business even before their first session is redeemed.
There are no SMS reminders, because there is no SMS. Phone verification and SMS delivery are not built — the endpoint answers 501 and says so. Notifications reach customers in the app, and email goes to verified addresses only.
The clinic type is a relabel, not a medical record system. It renames appointments to patients and treatment courses. It does not store clinical notes, prescriptions or anything that should live in an EMR, and it is not built to.
What the owner gets around it: reports, CRM and HR
A service or clinic business gets three module tiles — appointments, services and packages — plus everything every business type gets. Reports cover revenue, order count, average ticket, a split across cash, PromptPay and other, the top five best sellers, a seven-day revenue chart and periods of today, seven days, thirty days or all time, with receipt reprint and shareable receipt text. A tax invoice cannot be issued — only a VAT registrant may issue one, and nothing in this system records any shop's registration yet. For a service shop the best-seller list reads as which treatments actually pay, usually not the one on the poster.
CRM builds a customer list out of the sales ledger with notes and tags, purchase history, loyalty points earned at a rate the shop sets in its own currency, against a configurable minimum sale and reward. HR covers the staff side: clock in and out with GPS and a note, leave requests, shifts and payroll with worked minutes and overtime past eight hours a day on an hourly or monthly wage, announcements and assignable tasks. Payroll is scoped — an ordinary member sees only their own pay, the owner and manager see everyone.
Access runs on a permission matrix: thirteen core capabilities plus whatever the installed modules declare, role presets for owner, manager, waiter, kitchen and staff, and per-person overrides. Tiles disappear when a member lacks the capability, and a member with no permissions yet sees a screen saying exactly that rather than an empty list that reads as a bug. In the Android app those checks run on the client; the same matrix exists in the database as has_capability(business_id, capability), expanded server-side for the row-level security policies.
The module system underneath, and the add-ons you can install
Service is one of four core modules, alongside Food, Stay and Retail — the business types are the modules. A module declares an id, the business types it claims, a label, a catalogue title, a primary call to action, a catalogue view, and optionally capabilities, console tiles, a console screen and a customer-facing page section. That contract is why a permission editor can be built automatically out of whatever capabilities the installed modules declare.
On top of those sit seven installable add-ons that work for any business type, from the Plugin Store in the console: team permissions, payment channels, memberships and subscriptions, renewal reminders, projects and tasks, materials and production, and automation. Memberships and renewal reminders pair obviously with a service business — a plan customers buy from the shop's page, and a reminder before it lapses. Which of them a shop package already includes, and which are bought separately, is set out on the plans page. Uninstalling sits behind a confirmation stating plainly that the data is not deleted, and an uninstalled add-on contributes no tiles, no permissions and no customer-facing section. Third-party plugins are not open yet; the store says so itself. What exists today is a modular architecture with first-party add-ons, and opening submission is the next step.
Reviews, after the appointment is done
Using a service is one of the verified kinds in the review-eligibility view, so a customer who has actually been seen can write a review and everyone else gets a lock card explaining why the button is not there. The star rating is recomputed by a database trigger from the review rows, never typed in. Reviews carry photos, a five-to-one distribution summary, editing and deletion of your latest one, a new review on a repeat visit while the old one stays, and public owner replies.