Foodops
All docs

Getting Started · Updated 2026-08-23 · v3e14d18

Foodops Navigation & Module Map

Audio narration for this article is generated with the weekly docs refresh.

Plain-English summary

This is the cheatsheet of every URL in Foodops — the sidebar icons with what they do, plus every route that returns 200 OK, grouped by what kind of work happens there. Useful when an agent or human is asked "where do I find the kitchen display?" or "what's the URL to create a supplier?" — look up the answer here without having to navigate the app.

When you'd use this

  • A user reports the old app at app.foodops.io won't load or log in — that legacy app is retired (July-2026 launch); nothing is wrong with their connection. Point them to the new apps: the counter POS at counter.foodops.io and the back-office at admin.foodops.io (same sso.hubits.io account works on both).

  • Voice/chat agent answering navigation questions

  • Deep-linking from an external system directly into a Foodops screen

  • Training a new user on app structure before they click around

  • Troubleshooting — "does this page still exist?" URL probe reference

  • Building bookmarks or cheat sheets

Summary

REBUILT for the new stack (July-2026 launch). The legacy app.foodops.io monolith and its MVC URL map (/dashboards, /orders, /tables, /kitchen/index, /menuitems, …) are RETIRED. FoodOps is now two React SPAs:

  • Counter appcounter.foodops.io (foodops.counter.app): the on-the-floor POS. Routes in src/App.tsx; nav rail in src/components/layout/Sidebar.tsx.
  • Admin appadmin.foodops.io (foodops-admin-app, foodops brand): the back-office. ~100 lazy routes in apps/admin/src/App.tsx; settings rail in apps/admin/src/pages/settings/settingsNavConfig.ts (7 groups).

Both are client-side routed (React Router) — paths below are the in-app routes, not server-rendered pages. Note the foodops brand relabels the counter's "Counter" rail to "Orders", and Finance routes are tree-shaken out of the foodops build (they exist only on finance-v2).

Complete map of both Foodops SPAs, organized by functional area, code-verified against foodops.counter.app@32669a9 and foodops-admin-app@4173811 (both prod main).

Counter app — sidebar navigation (counter.foodops.io)

