Epic SS-10939 · Phase 1 · INFI Connect

INFI DISPLAY
UI, as it actually renders

Every frame below is a screenshot of running software, not a drawing. The phone frames are the shipped INFI Connect app, built from the repo and driven against the live demo merchant. The television frames are the display apps themselves, captured from their production URLs. Where a screen could not be captured, the section says so rather than showing a mock-up in its place.

SS-10939 · Epic19 real captures9 storiesCaptured 2026-10-02

Foundations

bgBase#0A0F20
bgCard#101528
bgSurface#0D1226
bgElevated#192040
borderSubtle#1A2240
blueBright#4547E8
blue#2A2BC0
textInteractive#7B8FFF
textSecondary#B0BAD4
textMuted#7A8BAD
available#00C896
soldOut#FF3B5C
amber#FFB020
cyan#00D4FF
purple#7C3AED
hidden#4A5578

Two palettes, not one

The swatches above are InfiColors — the dark chrome of INFI Connect, and the only palette the operator-facing screens use.

The televisions do not share it. The menu board’s own pairing screen is light, and a running board is painted by the display theme engine: six presets plus explicit Background, Accent and Text colours and a chosen font, set per merchant. A board is supposed to look like the restaurant, not like INFI.

Reading the app’s palette onto a board, as the first draft of this page did, got that backwards.

What was captured, and how

  • INFI Connect — the Flutter app built from this repo, served locally and driven headlessly, signed in as the demo merchant. Real locations, real menus, real screens.
  • Menu board — live at infi-display.pages.dev: the pairing screen, and the template previews that render a board without a login.
  • Order status screen — live at customer-display-app.pages.dev.

Phone frames are 390×844 at 3×; television frames are 1920×1080.

What the captures corrected

  • The board is light, not dark. Three drawn frames had it wrong.
  • The operator does pick a text colour, in the Theme tab. The claim that contrast is derived was backwards.
  • Only the order-status screen counts its pairing code down. The menu board does not.
  • The $15 disclosure and a full billing screen already ship; the billing story was behind the product, not ahead of it.
  • Template and theme are separate tabs, and a theme is shared across templates.

Still missing

  • A board rendering a real merchant’s menu, a sold-out item greyed, and the offline state — all need a paired screen.
  • The order-status board with orders on it.
  • Everything in [S10]: the supported-device list has no surface yet, and the first-run chooser lives in the Flutter TV shell.

These sections carry a note instead of a picture. None of them has been filled with a drawing.

SS-10940

S1  Screen Pairing & Setup

Two surfaces talking to each other: the TV states a code, INFI Connect claims it. Nothing is typed on the television and no remote is needed past turning it on.

Menu board · unpaired
Real captureMenu board · unpairedThe live screen at infi-display.pages.dev. Note it is light, not the dark INFI Connect palette — the board and the app do not share a theme. The code is real and lives five minutes; there is no countdown here, unlike the order-status screen.
INFI Connect · pair
Real captureINFI Connect · pairThe real pair screen. The scanner error is an artifact of running in a headless browser; on a phone the camera opens here. Worth noticing: the $15 disclosure at the bottom already exists in the shipped app.
Where pairing starts
Real captureWhere pairing startsAn unpaired display offers a single row, “Tap to pair screen”. The strip above counts screens and names the next charge date.
SS-10941

S2  One Screen Per Display

A subtraction, and these are shots of it having happened. The screen-count picker, the per-screen category tabs, the screen-number slots and the n-of-m counts are gone from the shipped build.

New Display
Real captureNew DisplayNo “Number of Screens” picker and no Screen 1/2/3 tabs. One name, one list of categories, taken live from the Coffee location’s real menu.
The list card
Real captureThe list card“1/1 screens” became Not paired, and the slot number became a screen glyph. A ratio nobody read is now a state.
Menu tab
Real captureMenu tabNo screen selector above the categories. Categories are chosen once for the display, and each row names the menu it came from.
ReversibleEvery control is behind one flag in the app, not deleted. Turning it on restores the picker, the tabs and the badges in place.
SS-10942

S3  Template Library & Brand Styling

A template decides the layout; a theme decides the colour and type. They are two separate tabs in the app, and the theme is shared across templates rather than owned by one.

