Context & Goal

The DN Ops Dashboard at ops.delinerds.com is currently a static ~2,000-line HTML file served via CF Pages. Data comes from a nightly-generated snapshot.json baked at build time. This makes the dashboard stale, unfilterable, and unable to support any write-back actions.

Do NOT build any new interactivity features (restocking, Square write-back, etc.) in this pass. This is a pure architecture migration β€” same visual output, live data source. Features come after the foundation is correct.

Architecture After This Build

🌐 Browser
ops.delinerds.com
↓ CF Pages static HTML/JS
πŸ”’ CF Access
@delinerds.com only
↓ CF Tunnel
⚑ FastAPI
localhost:5050
↓ psycopg2 pool
πŸ—„ dn_warehouse
PostgreSQL Β· hindsight@127.0.0.1:5432

Port 5050 and the LaunchAgent plist (com.openclaw.deli-ops-dashboard) are pre-configured with WAREHOUSE_BACKEND=postgres and correct DSN. The backend code directory is empty β€” this build populates it.

Build Steps

1

FastAPI Backend β€” Port 5050

Create workspace/projects/deli-ops-dashboard/backend/ with the following structure. Use beo-api as the template for auth, CORS, and DB pool patterns.

backend/
β”œβ”€β”€ main.py
β”œβ”€β”€ db.py             β† import get_connection from warehouse_db.py
β”œβ”€β”€ config.py
β”œβ”€β”€ routers/
β”‚   β”œβ”€β”€ overview.py
β”‚   β”œβ”€β”€ sales.py
β”‚   β”œβ”€β”€ inventory.py
β”‚   β”œβ”€β”€ labor.py
β”‚   β”œβ”€β”€ catering.py
β”‚   └── finance.py
└── requirements.txt
Auth pattern: read Cf-Access-Authenticated-User-Email header. No app-level login β€” CF Access handles it.
2

API Endpoints

All endpoints accept optional from_date and to_date query params (ISO date, default last 30 days). Auth required on all.

EndpointSource Table(s)Returns
GET /healthβ€”DB status + warehouse last sync timestamp
GET /api/overviewsquare_orders, sync_logRevenue 30d, orders 30d, AOV, top category, warehouse freshness
GET /api/sales/dailysquare_orders, square_order_itemsDaily revenue + order buckets
GET /api/sales/by-channelsquare_ordersIn-Person / Online / Catering / Delivery split
GET /api/sales/by-categorysquare_order_items, square_catalogRevenue by menu category
GET /api/items/topsquare_order_items, square_catalogTop items by revenue + units
GET /api/labor/summarysquare_laborTotal hours, OT, labor cost, labor % revenue
GET /api/labor/dailysquare_laborDaily hours + cost buckets
GET /api/food-cost/summarymarketman_invoicesTotal spend, food cost %, top vendor
GET /api/food-cost/by-vendormarketman_invoices, marketman_invoice_itemsVendor spend breakdown
GET /api/prime-costsquare_orders + square_labor + marketman_invoicesRevenue, COGS, labor, prime cost %
GET /api/inventory/eighty-sixmarketman_inventory_counts, marketman_itemsItems at qty ≀ 0 with days_at_zero
GET /api/inventory/at-riskmarketman_inventory_counts, marketman_itemsItems below par level
GET /api/inventory/count-disciplinemarketman_inventory_countsCount completeness stats
GET /api/catering/summarypublic.airtable_beosEvent count, confirmed, revenue, avg event value
Catering endpoint reads from public.airtable_beos (historical) until dn_catering β†’ dn_warehouse migration completes. Mark with # TODO: switch to catering schema post-migration.
3

Frontend Rewrite

Replace frontend/dist/index.html. Same visual design (dark theme, Inter, existing tab structure). Key changes:

  • Remove snapshot.json β€” delete all references
  • Remove password gate (Delinerd$1) β€” CF Access handles auth entirely
  • Add global date range picker in top nav (default: last 30 days) β€” all API calls use selected range
  • Add loading skeletons per section while fetch resolves
  • Add "Data as of [timestamp]" freshness indicator in top nav
  • Add inline error states β€” never full-page error
  • Implement URL hash routing per approved 2026-05-05 spec: #exec, #daily, #inventory/eighty6, #inventory/oos, #inventory/discipline, #finance, #catering
  • Add NAV RULE comment block in JS as specified
4

Infrastructure

Three infrastructure changes required:

  1. Add to ~/.cloudflared/config.yml ingress: hostname: ops-api.delinerds.com β†’ http://localhost:5050. Restart cloudflared.
  2. Add DNS CNAME in delinerds.com zone (id: dffc74fe06aedf828b67012bcc616f87): ops-api β†’ <tunnel-id>.cfargotunnel.com, proxied.
  3. Create CF Access app on account bd7970f7f6f702c95697ea234e39d3b2: domain ops-api.delinerds.com, allow @delinerds.com email domain.

After backend code is written: launchctl unload then launchctl load the plist. Deploy frontend: npx wrangler pages deploy dist --project-name deli-nerds-ops-dashboard.

5

ARCHITECTURE.md

Create workspace/projects/deli-ops-dashboard/ARCHITECTURE.md documenting: port 5050, DB (dn_warehouse public schema), auth pattern, tunnel hostname, CF Pages deploy command, LaunchAgent label.

Quasar QA Checklist

Out of Scope β€” This Pass

Do not build in this pass: Square write-back, restocking workflow, 86'd item resolution, any new tabs or data sections, any new features. This is a pure architecture migration.