The counter rail is brand-filtered. For the foodops brand the allowedItems whitelist renders: Counter (shown as "Orders"), Dine-In, Deliveries, Takeouts, Reports. ('Dashboard' is mapped in code but excluded from allowedItems, so it's reachable only by URL.) [code: foodops.counter.app/src/components/layout/Sidebar.tsx:190-192,249]

Rail item (foodops) Navigates to Description
Orders (label; "Counter" internally) /counter Main till — active dine-in/takeout/delivery orders; open a register session
Dine-In /counter?intent=dinein (or /sessions/:id/dinein in a session) Dine-in / table ordering
Deliveries /counter?intent=delivery Delivery ordering mode
Takeouts /counter?intent=takeout (or /takeout) Takeout ordering mode
Reports /reports/day-summary End-of-day Day Summary report
(Dashboard — not in rail) /dashboard KPI dashboard (URL-only on the counter)

Order-mode rail items reuse the current session: with an open session they route to /sessions/:id/..., otherwise to /counter?intent=.... [code: Sidebar.tsx:325-341]

Kitchen Display (KDS) is a separate bundle, not a counter route — it builds from the same repo to kds.html (src/kds/main.tsx, vite.kds.config.ts). There is no /kitchen route in the counter SPA. Reservations is not a counter route either.

Counter app — all routes (counter.foodops.io)

Everything except /login, the auth callbacks and the print pages is behind ProtectedRoute. [code: foodops.counter.app/src/App.tsx:147-314]

Route Purpose
/login · /auth/callback · /auth/silent-callback Auth (email+password; OIDC callbacks)
/update-required PWA force-update screen
/dashboard KPI dashboard (not in the rail; URL-only)
/counter Main till ("Orders" for foodops) — also /counter?intent=dinein|delivery|takeout
/sessions/:id/pos Session-scoped POS (the heart of the app)
/sessions/:id/orders/create · /sessions/:id/orders/:orderId/edit Create / edit an order (session-gated)
/sessions/:id/dinein Dine-in within a session
/takeout · /dine-in Takeout / dine-in entry points
/sales Sales list (online-only)
/customers · /customers/:id Customers
/register-sessions · /register-sessions/:id Register open/close + reconciliation
/reports/day-summary End-of-day Day Summary report
/conflicts Offline order version-conflict resolution
/settings Counter settings
/print/kot/:orderId/:kotId · /print/receipt/:orderId Print pages (no auth, new window)
/ and * Redirect → /counter

Admin app — route map (admin.foodops.io, foodops brand)

~100 lazy routes; the foodops-relevant domains (finance routes are tree-shaken out — see note). [code: foodops-admin-app/apps/admin/src/App.tsx:464-1258]

Domain Representative routes
Auth / onboarding /login, /register, /verify-email, /approve/:token, /onboarding/business, /onboarding/locale, /onboarding/outlet
Dashboard /dashboard, /assistant, /notifications
Catalog /catalog/items (+/:variantId), /catalog/groups, /catalog/categories, /catalog/modifiers, /catalog/brands, /catalog/price-lists (+/:id), /catalog/order
Sales /sales/register-sessions (+/:id), /sales/customers (+/:id), /sales/orders (+/new,/:id,/:id/edit,/imports), /sales/invoices (+/:id), /sales/payments (+/:id), /sales/returns, /sales/quotes, /sales/proforma-invoices, /sales/loyalty-programs
Expenses /expenses (index), /expenses/suppliers, /expenses/purchase-orders, /expenses/purchase-receipts, /expenses/records, /expenses/bills, /expenses/payments-made
Inventory /inventory
Costing /costing/overview, /costing/recipes, /costing/wastage-logs, /costing/wastage-reasons, /costing/yield, /costing/variance, /costing/food-cost
Marketing /marketing/overview, /marketing/campaigns, /marketing/promotions, /marketing/coupons (each + new/:id/edit)
Shopping list /shopping-list
Reports /reports/<name> — see Reports
Settings /settings + the 7 settings groups below

Finance is tree-shaken out of the foodops build. Accounting / banking / taxes / finance-reports routes (/accounting/*, /banking/*, /taxes/*, /reports/profit-loss, etc.) render <Navigate to="/dashboard"> on admin.foodops.io — they only exist on finance-v2.hubits.io. Navigating to one on foodops silently redirects to the dashboard. [code: foodops-admin-app/apps/admin/src/App.tsx:28-48 — INCLUDE_FINANCE]

Admin app — Settings (7 nav groups)

The settings rail is data-driven from SETTINGS_NAV; for the foodops brand all 7 groups show (finance-only items hidden). [code: foodops-admin-app/apps/admin/src/pages/settings/settingsNavConfig.ts:33-107]

# Group Items (foodops)
1 Organization Account Profile /settings/organization/profile · Users /settings/organization/users · Audit Log /settings/audit-log
2 Accounting Currencies /settings/organization/currencies · Taxes /settings/organization/taxes · Service Fees /settings/organization/service-fees · Payment Methods /settings/organization/payment-methods
3 Discounts Discounts /settings/discounts/list · Discount Reason Types /settings/discounts/reason-types
4 Outlets General /settings/restaurant/general · Outlets /settings/restaurant/outlets · Delivery Sectors /settings/restaurant/delivery-sectors
5 Inventory Units of Measure /settings/inventory/units
6 Customisation Pdf Templates /settings/customisation/pdf-templates · Transaction Series /settings/customisation/transaction-series · Import Wizard /settings/customisation/import-wizard
7 Integrations Integrations /settings/integrations

Finance-only settings items (Customer Portal, Approval Rules, Accountants, Period Locks, Organisation Groups) are hidden for foodops via showForBrands: ['finance'].

Onboarding wizard (new)

The legacy /onboarding/home 8-task wizard is retired. New-org setup now runs in the admin app as a 3-step wizard — /onboarding/business → /onboarding/locale → /onboarding/outlet — gated by OnboardingGate (which checks the sales API /onboarding/status). See Onboarding for the full flow.

Key concepts

  • Two SPAs — FoodOps is now two React Router apps: the counter (counter.foodops.io) and the admin (admin.foodops.io). Both are client-side routed; the paths above are in-app routes.
  • Route prefix convention (admin)/settings/* config, /reports/* reports, /catalog/* menu, /sales/* selling, /expenses/* purchasing, /inventory + /costing/* stock & food-cost.
  • Brand relabel — for the foodops brand the counter's "Counter" rail item is displayed as "Orders".
  • Finance is tree-shaken, not 404 — finance routes (/accounting/*, /banking/*, /taxes/*, finance reports) don't exist in the foodops bundle; navigating to one redirects to /dashboard (they live on finance-v2). A missing finance route is by-design, not deleted.
  • User management — under admin Settings → Organization → Users (/settings/organization/users); identity is shared with SSO.

Common questions

Q: Where do I find Users / Staff / Team management? A: Admin → Settings → Organization → Users (/settings/organization/users). Identity is shared with SSO (sso.hubits.io).

Q: Where's the dashboard / analytics? A: KPI snapshots are on the admin dashboard (/dashboard on admin.foodops.io) and the counter /dashboard; deeper analysis is in Reports (/reports/<name>). There is no separate /analytics route.

Q: I went to a finance/accounting page and it bounced me to the dashboard. Why? A: Expected. Finance (accounting, banking, taxes, finance reports) is tree-shaken out of the foodops build — those routes only exist on finance-v2. On foodops they redirect to /dashboard.

Q: How do I find a specific setting I can't remember? A: Admin /settings — the rail has 7 groups (Organization, Accounting, Discounts, Outlets, Inventory, Customisation, Integrations) plus a search box that filters items by label. [code: foodops-admin-app/apps/admin/src/pages/settings/settingsNavConfig.ts — filterNav]

Related

  • Onboarding — step-by-step setup guide

  • Menu Management — creating categories and items

  • Settings Overview — deep-dive on every settings sub-page

  • Users & Roles — SSO-based user management

  • 2026-08-08 — foodops-admin-app 45736a4..3db92a1. None of this diff's 5 commit subjects (Projects page, invoice paging fix, invoice outlet field, finance dashboard layout, project-from-invoice) touch Costing, so most of the '+' Costing sidebar block in brands.ts is a re-surfacing artifact of this diff's base (45736a4) predating the already-verified 2026-08-07 pass (verified_against_commit 2eaf621), which documented a 7-item Costing group (Overview, Food Cost %, Cost Variance, Recipe Costing, Recipe Data Quality, Wastage Log, Yield Analysis) — no action needed on those 7. The one item beyond that prior count is new: an 8th Costing child, 'Recipe Migration' (/costing/recipe-migration), gated ROLES.Costing.Manage only (unlike its read-only Costing siblings) per an explicit code comment noting it commits recipe cost changes org-wide. Additive to the entry's already-representative-not-exhaustive Costing domain row — no existing claim contradicted. Also re-surfaced from the 2026-08-07 pass and requiring no new action: the badgeKind: 'documents-review' type addition and the /expenses/documents sidebar wiring. Two changes in this diff are out of the entry's scope entirely: the Finance-brand rename ('Finance Admin' → 'Hubits Finance') and its new favicon/sidebarIcon/logo assets apply only to the finance brand config, not foodops/admin.foodops.io; and App.tsx's swap of every route from lazy() to a new lazyWithReload() helper is an internal deploy-resiliency change (auto-reloads a tab once if its hashed chunk 404s post-deploy) with no effect on any route path or the nav structure this entry documents. Worth a line next time this entry is touched: Costing now has a Manage-gated 'Recipe Migration' tool at /costing/recipe-migration, distinct from the group's otherwise read-only items. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-08-07 — foodops-admin-app 45736a4..2eaf621 adds a new Expenses 'Documents inbox' surface — /expenses/documents (DocumentsInboxPage) and /expenses/documents/:id (DocumentReviewPage), explicitly commented 'Phase 1.1 document intelligence' — and neither route is INCLUDE_FINANCE-gated, so both exist in the foodops build (not tree-shaken like Accounting/Banking/Taxes). Additive to the entry's Expenses domain row, which is already representative not exhaustive. The brands.ts hunk that wires a sidebar item + badge (badgeKind: 'documents-review') for this route sits in the Finance ('Hubits Finance', renamed from 'Finance Admin') brand's Expenses group in this diff slice — there's no evidence in this diff of a corresponding foodops-brand sidebar entry, so whether admin.foodops.io surfaces 'Documents' in-rail or only reaches it by URL (same pattern already documented for /dashboard and /creditcycle) is unconfirmed; worth checking on next read. Separately, a new Costing sub-item was added — /costing/data-quality (RecipeDataQualityPage, 'Recipe Data Quality') — alongside a full 7-item Costing sidebar group (Overview, Food Cost %, Cost Variance, Recipe Costing, Recipe Data Quality, Wastage Log, Yield Analysis) that maps directly onto the entry's existing Costing route list; additive only. A third new route, /accounting/projects (ProjectsPage), is wrapped in the same INCLUDE_FINANCE ? lazy(...) : ExcludedRoute gate as the entry's other cited finance-only pages, so it does not appear on admin.foodops.io — consistent with the entry's already-documented tree-shaken-finance behavior, no action needed there. None of this contradicts a documented claim. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-08-03 — foodops.counter.app 2e88679..f52b6dc changes how the counter sidebar handles clicks on any rail item flagged external (e.g. a link out to admin.foodops.io): a plain click no longer does an unconditional window.open, it now calls shouldConfirmAdminNav() and, unless the user has a saved opt-out preference, shows a new AdminAppRedirectDialog ('Continue to Admin') with a same-tab/new-tab choice before navigating; openAdminNav() fires immediately only when the preference says to skip the prompt. Separately, modified-click handling (Cmd/Ctrl/Shift/middle-click) was unified — external rail rows now fall through to native anchor <a href> behavior for new-tab/new-window opens instead of the old explicit item.external branch that always intercepted with preventDefault() + window.open, so an explicit open-in-new-tab gesture never triggers the confirmation dialog. This isn't a contradiction of the entry's documented rail table (Orders/Dine-In/Deliveries/Takeouts/Reports are all internal SPA routes, not external), but it's new cross-app navigation UX worth a line next time this entry is touched: any counter-sidebar item that jumps out to the admin app now interstitials through a confirm dialog on plain click (sticky via a saved preference), while modifier/middle-clicks bypass it. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-21 — foodops-admin-app f361a7c..fc28099 adds two new user-reachable admin routes: /catalog/items/product/:productId/edit (new ProductFormPage, alongside the existing /catalog/items/:variantId route) and a top-level /creditcycle route (new CreditCyclePage, explicitly commented 'intentionally not in sidebar nav' — the same URL-only pattern already documented for the counter's /dashboard and the admin's /settings/customisation/import-result). Neither contradicts the entry's Catalog/Sales route tables, which are explicitly representative, not exhaustive. Separately, apps/admin/src/config/brands.ts adds a new requiredRoles field and applies it across nearly every Catalog and Sales sidebar child item (Items, Modifiers, Categories, Brands, Menu Groups, Register Sessions, Customers, Quotes, Sales Orders, Invoices, Payments, Sales Returns, Loyalty Programs, Tip Pool) — these items are now hidden from the main admin sidebar unless the logged-in user holds at least one matching org-scoped role, layered on top of the brand-based (showForBrands) filter the entry already documents for Settings. Worth a line once the entry is next touched: a restricted-role staff account will now see a shorter Catalog/Sales sidebar than a full-access account — 'my sidebar item disappeared' for one user but not another is expected role-based behavior, not a bug. Also new but outside the entry's cited surface: a QueryClientProvider/React Query wrapper, plus lazy BillingSettingsPage, BmlPaymentGatewaySettingsPage, and StockReadinessSettingsPage imports, appear with no corresponding route hunk in this diff slice — insufficient evidence yet to document new billing/BML-gateway/stock-readiness routes. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-13 — foodops-admin-app 45245b7..f361a7c adds two new top-level admin routes for Catalog > Categories: /catalog/categories/new and /catalog/categories/:id/edit, both rendering a new lazy-loaded ProductCategoryFormPage, alongside the pre-existing /catalog/categories list route. Additive, not contradictory — the entry's Catalog domain row already lists /catalog/categories as a representative route without claiming an exhaustive sub-route list, matching the same pattern already noted for Modifiers, Payments Made, and PDF templates. Worth a line once the entry is next touched: Product Categories now has a dedicated full-page create/edit form rather than only an inline/list-view editor. The rest of this diff — the /catalog/modifiers/new and /:id/edit routes via ModifierGroupFormPage, the /expenses/payments-made/new and /:id/edit routes via PaymentMadeFormPage, and the PDF template editor's top-level full-screen routes — duplicates changes already captured in the 2026-07-13 (verified_against_commit 79be9d0), 2026-07-12 (verified_against_commit 3202946), and 2026-07-10 (verified_against_commit f1709e0) verification-history entries respectively; this diff's base (45245b7) simply predates all three prior verifications, so no further action needed on those. The StockCountFormPage lazy import reappears with still no corresponding route hunk in this diff slice — insufficient evidence to document a stock-count route. The account-profile logo-management, grid-dropdown, and recipe-output-unit commit subjects in this range touch no file on the entry's cited surface (App.tsx routes / Sidebar.tsx / settingsNavConfig.ts) and need no action here. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-13 — foodops-admin-app 45245b7..79be9d0 adds two new top-level admin routes for Catalog > Modifiers: /catalog/modifiers/new and /catalog/modifiers/:id/edit, both rendering a new lazy-loaded ModifierGroupFormPage, alongside the pre-existing /catalog/modifiers list route. Additive, not contradictory — the entry's Catalog domain row already lists /catalog/modifiers as a representative route without claiming an exhaustive sub-route list, matching the same pattern already noted for Payments Made and PDF templates. Worth a line once the entry is next touched: modifier groups now have dedicated full-page create/edit routes rather than only an inline/list-view editor. The rest of this diff (the /expenses/payments-made/new and /:id/edit routes via PaymentMadeFormPage, and the PDF template editor's move to top-level full-screen routes) duplicates changes already captured in the 2026-07-12 (verified_against_commit 3202946) and 2026-07-10 (verified_against_commit f1709e0) verification-history entries respectively — this diff's base (45245b7) simply predates both prior verifications, so no further action needed on those two. A StockCountFormPage lazy import was also added but no corresponding route hunk is present in this diff slice, so there's insufficient evidence yet to document a new stock-count route. (auto-applied by the truth pipeline; adversarially gated) (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-12 — foodops-admin-app 45245b7..3202946 adds two new top-level admin routes under the Expenses > Payments Made surface: /expenses/payments-made/new and /expenses/payments-made/:id/edit, both rendering a new lazy-loaded PaymentMadeFormPage component, sitting alongside the pre-existing /expenses/payments-made/:id details route. This is additive, not contradictory — the entry's Expenses domain row already lists /expenses/payments-made as a representative route without claiming an exhaustive sub-route list, so no existing claim is broken. Worth a line in the Expenses table (or a Related note) once the entry is next touched: Payments Made now has a dedicated full-page create/edit form rather than only a details/view page. Separately, this diff's PDF-template-editor hunk (moving /settings/customisation/pdf-templates/new and /:id/edit out of the nested SettingsShell tree into top-level full-screen routes) is the SAME change already captured in the entry's 2026-07-10 verification-history entry (verified_against_commit f1709e0) — no new action needed there, it's just re-surfaced because this diff's base (45245b7) predates that prior verification. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-10 — foodops-admin-app 45245b7..f1709e0 moves the PDF Template editor (/settings/customisation/pdf-templates/new and /settings/customisation/pdf-templates/:id/edit) out of the nested SettingsShell route tree into two top-level routes rendered full-screen (own Toolbar with back/save, no settings nav rail). URLs are unchanged — still under the /settings/customisation/pdf-templates/... prefix documented in the entry's Settings table (item 6, Customisation group) — so no existing claim is contradicted, but the entry's Settings table only lists the list page (/settings/customisation/pdf-templates) and doesn't describe the editor's chrome; worth a line noting that opening 'New' or 'Edit' on a PDF template now opens a distraction-free full-screen canvas rather than a page boxed inside the Settings panel, since a user/agent reporting 'the settings sidebar disappeared' when editing a template is expected behavior, not a bug. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-10 — foodops.counter.app 6885e57..e4e7aaa (icon-migration series). No contradiction of documented routes: the diff adds a new resolveItemHref/handleNavAnchorClick pair that explicitly mirrors the existing handleMenuClick branching, and its logic matches this entry's documented rail routing (Dine-In → /sessions/:id/dinein or ?intent=dinein; Deliveries/Takeouts → /sessions/:id/pos?mode=... or ?intent=...; Reports → /reports/day-summary), so it confirms rather than changes the URL map. What's new and worth a line: desktop and mobile sidebar rail rows were converted from <button onClick> to <a href=...>, so right-click 'Open in new tab', Ctrl/Cmd+click, and middle-click now work natively on the counter rail (previously only in-app SPA navigation was possible). Separately, as part of an app-wide Hugeicons→lucide icon swap, the 'Counter' fallback icon class changed from hgi hgi-stroke hgi-shipping-center to lucide's airplay — cosmetic only, not previously documented in this entry, no action needed. (auto-applied by the truth pipeline; adversarially gated)

  • 2026-07-04 — foodops-admin-app 88dfde2..cc539d1 adds a new 8th SETTINGS_NAV group, 'AI Assistant' (icon Sparkles), with two items — AI Autonomy (/settings/ai/autonomy) and AI Activity (/settings/ai/activity) — both gated showForBrands: ['finance'], so consistent with the entry's existing 'finance-only items hidden for foodops' pattern these stay hidden on admin.foodops.io for now; the documented '7 nav groups' count for foodops is not contradicted but should be re-confirmed once the actual group-level filter (not just item-level) is read, since this is the first group whose items are 100% finance-gated. Also new: a URL-only result page /settings/customisation/import-result (ImportResultPage) was added under the existing Customisation group — not added to settingsNavConfig.ts, so it's reachable only by URL/redirect (e.g. after running the Import Wizard), same pattern as the counter's rail-less /dashboard. Separately, brands.ts now ships a brand-configurable AI 'docked panel' (assistant: {enabled, title, suggestions}) and this is explicitly enabled for the foodops brand with foodops-flavoured suggestion chips ('How did we do today?', 'Give me my margin brief', 'Which invoices are overdue?') — this substantiates/extends the entry's already-listed /assistant route under the admin Dashboard domain and is worth a line noting the assistant panel is now live and brand-tuned for foodops. (auto-applied by the truth pipeline; adversarially gated)

Warning: 2026-06-29 — REBUILT for new stack (July-10 launch) · codebase Verified_by: codebase · Last verified: 2026-06-29 · foodops.counter.app@32669a9 (main) + foodops-admin-app@4173811 (main) Full re-point off the retired haafai.app.foodops monolith. Replaced the legacy MVC URL map with the two new SPAs: counter (counter.foodops.io — routes from src/App.tsx:147-314, rail from Sidebar.tsx) and admin (admin.foodops.io — ~100 routes from apps/admin/src/App.tsx:464-1258, settings from settingsNavConfig.ts). Confirmed: counter allowedItems rail = Counter("Orders")/Dine-In/Deliveries/Takeouts/Reports (Dashboard URL-only); KDS is a separate kds.html bundle (no /kitchen route); admin domains Catalog/Sales/Expenses/Inventory/Costing/Marketing/Reports/Settings; Settings = 7 nav groups (Organization, Accounting, Discounts, Outlets, Inventory, Customisation, Integrations). Documented Finance routes as tree-shaken out of the foodops build (redirect to /dashboard, not 404). Onboarding wizard re-pointed to the 3-step admin wizard. Dropped all legacy /dashboards,/orders,/tables,/kitchen/index,/menuitems,etc. Sidebar icon order + live nav-API payload not re-probed (code-only).

Success: Verified 2026-06-11 · codebase (LEGACY monolith — superseded) Status: stable · Confidence: medium (routes code-confirmed; HTTP statuses and sidebar behaviour from the original live probe)

  • 2026-06-11 — codebase validation pass against haafai.app.foodops@a8ea20b (main). Every 200-OK route in the tables maps to a real MVC controller under the default route pattern (Startup.cs:1045-1047): Dashboards, Orders, Tables, Delivery, Takeouts, Kitchen, Reservations, SalesSessions, MenuCategories, MenuItems, Modifiers, Recipes, Ingredients, Reports, Onboarding in Haafai.Restaurant.App; Customers in Haafai.Sales; Suppliers + PurchaseOrders in Haafai.Expenses; Settings in Haafai.Layouts. All 8 onboarding-wizard task labels confirmed verbatim in Views/Onboarding/Home.cshtml (incl. "Send a Feedback" and the SSO users deep-link). 404 table upgraded with code-level causes: /analytics Index action is commented out in AnalyticsController; /shoppinglists is a near-miss (controller is singular ShoppingListController); /mealplans likely lives at /mealsubscriptionplans. Sidebar icon order, SPA javascript:void(0) behaviour, and live HTTP statuses were not re-probed — original Playwright observations retained.

Additional verification events are appended here by the weekly KB sync and by manual re-verification passes. See _meta/failure-log.md for the global failure index.

Go beyond POS.
Choose the total solution.

Focus on creating the best experience for your guests while we handle the rest.