Stage 1 · Code
Building a Terminal Dashboard with Bubble Tea
Why Bubble Tea
Everything you have built so far prints once and exits. This module builds a terminal program that stays open, redraws itself, and reacts to keys and time — using Bubble Tea, a framework built by Charm.
The Gap Between a CLI and a Dashboard
tasker, the capstone you shipped in the last module, follows a simple shape: parse arguments, do one thing, print the result, exit. That shape covers an enormous number of real tools. But it does not cover everything. Some programs need to stay open — redrawing a live view every second, reacting to key presses, showing a gauge that fills and empties as time passes. A deploy-progress screen. A log tailer with filters. A dashboard that watches a number and tells you when it's in trouble.
Building that kind of program by hand — clearing the screen, repositioning the cursor, tracking what changed since the last draw — gets unpleasant fast. That is the exact gap a terminal UI (TUI) framework closes. In Go, the framework almost everyone reaches for is Bubble Tea, built by a company called Charm.
By the end of this module you will have built burnrate, a small, real terminal dashboard for a genuinely useful production concept — multi-window SLO burn-rate alerting. It has a self-contained demo mode, a real JSON-snapshot replay mode, and a pure, independently-tested math package underneath the UI. This is not a toy exercise; it is a shippable tool, built the same disciplined way tasker was.
The Elm Architecture: Model, Update, View
Bubble Tea is built around a pattern borrowed from the Elm programming language, and it is worth understanding before you write a line of code, because every Bubble Tea program you will ever read is organized around exactly three ideas:
- Model — one Go value that holds everything the program currently knows: what data it has, what the user has typed, whether it's paused, how wide the terminal is. There is no hidden state anywhere else.
- Update — a function that takes the current Model plus one incoming event (a key press, a timer tick, a resize) and returns a new Model, plus optionally a command to run next.
- View — a function that takes the current Model and renders it to a plain string. It never mutates anything; it only describes what the screen should look like right now.
Notice what is missing from that list: there is no manual screen-clearing code, no cursor math, and no mutable global state scattered across the program. Bubble Tea's runtime handles redraw efficiently on its own — your job is only to answer three questions, over and over: what do I know right now, how does a new event change what I know, and what should the screen show given what I know.
Meet the Project: burnrate
Just as tasker gave the CLI modules a single focused project to build all the way to shipped, burnrate is that project for this module. It renders a live terminal dashboard that watches a service's error rate through two "burn-rate windows" — a fast one that catches a sudden outage in minutes, and a slower one that catches a steady regression a fast window alone would miss — and shows how much of a 30-day error budget is left.
This is a real technique used at companies that run production services at scale, described in Google's SRE workbook chapter on alerting on SLOs. You are not building a simplified toy version of the idea — you are implementing the real math, wired into a real, interactive terminal UI.
| Layer | What it does | What you'll learn from it |
|---|---|---|
internal/slo | Pure Go: burn-rate arithmetic and a rolling error-budget tracker, with no dependency on the terminal at all. | Keeping business logic testable and UI-independent — the same lesson from tasker's internal/task package, applied again. |
internal/data | Supplies traffic samples, either simulated (demo mode) or replayed from a JSON snapshot file. | Programming to an interface (Source) so the dashboard doesn't care where its numbers come from. |
internal/tui | The Bubble Tea model and Lip Gloss styling that turn the numbers into a live, readable screen. | The Model/Update/View pattern, styling composable terminal UI, and handling a ticking clock. |
Credit Where It's Due
Bubble Tea and its companion styling library, Lip Gloss, are built by Charm (charm.sh), and are two of the most widely used, actively maintained libraries in the entire Go ecosystem for building terminal interfaces. They are open source, extremely well documented, and used in production tools by companies far larger than the one you're building here. This module exists because Charm made building a genuinely pleasant terminal UI something any Go programmer can learn in an afternoon — the finished burnrate project will say so directly, in its own help text and its own README.
Before the next lesson, run go get github.com/charmbracelet/bubbletea, go get github.com/charmbracelet/lipgloss, and go get github.com/charmbracelet/bubbles inside the project you'll scaffold in the next lesson. All three are maintained by Charm and used together throughout this module.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.