Vertical: restaurants & hospitality — don't spec it naive
Restaurants run on razor-thin margins (net 3–6%) with a hostile incumbent
stack. A spec that treats a menu as a flat list of {name, price} or
ignores who already owns the POS will ship something no operator can use.
This skill loads the domain so architect/pm sound like they've worked a
shift.
The 4 products in this vertical:
| Product | Archetype | One-liner |
|---|
| online-ordering | content | Own menu + checkout for dine-in/pickup/delivery — dodge aggregator fees |
| reservations | booking | Bookings, tables, text-the-waitlist |
| loyalty | crm | Points, offers, win-back |
| shift-scheduling | booking | Rota, open shifts, swaps with coverage rules |
Incumbents to position against: Toast (POS, ~$69–165/mo + hardware +
2.49%+ per swipe), Square (POS/SMB), SevenRooms (reservations/CRM,
upmarket), ChowNow (commission-free ordering), DoorDash / Uber Eats /
Grubhub (aggregators, 15–30% commission per order).
1. Domain vocabulary (use these words in the spec)
- COGS / food cost % — cost of ingredients ÷ menu price. Target ~28–35%.
- Prime cost — food cost + labor cost; the number operators obsess over
(target ≤ ~60% of sales).
- Menu engineering — classifying items by popularity × margin into
stars (high/high), plowhorses, puzzles, dogs (low/low). Drives what
gets promoted or cut.
- 86'd — an item is out of stock / unavailable ("we're 86 on the
salmon"). Must propagate instantly to every ordering channel.
- Modifiers / mods — choices on an item (size, temp, add bacon, no
onions, sub fries). Grouped, with required/optional + min/max rules.
- Covers — number of guests served (a "200-cover night").
- Turn time — how long a table is occupied; reservations math depends
on it (a 2-top turns in ~75 min).
- FOH / BOH — front of house (servers, host, bar) / back of house
(kitchen, prep, dish). Scheduling and tips differ between them.
- Tip pooling — pooled tips split by rule (hours, role, points).
Legally constrained — see §6.
- Comps / voids — comp = item given free (manager discretion); void =
item removed before it's made. Both need audit trails.
- Ticket times — elapsed time from order fired to served; the kitchen's
core SLA.
- Third-party aggregator commission — the 15–30% DoorDash/Uber Eats/
Grubhub take. The pain that makes owned ordering a wedge.
- KDS (kitchen display system) — screen in the kitchen that replaces
paper tickets; orders route to it by station.
2. Non-obvious domain rules
- The POS is the sticky system of record — don't fight it. Toast/Square
own the menu, payments, and floor. Our products integrate with or sit
beside the POS; they don't try to replace it. Sync the menu, don't fork it.
- Aggregator commission is the wound; owned online-ordering is the wedge.
A restaurant paying 25% to DoorDash on a $40 order keeps $30. Commission-
free direct ordering is the single clearest ROI pitch — lead with it.
- Menus have deep modifier hierarchies, not flat prices. "Burger" → size
group (required, choose 1) → temp group (required) → add-ons (optional,
0–5) → side (required, choose 1, sub upcharges). Price = base + mods.
- 86'd / out-of-stock is real-time and must sync everywhere. When the
kitchen 86's an item it must vanish from online ordering, KDS, and the
POS simultaneously, or you sell what you can't make.
- Tips have legal handling. Pooling rules, who can share (FLSA bars
managers/owners from tip pools), tip credit, and service-charge vs tip
distinction are labor-law constrained, not free-form.
- Margins are razor-thin. A feature that adds 30¢/order of cost can erase
the margin on that order. Cost-consciousness is a feature, not a nicety.
- Reservations + waitlist are SMS-driven. "Your table's ready" is a text,
not an email. Waitlist quote times and ready-pings are the product.
3. What a naive build gets wrong
- Flat menu, no modifier hierarchy.
{name, price} can't express
"medium, well-done, add bacon, sub fries (+$2)". Model modifier groups
with required/optional + min/max from day one.
- Ignoring 86'd / out-of-stock. Selling a sold-out item online is a
refund, an angry guest, and a chargeback. Stock state is first-class.
- Online ordering that doesn't sync the menu. A second menu that drifts
from the POS menu means wrong prices and phantom items. One source of
truth, synced.
- Tip handling that breaks labor law. Letting managers into the pool, or
mislabeling a service charge as a tip, is an FLSA violation, not a bug.
- No dine-in vs pickup vs delivery distinction. Each channel has
different fulfillment, timing, fees, address/table data, and tax. One
generic "order" type is wrong.
- Loyalty that's points-only with no win-back. Points without a lapsed-
guest re-engagement flow (offers, "we miss you") leaves the highest-ROI
CRM lever on the table.
4. Must-model entities
- MenuItem — base price, category, station, tax class, availability
state (available / 86'd / scheduled), with one or more ModifierGroups.
- ModifierGroup —
{required: bool, min, max} + ordered Modifiers
(name, price delta, default, in-stock). Hierarchy, not a flat list.
- Order — channel (
dine_in | pickup | delivery), status
(placed → confirmed → preparing → ready → completed | cancelled), line
items with resolved modifiers, computed total, table/address per channel.
- Reservation — party size, time, turn-time estimate, table assignment,
status; plus Waitlist entry (quoted wait, ready-ping, SMS thread).
- Shift — role (FOH/BOH), start/end, coverage rule (min staff per
role/time), open shift + swap request with approval/coverage check.
- LoyaltyMember — identity (phone-first), points balance, earn/redeem
ledger, last-visit (for win-back segmentation), consent state.
5. Per-product notes (wedge + the one domain thing)
- online-ordering (content) — Wedge: commission-free direct ordering
vs DoorDash's 15–30% and Toast Online Ordering's per-order fee. The one
thing: the menu + modifier hierarchy must sync from the POS and honor
86'd state, across dine-in/pickup/delivery, or it's worse than the
aggregator it replaces. Menus rank locally → see [[local-seo]].
- reservations (booking) — Wedge: SevenRooms is upmarket/expensive;
give SMBs bookings + waitlist without the price tag. The one thing:
it's SMS-first — text-the-waitlist and ready-pings are the product; turn
time drives table availability. SMS consent → [[lifecycle-messaging]].
- loyalty (crm) — Wedge: most POS loyalty is points-only; we add
offers + win-back. The one thing: lapsed-guest re-engagement
(segment by last-visit, send an offer) is where the revenue is — design
win-back, not just an earn-points counter. Sends → [[lifecycle-messaging]].
- shift-scheduling (booking) — Wedge: rota + open shifts + swaps
cheaper/simpler than the incumbents. The one thing: swaps must enforce
coverage rules (min staff per role per time band) — an unconstrained
swap that leaves the line uncovered is the failure mode.
6. Compliance (light — defer the heavy lifts)
- Tip pooling / labor law (FLSA) — managers/owners may not share in tip
pools; keep tip vs service-charge distinct; honor tip-credit rules. State
law varies (e.g. CA). Surface as a constraint; get specifics confirmed.
- Food-allergen disclosure — the big 9 US allergens must be declarable
on menu items; some jurisdictions require menu labeling. Model allergen
tags on MenuItem.
- SMS consent for waitlist/loyalty — TCPA consent, STOP/HELP, quiet
hours apply to every text. Defer the mechanics to [[lifecycle-messaging]].
- Payment — PCI scope, SCA, refunds/chargebacks. Defer billing/payment
design to the billing/PCI track; don't hand-roll card handling here.
Cross-refs: [[lifecycle-messaging]] (every SMS/email leg — consent + deliver-
ability), [[local-seo]] (menus and reservations rank locally; "best tacos
near me" is the funnel), [[migration-ready-schema]] (importing an existing
menu / guest list from the incumbent POS without losing modifier structure).