19 — Storefront (e‑commerce)

Public multi-tenant shop: catalog → guest cart → tender → Core Invoice

CEO Summary

Storefront is the public online shop for each business. Shoppers browse menus/catalogs, add items to a guest cart, enter contact/shipping, pay with card or crypto, and land on a Core Invoice + optional receipt email — same money spine as POS. Business value: Online sales without a separate e‑com stack. Key metrics: Storefront orders, conversion, AOV. If this breaks: Online checkout fails; POS/in-person sales still work.

Architecture

flowchart TB subgraph client [Client] Public[Public Storefront UI] Admin[Admin Storefront Settings] end subgraph api [API] SF[storefront.routes] CartSvc[storefrontCart.service] Core[Core Invoicing] Crypto[cryptoMode Easy/Advanced] end subgraph db [Tenant main DB] Config[(storefront_settings)] Menu[(Menus / MenuAssignments)] Cats[(Catalogs)] Carts[(pos_carts)] Inv[(Invoices)] end Public --> SF Admin --> SF SF --> Config SF --> Menu SF --> Cats SF --> CartSvc CartSvc --> Carts CartSvc --> Crypto CartSvc --> Core Core --> Inv

Overview

Customer-facing store per tenant. Public routes use tenantSlug from the URL (/{slug}/store). No staff session required when guest checkout is allowed.

Guest checkout flow

  1. Create or resume guest cart (localStorage cart id)
  2. Add/remove items; optional tip
  3. POST …/checkout — email (required), name, phone, shipping address + shipping cents
  4. Tender: card (simulate in non-prod) or crypto (Easy hosted URL or Advanced native QR)
  5. POST …/finalize — requires full payment + email → Core Invoice (shipping/tip as lines) + optional receipt email
  6. Order confirmation UI; new cart on “Continue shopping”

API Endpoints

MethodPathAuthPurpose
GET/api/storefront/:tenantSlug/configPublicBranding, shipping flags, SEO
GET/api/storefront/configSessionAdmin: get config
PUT/api/storefront/configSessionAdmin: update config
GET/api/storefront/:tenantSlug/menu-itemsPublicProducts for shop
POST/api/storefront/:tenantSlug/cartsPublicCreate guest cart
GET/api/storefront/:tenantSlug/carts/:cartIdPublicGet cart + totals
POST/api/storefront/:tenantSlug/carts/:cartId/itemsPublicAdd lines
DELETE/api/storefront/:tenantSlug/carts/:cartId/items/:lineIdPublicRemove line
POST/api/storefront/:tenantSlug/carts/:cartId/tipPublicSet tip
POST/api/storefront/:tenantSlug/carts/:cartId/checkoutPublicContact + shipping
POST/api/storefront/:tenantSlug/carts/:cartId/tender/cardPublicCard tender
POST/api/storefront/:tenantSlug/carts/:cartId/tender/cryptoPublicDOGE/LTC/BTC
POST/api/storefront/:tenantSlug/carts/:cartId/finalizePublicCore Invoice + receipt

Config Fields

FieldPurpose
enabledStorefront on/off (defaults on for public if unset)
storeName, storeDescriptionStore branding
primaryColor, secondaryColor, backgroundColor, textColorTheme
logoUrl, faviconUrlAssets
showSearch, showCategoriesLayout
productsPerPagePagination
currency, taxIncluded, taxRateBpsPricing
shippingEnabled, flatShippingCentsShipping UX + amount
allowGuestCheckout, requireAccountCheckout options
shopCatalogIdFull-catalog shop when no menu assigned
seoSettings, footerText, socialLinksSEO / footer

Integration Points

SystemConnection
Core Invoicingfinalize → createPOSSaleInvoice; channel=storefront
POS cartsShared pos_carts tenant SQL (org-scoped)
CryptostartCryptoTender Easy hosted or Advanced native
Ops emailOptional invoice receipt after finalize
Catalog / menusMenuAssignments target_type=storefront

Key Paths

PathPurpose
backend/routes/storefront.routes.jsPublic + admin storefront API
backend/services/storefrontCart.service.jsGuest cart, tender, finalize
frontend/src/pages/store/Storefront.jsxShopper UI
frontend/src/pages/admin/StorefrontSettings.jsxMerchant config

Post-sale rails

After Core Invoice commit, saleSideEffects.service.js (best-effort):

Admin: GET /api/storefront/orders lists recent channel=storefront invoices; Storefront Settings shows tax bps, flat shipping, shop catalog, and recent orders.

Roadmap (next)