Openfront Restaurant
Menu, ordering, POS, service floor, kitchen, inventory, staff, and reporting.
Source · Live site · Catalog
Openfront Restaurant is the restaurant version of Openfront. It covers the main restaurant loop: publish a menu, take orders from the storefront or from staff tools, route them to kitchen stations, run the floor, close the check, and reconcile the day.
What ships today
Storefront ordering
Menu, item pages, cart, multi-step checkout, account pages, and order confirmation.
Point of sale
Dine-in and takeout order entry with tables, modifiers, courses, urgency, and a payment screen.
Service floor
Table states, adding items, courses, split and merged checks, voids with manager approval, and closing checks.
Kitchen display system
Station tickets, prep and expediter lanes, all-day view, and item-level completion.
Menu and modifiers
Categories, items, images, allergens, dietary flags, meal periods, and modifier groups.
Inventory and recipes
Ingredients, recipes, purchase orders, receiving, lots, counts, transfers, and waste.
Staff and labor
Staff records, shift schedule, time clock with corrections, tip pools, and labor reporting.
Reporting and close
Operations dashboard, sales, menu performance, labor, receipts, and cash and business-day close.
How the order lifecycle works
A guest or staff member starts the order
Guests order through the storefront. Staff open orders from the POS or add items to a table from the service floor. Every path writes a RestaurantOrder with OrderItem rows. Item rows keep snapshots of name, price, modifiers, and kitchen station.
Payment is handled per channel
In the storefront, the guest picks a payment provider first (initiatePaymentSession). Then completeActiveCart checks or captures the payment and creates the order, its items, and a Payment in one database transaction. Staff orders are paid at the end through the POS payment screen (cash, card, gift card, or split tenders).
The order enters the kitchen
Orders in sent_to_kitchen, in_progress, or ready get KitchenTicket records, one per station. POS orders are created as sent_to_kitchen. Online orders paid by card start as sent_to_kitchen. Online orders using the manual provider start as open.
Front of house keeps the floor moving
Hosts work the waitlist and reservations. Servers use the service floor to add items, fire or hold courses, split or merge checks, combine or transfer tables, and close checks.
The day closes
When an order reaches completed or cancelled, the app syncs kitchen tickets, depletes recipe ingredients, and releases tables. A failed step is logged for recovery. Managers then reconcile cash, refunds, and processor statements on the Cash & Close page.
Tenancy
One deployment runs one restaurant. StoreSettings is a singleton. There is no organization, restaurant group, or location model. Orders, menu, inventory, tables, payments, and staff are not split by tenant. InventoryLocation is only a storage location for ingredients, not a restaurant location.
Access is controlled by the user's Role. Roles carry flags such as canAccessDashboard, canManageOrders, canManagePayments, canManageProducts, canManageInventory, canManageKitchen, canManageTables, canManageStaff, canManageSettings, canManageOnboarding, canManageGiftCards, and canManageDiscounts, each with a matching read flag where relevant. API keys add scopes on top of the owner's role.
Data model
The Keystone lists in features/keystone/models are:
| Area | Lists |
|---|---|
| People and access | User, Role, ApiKey, Address |
| Store | StoreSettings |
| Floor | Floor, Section, Table, Reservation, WaitlistEntry |
| Menu | MenuCategory, MenuItem, MenuItemImage, MenuItemModifier |
| Orders | RestaurantOrder, OrderItem, OrderCourse, OrderAdjustment, ManagerApproval |
| Kitchen | KitchenStation, PrepStation, KitchenTicket, KitchenTicketEvent, KitchenMessage |
| Cart and checkout | Cart, CartItem, PaymentCollection, PaymentSession |
| Payments | PaymentProvider, Payment, Refund, Receipt, PaymentWebhookEvent, IdempotencyKey |
| Promotions | Discount, DiscountRule, GiftCard, GiftCardTransaction |
| Inventory | Vendor, InventoryLocation, Ingredient, Recipe, StockMovement, PurchaseOrder, WasteLog |
| Staff | Shift, TimeEntry, TipPool |
| Audit | AuditEvent |
Several features do not have their own list. Business days, cash movements, settlements, notifications, campaigns, privacy requests, and time-correction requests are all stored as AuditEvent rows.
Current limits
- One restaurant per deployment. No multi-location support.
- Stripe, PayPal, and manual adapters exist. Behavior differs by provider. Test sessions, capture, refunds, and webhooks for the ones you enable.
- Discounts have models and an admin list, but no order path applies a discount code. Only the pickup discount from store settings is applied at checkout.
- The waitlist does not send SMS. Hosts contact guests by hand and confirm it in the app.
- Email (order confirmations, campaigns) is queued and sent only when an operator triggers sending from the dashboard. SMTP acceptance is not proof of delivery.
- The POS saves a draft on the device when offline, but it does not send orders offline. There is no printer or device management.
- There is no loyalty program, delivery dispatch integration, accounting export, or payroll integration. Time clock and tips export CSV only.
Stack
- Next.js 16 with the App Router, React 19
- KeystoneJS 6 for lists, auth, and GraphQL
- PostgreSQL through Prisma
- Stripe, PayPal, and manual payment adapters
- Tailwind CSS and shadcn/ui
- An MCP-backed AI assistant in the dashboard
Route files under app/ are thin. Product logic lives in features/platform (operator screens), features/storefront (customer screens), and features/keystone (models, access, custom GraphQL operations).