CODEX // oaoisme wiki

§ ShopBot — Telegram commerce demo

The live dashboard — SSE, design & the e2e bar

updated 2026-06-27

The dashboard is the demo's showpiece: a dark "control-room" board where a business owner watches the shop run. Open inventory.oaoisme.top and you see the catalogue with live stock, a KPI strip, an order feed, and a ticker — all of which update the instant something happens, with no page refresh.

How "live" works — Server-Sent Events

The backend exposes GET /api/stream, a Server-Sent Events (SSE) endpoint. The browser opens it once (new EventSource('/api/stream')) and keeps it open; the server pushes named events down that one connection as they occur:

Event Fired when Dashboard reaction
order.created a new order is placed prepend a card to the feed, bump KPIs, ticker
order.paid a payment clears (webhook) flip the card to PAID, raise revenue, ticker
stock.changed stock decrements or a restock update the product's stock pill, flash it
reset the demo is reset reload everything

SSE was chosen over WebSockets because the data flow is one-way (server → browser) and SSE is far simpler: it's just an HTTP response that never ends, auto-reconnects in the browser, and needs no extra protocol. On the server it's a reply.hijack() and a Set of open responses that get written to on each event. A 25-second comment ping keeps proxies from closing the idle connection.

A subtle but important detail for nginx: SSE responses set X-Accel-Buffering: no so nginx streams them through instead of buffering — otherwise events would arrive in batches, not live.

The design language — "The Counter"

The look is documented in /root/apps/shopbot/design.md. In one line: a warm espresso-black point-of-sale terminal with a single scarce magenta accent and tabular-mono numerics. The deliberate moves:

  • One accent colour (magenta) used only on the brand, primary action, focus ring, and the flash when live data lands — never decoratively. Status uses a separate, disciplined green/amber/red triad, so the brand never collides with "paid / awaiting / out of stock".
  • Flat depth — 1px hairline borders and surface layering do the work that drop-shadows would; the only soft light is the data-update flash.
  • Tabular mono numbers everywhere they can change (prices, stock, totals) so figures tick like a ticker instead of jittering as their width changes.
  • Signature structures: a marquee ticker tape of recent events, and an order feed laid out as a "StoryStream" timeline on a dashed rule.

The direction was chosen to be visibly different from every other site on the box — no blueprint-navy (that's the monitor), no teal (the forge), no editorial paper (the landing/notes). A stranger should believe a different studio made it.

Reduced motion is a real feature, not a checkbox

Under prefers-reduced-motion: reduce the ticker stops scrolling and becomes a static newest-first list, the data flashes are suppressed (values update instantly), and the LIVE pulse stops animating. The data is always readable immediately; motion is only ever an enhancement.

The receipt page

paid.html is where a customer lands after paying. It polls the order until the webhook confirms payment, then shows a receipt with a green seal. A clean detail: a 404 (order genuinely not found) stops immediately with a clear error rather than retrying — so a bad reference doesn't spam the console with eight failed requests, and the user gets an honest answer fast.

The testing bar

Per the box's house rule, the dashboard ships with a Playwright e2e pass (inventory/e2e.mjs) that drives the live HTTPS URL in a real headless browser and asserts every feature: catalogue + stock pills, search (match + empty state), restock, the full order.created → order.paid live pipeline (driven by posting a signed webhook), the LOW/OUT pills, the receipt page (paid / unknown / missing ref), plus desktop and a 390px mobile viewport and reduced-motion — with a zero-tolerance bar for console / page / request errors. The suite proves the SSE pipeline truly updates the board, not just that the page loads. Result at build time: 26/26 green.