From ae3c85fee0138416d0c8bca90e1e03f391254a6c Mon Sep 17 00:00:00 2001 From: Ryan Moon Date: Mon, 30 Mar 2026 19:08:16 -0500 Subject: [PATCH] =?UTF-8?q?Add=20frontend=20strategy=20planning=20doc=20?= =?UTF-8?q?=E2=80=94=20admin,=20POS,=20floor=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- planning/28_Frontend_Strategy.md | 216 +++++++++++++++++++++++++++++++ 1 file changed, 216 insertions(+) create mode 100644 planning/28_Frontend_Strategy.md diff --git a/planning/28_Frontend_Strategy.md b/planning/28_Frontend_Strategy.md new file mode 100644 index 0000000..b79ef3a --- /dev/null +++ b/planning/28_Frontend_Strategy.md @@ -0,0 +1,216 @@ +LunarFront Platform + +Frontend Strategy — Multiple UI Surfaces + +Version 1.0 | Draft + + + +# 1. Overview + +LunarFront serves different users in different contexts — a store owner at their desk, a cashier at the counter, a staff member receiving stock in the back room, and a salesperson at a trade show. One UI cannot serve all of these well. + +The platform uses a single backend API with multiple purpose-built frontends. Each frontend is a separate package in the monorepo, shares the same `@lunarfront/shared` schemas and types, and calls the same REST API. The backend doesn't know or care which frontend is making the request. + + + +# 2. Frontend Packages + +## 2.1 Admin UI — `packages/admin` + +**Status:** Active development (current) + +| Attribute | Detail | +|-----------|--------| +| Form factor | Desktop / laptop, large tablet | +| Stack | React, Vite, TanStack Router, TanStack Query, shadcn/ui | +| Users | Store owner, manager, back-office staff | +| Access | Web browser | + +**Purpose:** Full management interface. Everything that isn't a real-time transaction happens here — accounts, members, inventory configuration, RBAC, roles, reports, settings, lesson scheduling, repair management, vault. + +**Design priorities:** +- Dense information display (data tables, detail pages) +- Keyboard-friendly (tab navigation, search) +- Multi-column layouts, sidebars, dialogs +- Not optimized for touch or small screens — that's intentional + +## 2.2 POS UI — `packages/pos` + +**Status:** Planned + +| Attribute | Detail | +|-----------|--------| +| Form factor | Counter-mounted tablet (10"+) or touchscreen monitor | +| Stack | React, Vite (same toolchain as admin) | +| Users | Cashier, sales associate | +| Access | Web browser (full-screen / kiosk mode) | + +**Purpose:** Point-of-sale for in-store transactions. Staff stares at this 8 hours a day. Every interaction must be fast and require minimal taps. + +**Design priorities:** +- Always-on, single-screen (no page navigation) +- Large touch targets (44px+ minimum) +- Fast product search (keyboard wedge barcode scanner + text search) +- Cart management (add, remove, adjust quantity, apply discount) +- Payment flow (cash, card via terminal, split payment) +- Cash drawer integration +- Receipt printing (thermal printer via browser print or ESC/POS) +- Session management (clock in/out, cash drawer open/close, X/Z reports) +- Offline resilience — queue transactions if network drops, sync when back + +**Key screens:** +1. **Sale screen** — product search (left), cart (right), totals + pay button (bottom) +2. **Payment screen** — amount due, payment method selection, card terminal status, change calculation +3. **Return/exchange screen** — lookup original transaction, select items, process refund +4. **Drawer management** — open session, cash drops, close session with counts + +**Hardware integration:** +- Barcode scanner: keyboard wedge (types into focused input, no special API) +- Card reader: local network or USB terminal via Stripe Terminal SDK or Global Payments SDK +- Cash drawer: triggered via receipt printer (kick pulse) or USB relay +- Receipt printer: ESC/POS over USB or network, or browser `window.print()` with receipt-formatted CSS + +## 2.3 Floor App — `packages/floor` + +**Status:** Planned + +| Attribute | Detail | +|-----------|--------| +| Form factor | Phone or small tablet | +| Stack | React Native (Expo) or PWA | +| Users | Sales staff on floor, inventory staff, trade show sales | +| Access | Native app (iOS/Android) or PWA in Safari/Chrome | + +**Purpose:** Two modes in one mobile app — inventory management and mobile sales. Both are walk-around-the-store (or walk-around-a-trade-show) workflows with scanning, big inputs, and minimal typing. + +**Design priorities:** +- Phone-first layout (single column, stacked) +- Camera barcode scanning (no external scanner needed) +- Large buttons, minimal text input +- Works on cellular (trade shows) and store WiFi +- Offline support for inventory counts (sync when connected) + +### Inventory Mode + +**Purpose:** Receiving, cycle counts, transfers, shelf checks. + +**Key screens:** +1. **Receive stock** — scan items, enter quantities, confirm receipt against purchase order +2. **Cycle count** — scan location/shelf, scan items, enter counts, submit discrepancies +3. **Quick lookup** — scan barcode, see product details, stock levels across locations, price history +4. **Transfer** — scan items to move between locations +5. **Condition check** — scan item, update condition (new, used, damaged), add notes/photo + +### Mobile POS Mode + +**Purpose:** Sales at trade shows, on the shop floor, off-site events. + +**Key screens:** +1. **Quick sale** — search/scan products, add to cart, take payment +2. **Payment** — Bluetooth card reader integration, or manual card entry +3. **Customer lookup** — search by name/phone/account number for account-linked sales +4. **Receipt** — email or text receipt (no printer at a trade show) + +### Build Strategy + +**Phase 1 — PWA:** +- Build as a web app with mobile-optimized UI +- "Add to Home Screen" for app-like experience +- Camera scanning via `navigator.mediaDevices` + barcode detection library +- Local network card reader for payments +- No App Store, no developer cert, works on any device + +**Phase 2 — Native (if needed):** +- React Native with Expo +- Reuses `@lunarfront/shared` schemas and business logic +- Native Bluetooth for card reader pairing +- Native camera for faster barcode scanning +- Requires Apple Developer ($99/year) and Google Play ($25 one-time) +- Only worth it if PWA limitations become blockers (Bluetooth, offline, performance) + + + +# 3. Shared Infrastructure + +All frontends share: + +| Layer | Package | What it provides | +|-------|---------|------------------| +| Validation | `@lunarfront/shared` | Zod schemas — same validation client and server | +| Types | `@lunarfront/shared` | TypeScript interfaces for all domain entities | +| Business logic | `@lunarfront/shared` | Formatters, calculators, state normalization | +| API | Backend REST | Same endpoints, same auth, same response format | +| Auth | JWT | Same token works across all frontends | +| Permissions | RBAC | Same permission checks — POS user doesn't need admin access | + +This means: +- A bug fix in a Zod schema fixes validation everywhere +- A new API endpoint is immediately available to all frontends +- No data format translation between frontends +- One test suite covers the API regardless of which frontend calls it + + + +# 4. Permission Mapping + +Different frontends surface different permissions: + +| Permission | Admin | POS | Floor | +|------------|-------|-----|-------| +| `accounts.view/edit/admin` | Yes | View only (customer lookup) | View only | +| `inventory.view/edit/admin` | Yes | View only (product search) | Full access | +| `pos.view/edit/admin` | Reports only | Full access | Mobile POS mode | +| `rentals.*` | Yes | Process returns | No | +| `lessons.*` | Yes | No | No | +| `repairs.*` | Yes | Intake only | No | +| `vault.*` | Yes | No | No | +| `users.*` | Yes | No | No | + +The backend enforces permissions regardless — the frontend just decides what to show. + + + +# 5. Offline Strategy + +Offline support is critical for POS (network drops) and Floor (dead zones in warehouse). + +**POS offline:** +- Cache product catalog in IndexedDB (refresh periodically) +- Queue transactions locally when offline +- Process card payments when back online (or show "cash only" mode) +- Sync queue when connection restores +- Visual indicator: "Offline — transactions will sync when connected" + +**Floor offline (inventory):** +- Cache current inventory counts +- Store count entries locally +- Sync on reconnect +- Conflict resolution: last-write-wins with audit log of discrepancies + +**Admin:** +- No offline support needed. Back-office work requires connectivity. + + + +# 6. Deployment + +| Frontend | Hosting | Notes | +|----------|---------|-------| +| Admin | Same server as backend (Caddy/nginx serves static files) | Single origin, no CORS | +| POS | Same server or dedicated POS terminal | Kiosk mode browser, auto-launch on boot | +| Floor | PWA from same server, or App Store | Phone/tablet accesses over store WiFi or cellular | + +For on-prem: all frontends are served from the same LunarFront server. One box, one URL, multiple apps at different paths (`/admin`, `/pos`, `/floor`). + + + +# 7. Implementation Order + +1. **Admin UI** — current, continue until core management is complete +2. **POS UI** — next major effort after admin is stable. This is the revenue-critical surface. +3. **Floor App (Inventory mode)** — PWA first. Enables stock receiving and cycle counts. +4. **Floor App (Mobile POS mode)** — add-on to floor app. Trade show / floor sales. +5. **Floor App (Native)** — only if PWA hits limitations. Bluetooth reader, performance, offline. + +Each frontend is independently deployable. Stores can run just Admin + POS if they don't need mobile inventory. Modules control which features are available, not which frontends are installed.