adds a /pay/{token} redirect endpoint that generates a short URL
pointing to a stripe checkout sessions in setup mode. The TUI shows a QR
code and URL on the payment page so users can add a card via the browser
instead of entering raw card data over SSH.
the checkout.session.completed webhook saves the card to the database.
the TUI polls GET /api/v1/cards every second and auto-proceeds to
confirmation once the new card is detected.
also adds a dev.sh startup script that runs all four required processes.
(SSH server, API server, Stripe CLI listener, ngrok) in a single
terminal
3.7 KiB
3.7 KiB
TODO
Done
- Cart persistence across sessions
- Token refresh — auto-refresh JWT before expiry
- Help screen — press ? to show keybindings
- Order detail view — press Enter on an order to see full details
- FAQ page
- About page
- Splash screen — logo + auth + data preload on connect
- Bulk data preload — /view/init endpoint fetches all user data at once
- Stripe webhook — payment_intent.succeeded/failed sync order status
- PCI-safe card tokenization — publishable key in SSH process, raw card data never reaches backend
- Rate limiting — per-IP and per-user limits on sensitive endpoints
- Audit logging — structured JSON logs for all financial events
- Shop page — dual viewport (menu left, detail right), matches reference shop.go
- Cart page — single viewport with proper scroll
- Shipping page — single viewport
- Payment page — single viewport
- Confirm page — single viewport (uses DefaultKeyMap for pgup/pgdn scrolling)
Do First (meaningful gaps vs reference)
Product variants
The reference supports multiple variants per product (roast type, grind, size) with separate prices. We treat every product as single-variant. Without this the shop is very limited once you have real products.
- Variant model + DB migration
- API: return variants in /products response
- TUI: show variant selector in shop detail panel
User profile editing
Users currently cannot update their name or email from inside the app.
- PUT /api/v1/profile endpoint
- TUI: editable name/email fields in account view
Missing API endpoints
- PUT /api/v1/addresses/:id — update a saved address
- GET /api/v1/orders/:id — single order (needed for better order detail view)
Polish (noticeable but not blocking)
- Animated cursor — reference has a blinking block cursor on the splash/logo (cursor.go, CursorTickMsg, 700ms interval). Small but gives the app personality.
- Themed UI — reference has a theme/ package; we use hardcoded hex colors everywhere. Makes it hard to change the look later.
- Shipping timeframe — Shippo returns estimated delivery window; show it on confirm page
- Loading spinner — replace plain "loading..." text with animated spinner
- HTTPS/QR payment option — third card-entry method, generates a one-time URL + QR code so users can enter card details in their browser instead of over SSH. Reference: payment.go paymentHttpsView, PollPaymentInitMsg/StatusMsg/CompleteMsg.
- Per-field card validation — use huh .Validate() on each form field so errors show inline as user tabs through, instead of a single error on submit.
Testing
- API client tests — pkg/api/client.go has no tests
- Card handler tests — api/handlers/cards.go
- Order handler tests — api/handlers/orders.go
- Address handler tests — api/handlers/addresses.go (partial)
- Webhook handler tests — api/handlers/webhook.go
- TUI payment form tests — validatePaymentForm() is pure and easy to unit test
Post-Launch
- Shippo webhook — order tracking status updates pushed from Shippo
- Email system — order confirmation + shipped notification
- Subscription model — DB table, CRUD endpoints, TUI flow (select → shipping → payment → confirm)
- Subscription management — list, detail, cancel with confirmation in account view
- Personal access tokens — model, CRUD API, TUI management in account view
- OAuth app management — model, CRUD API, TUI create/list/delete
- Region-based product filtering — IP geolocation, press 'r' to toggle
- Cron jobs — subscription processing, inventory tracking, unshipped alerts