Template tab
Real captureTemplate tabThe current template renders its own live preview — this is the board, not a stock image. Everything else is two rows: change it, or edit its settings.
Theme tab
Real captureTheme tabSix presets, then explicit Background / Accent / Text colours and a font. The operator does pick a text colour here, which is the opposite of what the first draft of this story assumed.
Hero template
Real captureHero templateA real render. One feature item with its photograph, then category columns and a modifier bar.
Chalkboard template
Real captureChalkboard templateSame data, different template. The theme engine’s accent drives the category rules in both.
SS-10943

S4  Display Menu Page & Live Sync

One page decides what the board shows. Everything on it is a curation choice — which categories, how much modifier detail, how verbose the sizes — and none of it reaches the screen until the operator pushes. Prices and sold-out status are the opposite: they arrive on their own, and nobody opens this page for them.

The Menu page, top to bottom
Real captureThe Menu page, top to bottomAssigned categories with a count, each row carrying its item count and the menu it came from — one display can draw from several. Then Modifier column: Auto mode picks the modifiers common to those categories, and Min. prevalence decides how common counts — 5% to 100%, starting at 40%. Switch Auto off and the operator picks from only what those categories actually offer. Then Size Abbreviate, on by default, which turns Small / Medium / Large into S / M / L. Finally Save & Push to Displays: nothing above it is live until that is pressed.
Where the modifier column lands
Real captureWhere the modifier column landsThe right-hand MILK OPTIONS column is the modifier column this page configures. In Auto mode at 40% it is showing the milk choices because they sit on most of the coffee items; at 100% only modifiers on every item would survive.
Where the categories land
Real captureWhere the categories landThe assigned categories become the board’s columns, in the order the Menu page sets. Prices, photographs and tags are read from the item record — the Menu page chooses what appears, never what it says.
Two mechanisms, deliberately differentCuration is explicit and pushed: assignments, modifier mode and display options travel together when the operator saves, and the screen reloads. Freshness is automatic: a worker re-reads the menu every couple of minutes, hashes it, and pushes only when the hash moved. An 86 during service must never wait on somebody opening this page.
Min. prevalence is the one real decisionToo low and the board carries a modifier that applies to three items; too high and it carries none. 40% is the shipped default, and it is the setting most worth watching in a pilot.
SS-10946

S7  Customer Display — Order Status Screen

The only surface in the product whose user is the guest. It answers one question from across a room and shows nothing else.

Order status · unpaired
Real captureOrder status · unpairedThe live screen at customer-display-app.pages.dev. Unlike the menu board it does count down — “Expires in 04:50” — and it spells out the route through the app: Connect App → Display Boards → Pair Screen.
Not capturedThe board with orders on it is not here. It needs a paired screen with live orders, and we decided not to pair one for a screenshot.
SS-10947

S8  Remote Screen Management & Health

The operator is not in the store and the screen cannot tell them anything, so the list is the product: every display, whether it is connected, and when it was last heard from.

Health at a glance
Real captureHealth at a glanceOnline against total screens, the billing line, then one card per display. State and last-seen live on the row.
Display detail
Real captureDisplay detailA real offline screen: “Last ping 22d ago”, the device id, and the two actions this story claims — Flash to identify the physical TV, and Unpair. No “SCR 1” badge any more.
SS-10948

S9  Offline Resilience

The failure to prevent is a blank TV above a queue. What the app shows about an offline screen is real; what the board shows while offline is still to be built.

Offline, as the operator sees it
Real captureOffline, as the operator sees itThe screen reports Offline with its last ping, and the preview area says so rather than going blank. This half exists today.
Not capturedThe board’s own offline behaviour is not pictured, and the capture work turned up why: the TV app stores no menu locally, so “keeps showing the last menu” is net-new engineering rather than something to photograph.
SS-10949

S10  Supported Devices & TV App Distribution

Merchants buy their own hardware, so the deliverable is a list of model names with a verdict beside each, and an install flow short enough to finish on a remote control.

Not capturedNothing here is real yet. The supported-device list has no surface in the product, and the first-run chooser lives in the Flutter TV shell, which cannot be captured from a browser the way the two web displays can. These need either a device on a desk or a build of the TV app.
SS-10950

S11  Per-Screen Billing & Entitlement

Nobody should meet the price of a screen on an invoice. Both halves of this already exist in the shipped app, and they are further along than the story assumed.

Before the commitment
Real captureBefore the commitment“$15 / month per screen — Covered by your current plan, no change to your bill.” The disclosure sits on the pair screen itself, under the camera, where the decision is made.
Billing
Real captureBillingOpen balance, the monthly figure, the next charge date, and one subscription per location — including a cancelled one that states plainly that it no longer covers any screens.