Case study · 03 / Sweep
What actually happens if I act right now?
A live crypto market terminal built around the question existing terminals refuse to answer directly: what actually happens if I act right now? Point a size at the order book and it states your average fill, slippage and worst price before you commit. And when the feed dies, the terminal says so instead of impersonating a quiet market.
Point a size at the book
SWEEP · BTC-USD · KRAKEN
RECORDED FRAME · $5 BUCKETS
- AVG FILL
- 77,780.50
- SLIPPAGE · BPS
- +0.0
- LEVELS
- 1
- WORST
- 77,780.50
PAPER ONLY · LEVELS FROM THE RECORDED SESSION THE LIVE TERMINAL REPLAYS · DISPLAYED DEPTH IS OPTIMISTIC
The slice above is coded into this page. The full build is at sweep-trade.vercel.app.
- Year
- 2026
- Role
- Product Design, Front-end Build, Data Engineering
- Venue
- BTC-USD on Kraken; Binance in code as proof the engine is venue-agnostic
- Type
- Personal build; design, engine and interface
- Stack
- Next.js, TypeScript, lightweight-charts, zero other runtime deps
- Honesty
- Observation and simulation only. No keys, no auth, no real orders
- Outcome
- last trade → your fill, the number no retail terminal shows: your average price across the levels your size would actually consume
The short version
A market interface should show executable truth, and should degrade visibly when it stops being true.
- Terminals answer “what is the price?” Sweep answers the question with money on it: what actually happens if I act right now?
- Point a size at the book and it states average fill, slippage and worst price before you commit. The levels you would consume tint amber.
- A dead feed stops impersonating a quiet market: past 250ms the figures themselves fade until you cannot confidently act on them.
- The deploy replays a real recorded session through the same engine as the live socket; GO LIVE sits behind it.
- 797,210 messages in a one-hour live soak, every checksum clean, zero crossed books, zero gaps swallowed.
What was wrong
What the old experience made people do
01
The price on screen is not a price you can get
Every terminal leads with the last trade, or the top of a book you will not fully get. The number that matters to someone with size is the average fill across the levels their order would consume, and no retail terminal puts it in front of them. People guess, act, and meet the real number in their fill history.
Fixed by making the book an instrument you point a size at: consumed levels tint amber, and a readout states average fill, slippage in basis points, levels cleared and worst price touched, before you act.
02
A dead feed looks exactly like a quiet market
Terminals render a three-minute-old price identically to a live one. A dropped socket and a calm market are indistinguishable on screen, which makes staleness the most expensive lie in the category. It is a design failure, not an engineering one.
Fixed by putting staleness on the figures themselves, never in chrome: past 250ms of silence the numbers desaturate, then fade, then an explicit counter appears reading LAST MESSAGE 14.8s AGO, DO NOT ACT ON THIS. A number you can barely read is one you cannot confidently act on.
03
Activity rendering that punishes attention
Flash-on-change is the category default, and at real feed rates it is a strobe. A level changing five times in half a second flashes five times, which trains people to stop looking at exactly the thing the interface exists to show.
Fixed by replacing flash with accumulating heat: +0.18 alpha per change, a 500ms half-life, clamped at 0.35. Sustained activity reads as sustained warmth. The rejected strobe survives as the losing half of a side-by-side A/B on the deploy.
The problem
Two questions, zero answers
A person with money on the line is not asking what the price is. They are asking what happens if they act, and whether they can trust what they are looking at.
Trading terminals are dense, and the density is a costume. Under the panels and the indicators, the retail category answers one question: what was the last price somebody paid? That number is already history, and for any meaningful size it is not even a good prediction, because your order will walk through the book consuming levels, each one worse than the last.
The second question is quieter and more expensive. Every figure on a trading screen carries an implicit claim of nowness, and nothing in the category tests that claim in front of the user. The connection drops, the screen holds its last state, and the interface goes on looking confident. Sweep was built as a two-part answer: state what a size actually gets, and make trust in the screen something the screen itself has to earn.
A market interface should show executable truth, and should degrade visibly when it stops being true.
What I built
One screen, one venue, one instrument
BTC-USD on Kraken, depth over breadth. The order book stops being a passive table and becomes an instrument you point a size at.
The levels your order would consume tint amber. A readout states average fill, slippage in basis points, levels cleared and worst price touched. A cost curve draws size against average price, and the shape is the liquidity story: steep means thin, flat means deep. The FILL button records a paper position at the sweep’s computed average, exactly the figure the readout promised, and marks it against the live mid from then on. A 15 BTC paper buy showing a loss the instant it fills is not a bug; it is the slippage lesson transferred into your own position.
Under the screen sits a venue-agnostic engine kept deliberately outside React. It ingests the feed at whatever rate arrives, coalesces changes into immutable snapshots, and the interface subscribes at a fixed 10Hz, because reading a figure costs about 200ms and rendering faster than comprehension is noise, not freshness. The tape runs its own 30Hz budget: motion is tracked pre-attentively, digits are not. The cadence is enforced in architecture rather than left to discipline.
The engine is proven against two venues with different wire protocols, Kraken and Binance, and fed either by a live socket or by deterministic replay of raw recorded frames. It cannot tell which. Replay is the deploy default and GO LIVE sits behind it, which means the deployed piece will still play a real session in three years, after every venue API has changed.
The engineering
Recordings are raw wire frames, and the clock is the master
The recorder writes every raw message with its arrival time, not parsed events, so a recording outlives every parser improvement.
The same stateful session classes drive live and replay, which is what makes the claim that the engine cannot tell true rather than aspirational. A one-hour live soak of 797,210 messages passed every Kraken checksum with zero crossed books, and replays deterministically with identical numbers. The browser plays a spliced clip whose synthetic head snapshot is re-verified by the venue’s own CRC32 across the splice: 49,189 of 49,189 clean.
The first replay shipped as a setTimeout chain, one timer per message, and died the same day: browsers throttle chained timers in hidden tabs to one per second, which crawled a 150-message-per-second feed to one. The rewrite inverted control. The store owns a replay clock; every publish tick pumps the player synchronously up to it. A clock cannot be throttled, only the pump can, and a starved pump just emits a bigger batch on the next tick, with the clock walking back to the feed rather than skipping past it. In a throttled tab, replay time lags wall time, which is the honest direction to fail.
Every real fork in the build is logged in decisions.md from the day it was hit, and each entry names what the choice costs and who pays it. The setTimeout rewrite is in there as the fork it was.
Decision 01
The UI hears about the book at 10Hz, and flash became heat
Reading a figure costs about 200ms, so rendering faster than 10Hz is noise. The cost is named: a scalper watching for sub-100ms book flicker loses information here. That user is not who this is for, and would need a different mode, not a different constant.
Decision 02
Staleness lands on the figures, never in chrome
A banner is chrome and gets ignored; a number you can barely read is one you cannot confidently act on. The rule has no exceptions: when the recorded session ends, the clock keeps walking and the terminal degrades exactly as it would on a dead socket. A hole in the feed is never silently resumed. It is stated, 42s MISSING, until a human dismisses it.
Decision 03
Replay is the deploy default
On an ordinary bad network the live path fails, and the design’s job is to make that failure visible rather than rare. Raw frames cost about 6× the storage of parsed events, and the meta line of every clip says what the splice snapshot is. This is a scene to design against, not a dataset.
Decision 04
Paper fills record the number the readout promised
Entry is booked at the sweep’s computed average, and the blotter marks it against live mid from then on. A blotter that recorded a kinder price would be the interface calling its own headline number a lie. No fees, no latency model; the panel says PAPER and means it.
Decision 05
One decided layout
Every terminal ships draggable panels to avoid making a layout decision; making the decision is the work. Chart left, book and tape right, sweep and positions below. No panel invents its own rhythm: 32px headers, 24px column heads, 20px rows.
The landscape
Where the category stands
Not a feature matrix, because Sweep would lose one on purpose: it has no watchlist, no indicators and no drawing tools, and refuses them in writing. The comparison that matters is behavioural. When the same six moments happen, what does the screen do?
The moment
Retail crypto terminals
Sweep
The headline number
Retail crypto terminals ·The last trade, or top of book. A price that is already history, and one your size would not get.
Sweep ·Your average fill across the levels your size would consume, stated before you act.
The feed quietly dies
Retail crypto terminals ·The screen holds its last state and goes on looking confident. A dropped socket is indistinguishable from a calm market.
Sweep ·Figures desaturate, fade toward 40% opacity, then a counter states LAST MESSAGE 14.8s AGO, DO NOT ACT ON THIS.
A hole in the data
Retail crypto terminals ·Reconnect and resume as though nothing happened.
Sweep ·Stated in amber, 42s MISSING, until a human dismisses it.
A busy level
Retail crypto terminals ·Flashes on every change. At real feed rates, a strobe.
Sweep ·Accumulates heat with a 500ms half-life, so sustained activity reads as sustained warmth.
The layout
Retail crypto terminals ·Draggable panels, so the product never has to make a decision.
Sweep ·One decided layout. Making the decision is the work.
Paper trading
Retail crypto terminals ·Fills at the price on screen, which is kinder than reality.
Sweep ·Fills at the computed sweep average, slippage included. The readout is accountable to its own number.
The professional tier is a different conversation: Bloomberg and the exchange-native pro tools do estimate depth-weighted fills, at desk prices, for people who already know to ask. The claim here is narrower and checkable: in the terminals retail crypto actually trades on, these six moments default the other way.
The design system
The tokens every screen is built from
The system exists to serve two sentences: show executable truth, and degrade visibly when it stops being true. Green and red are spent entirely on direction, amber is reserved for the single state where a human must decide, and the highest contrast on screen belongs not to a brand mark but to the digits that are currently changing.
01
Executable truth
The book answers a size, not a level. Average fill, slippage, levels cleared, worst touched.
02
Liveness you can feel
Staleness lives in the figures, never in chrome. Silence is the good state.
03
Hue is never the only channel
Direction is carried three ways at once: fixed position, a luminance gap, and a sign glyph. Verified under deuteranopia simulation.
04
The terminal remembers
Look away for forty seconds and it tells you what you missed, once, then gets out of the way.
Sweep DS v1Nine colour tokens, a 2px spatial scale, and two typefaces with a treaty between them. Small on purpose: every token that exists is one a screen this dense has to defend.
Two tiers. The ramps are raw values that no component is allowed to reference; the tokens beneath name a role and point at one. Select a token to see which step it resolves to.
ink The greys, darkest to lightest. Canvas is never #000: saturated green halates on OLED.
canvas
surface
raised
hairline
stable
dim
text
volatile
signal The only hues on screen, and each is allowed to mean exactly one thing.
bid
ask
attention
Direction
Figures
Structure
More screens




Still open
What I would do in the next pass
Displayed depth is not executable depth
A meaningful share of resting size is cancelled before you reach it, so the sweep readout is optimistic and does not yet say so. Measuring cancellation rates near the touch and drawing a confidence band on the fill estimate is the strongest v2 idea, and the honest answer to spoofing.
Mobile is a different hierarchy, not a smaller one
The density argument assumes a desktop viewport. Shrinking this layout would be a lie; a phone terminal would lead with the readout and hide the book behind a gesture.
Live means we heard from them recently
Message arrival is measured; venue-side latency is not. Liveness overstates itself by exactly the width of the network, and the next pass should say so on screen.
The dark convention deserves a real challenge
Dark terminals come from low-light desks, and a lot of crypto is traded in daylight on a phone. v1 declined to ship a half-committed light mode, which is not the same as the question being settled.
A number you cannot trust should be a number you can barely read.