19 — Storefront (e‑commerce)
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
Overview
Customer-facing store per tenant. Public routes use tenantSlug from the URL (/{slug}/store). No staff session required when guest checkout is allowed.
- Base path:
/api/storefront - UI:
frontend/src/pages/store/Storefront.jsx - Cart service:
backend/services/storefrontCart.service.js→ samepos_carts+ Core Invoicing as POS - Catalog sources (in order): Menu assignment → shopCatalogId → first non-empty Catalog
Guest checkout flow
- Create or resume guest cart (
localStoragecart id) - Add/remove items; optional tip
POST …/checkout— email (required), name, phone, shipping address + shipping cents- Tender: card (simulate in non-prod) or crypto (Easy hosted URL or Advanced native QR)
POST …/finalize— requires full payment + email → Core Invoice (shipping/tip as lines) + optional receipt email- Order confirmation UI; new cart on “Continue shopping”
API Endpoints
| Method | Path | Auth | Purpose |
|---|---|---|---|
| GET | /api/storefront/:tenantSlug/config | Public | Branding, shipping flags, SEO |
| GET | /api/storefront/config | Session | Admin: get config |
| PUT | /api/storefront/config | Session | Admin: update config |
| GET | /api/storefront/:tenantSlug/menu-items | Public | Products for shop |
| POST | /api/storefront/:tenantSlug/carts | Public | Create guest cart |
| GET | /api/storefront/:tenantSlug/carts/:cartId | Public | Get cart + totals |
| POST | /api/storefront/:tenantSlug/carts/:cartId/items | Public | Add lines |
| DELETE | /api/storefront/:tenantSlug/carts/:cartId/items/:lineId | Public | Remove line |
| POST | /api/storefront/:tenantSlug/carts/:cartId/tip | Public | Set tip |
| POST | /api/storefront/:tenantSlug/carts/:cartId/checkout | Public | Contact + shipping |
| POST | /api/storefront/:tenantSlug/carts/:cartId/tender/card | Public | Card tender |
| POST | /api/storefront/:tenantSlug/carts/:cartId/tender/crypto | Public | DOGE/LTC/BTC |
| POST | /api/storefront/:tenantSlug/carts/:cartId/finalize | Public | Core Invoice + receipt |
Config Fields
| Field | Purpose |
|---|---|
| enabled | Storefront on/off (defaults on for public if unset) |
| storeName, storeDescription | Store branding |
| primaryColor, secondaryColor, backgroundColor, textColor | Theme |
| logoUrl, faviconUrl | Assets |
| showSearch, showCategories | Layout |
| productsPerPage | Pagination |
| currency, taxIncluded, taxRateBps | Pricing |
| shippingEnabled, flatShippingCents | Shipping UX + amount |
| allowGuestCheckout, requireAccount | Checkout options |
| shopCatalogId | Full-catalog shop when no menu assigned |
| seoSettings, footerText, socialLinks | SEO / footer |
Integration Points
| System | Connection |
|---|---|
| Core Invoicing | finalize → createPOSSaleInvoice; channel=storefront |
| POS carts | Shared pos_carts tenant SQL (org-scoped) |
| Crypto | startCryptoTender Easy hosted or Advanced native |
| Ops email | Optional invoice receipt after finalize |
| Catalog / menus | MenuAssignments target_type=storefront |
Key Paths
| Path | Purpose |
|---|---|
backend/routes/storefront.routes.js | Public + admin storefront API |
backend/services/storefrontCart.service.js | Guest cart, tender, finalize |
frontend/src/pages/store/Storefront.jsx | Shopper UI |
frontend/src/pages/admin/StorefrontSettings.jsx | Merchant config |
Post-sale rails
After Core Invoice commit, saleSideEffects.service.js (best-effort):
- Match lines to
InventoryItemsby SKU / numeric id /cat-N - Decrement
InventoryLevels(default location) + writeinventoryledger(idempotent reference) - POS analytics + customer analytics when email present
Admin: GET /api/storefront/orders lists recent channel=storefront invoices; Storefront Settings shows tax bps, flat shipping, shop catalog, and recent orders.
Roadmap (next)
- Real Stripe/online card (replace non-prod simulate)
- Hard gate when requireAccount=true
- Inventory reservation at add-to-cart (vs deduct-on-paid)
- Per-rate shipping tables / pickup vs ship