Behind the Build

How I Built Bitcoin Price Board

Steve Vogt · May 2026 · 7 min read

I check the price of Bitcoin more often than is probably reasonable. For years I bounced between three or four sites, none of which did exactly what I wanted. CoinGecko has too much going on. The Coinbase consumer app is fine but slow to update and full of upsells. TradingView is excellent but heavy. I just wanted a tab I could leave open with a live price, a clean chart, and a way to know if BTC crossed a number without having to stare at it. So I built one.

The Goal

One page. Live BTC/USD price ticking in real time. A chart that can go from a 5-minute view to all-time. A small set of indicators that I actually use, not all 60. Price alerts I can set without an account. A theme dark enough for OLED and a theme light enough to read at noon. No accounts, no tracking, no ads. Installable as an app on my phone if I want.

That was the spec. The interesting decisions came in figuring out which corners to cut and which corners not to.

The Data Source

I knew from the start I wanted real ticks, not polled snapshots. The difference matters. A site that polls a REST endpoint every five seconds shows you a number that is up to five seconds old. A WebSocket feed pushes you every trade as it happens, which feels alive in a way that polled data never does.

Coinbase Exchange exposes a public WebSocket feed at wss://ws-feed.exchange.coinbase.com. No API key, no rate ceiling that an individual user is going to bump into, and Coinbase is one of the more reputable sources for BTC/USD pricing in the U.S. I subscribe to the ticker channel for BTC-USD on page load, and from then on every trade triggers a state update. Historical candles for the chart and the all-time high come from the public Coinbase Exchange REST API.

If the WebSocket drops, the page reconnects automatically with exponential backoff. While reconnecting, the last known price stays on screen with a subtle indicator that the feed is paused. The worst version of a real-time tracker is one that goes silent when the connection hiccups.

The Chart

I tried building the chart from scratch first. SVG works fine for static charts (see The Gas Map) but it gets clumsy fast when you need crosshairs, zoom, and a candlestick mode. So I went with TradingView's lightweight-charts library. It is the only charting library I have used that is genuinely both lightweight and professional-quality. About 50 KB gzipped, no React, no jQuery, just give it a div and some data.

The four chart styles (area, line, candlestick, OHLC bars) are all native to lightweight-charts. The twelve timeframes (5m, 15m, 30m, 1h, 4h, 1D, 1W, 1M, 3M, 6M, 1Y, all-time) each map to a Coinbase candle granularity, with some client-side aggregation for the longer ones. The trickier part was the indicators, which I implemented from scratch: SMA, EMA, VWAP, Bollinger Bands, RSI, and Volume bars. I wanted to know exactly what every line was doing, and I wanted them to recompute correctly when the user swaps timeframes mid-session.

The Momentum Gauge

This is the part I actually use most. The gauge is a half-circle dial that points somewhere between bearish and bullish based on a blend of three things: recent percent moves over 5, 15, 30, and 60 minutes; the ratio of green-to-red 1-minute candles in the last hour; and where the current price sits in the recent intraday range. It updates with the live tick.

It is a heuristic, not a prediction. I am very explicit about that on the page. I built it because, as a human looking at a price ticking up and down, I find it useful to have a single number that summarizes "is this calm, climbing, rolling over, or slamming." The gauge gives me that without me having to interpret three different chart panels at once. But the gauge cannot tell you what BTC will do next, and I would not trust any tool that claims it can.

Price Alerts

The alerts feature is dead simple from the user's side. Type a number, press Add. The site figures out automatically whether your target is above or below the current price and stores the alert in localStorage. When the live price crosses the target, the page fires a browser notification and plays a short audio chime, then removes the alert. The notification works even when the tab is in the background, because that is the whole point.

Two small touches that took longer than they should have. First, the audio chime. Browsers will not play audio without user interaction, so I had to gate the first sound behind a click. Second, the favicon. Most price sites do not update the browser tab title when the price changes, but for a tab you leave open all day, that is the most useful thing the site can do. The tab now shows the live price and a tiny arrow up or down, and the favicon repaints to a small green or red dot. You can tell what is happening without bringing the tab to the front.

Three Themes

Light, dark, and OLED-darker. The light theme is for daytime use on a regular monitor. The dark theme is the default and uses the same warm gray palette I use across the rest of my projects. The OLED theme is pure black, which sounds gimmicky but is actually meaningful: on phones with OLED screens, true black pixels are turned off, which saves power and looks gorgeous. If you leave a price tracker open all day on your phone, OLED black actually matters.

The whole theme system is one set of CSS variables per mode, swapped on a single data-theme attribute on the root element. No build step, no CSS framework. I want to be able to open this file in five years and still know what is happening.

Drag-and-Drop Layout

The dashboard is broken into cards: price, chart, momentum gauge, market stats, order book stats, and alerts. People care about different things in different orders, so I made the cards reorderable. The library is SortableJS, which is a tiny dependency that handles all the touch and pointer edge cases I did not want to write myself. The order saves to localStorage, so your layout is your layout from one visit to the next.

Privacy

No accounts, no analytics scripts, no tracking pixels. The only network requests the page makes are to Coinbase (for the WebSocket and historical candles) and to Google Fonts. Theme, layout, alert list, and sound preference are all in localStorage on your machine. Close the tab and the only thing that persists is what is on your own device.

What is Next

The next thing I want to add is a small news headline strip pulled from a couple of public RSS feeds, but only as an opt-in toggle. People who want price-only get price-only. People who want context can flip it on. After that, possibly an ETH-USD second view, although I am still on the fence about whether that adds value or just dilutes the focus.

If you keep an eye on more than just crypto, the rest of my projects might be useful too. BridgeToFI models early retirement spend-down strategy, Churning Hub tracks credit card sign-up bonuses, and The Gas Map shows daily U.S. gas prices by state. The full list is on the homepage.

Try Bitcoin Price Board
Free. No signup. Live BTC/USD with charts and alerts.
Visit Bitcoin Price Board
More Projects
Finance
BridgeToFI
FIRE planning calculator
Rewards
Churning Hub
Credit card bonus tracker
Travel
Delta Price Tracker
Free flight price drop alerts
Shopping
Amazon Price Tracker
Post-purchase price monitoring
Education
Spanish Spelling Test
Spelling practice with auto-grading
Reference
The Gas Map
U.S. gas prices by state
Education
Learn Clock Time
Interactive clock for kids