Stage 1 · Code
Building a Terminal Dashboard with Bubble Tea
Wiring the Bubble Tea Model
Take the Model/Update/View pattern from theory to a running dashboard: a struct that holds state, a function that reacts to keys and time, and a function that renders it all with the styles from the last lesson.
The Model Struct
Everything burnrate's dashboard knows at any moment lives in one struct. Not global variables, not package-level mutable state — one value that gets passed into Update and out again, updated, on every single event.
Init and a Ticking Clock
Init runs exactly once, before the very first draw, and its job is to return whatever command should kick things off. For a live dashboard, that command is "start ticking once a second." For a static snapshot, there is nothing to kick off — it draws once and waits for the user to quit.
Update: Reacting to Events
Every event Bubble Tea's runtime knows about — a key press, a terminal resize, or your own tickMsg — arrives at Update as a tea.Msg. A type switch decides what kind of message it is and what should happen next.
Model methods use a value receiver, and Update returns a (possibly modified) copy rather than mutating through a pointer. This mirrors the immutable-update style Elm popularized: every step of the program is an explicit, traceable "old state in, new state out" transformation, with no hidden mutation to chase down when something behaves unexpectedly.
View: Rendering the Frame
View takes no arguments beyond the model itself and returns one plain string — the entire screen, re-rendered from scratch on every draw. Bubble Tea's runtime is responsible for turning that string into an efficient terminal redraw; your only job is to describe what the screen should currently look like.
Wiring It Into main.go
With a Model that implements Init, Update, and View, starting the whole program is two lines: build a tea.Program from your model, and call .Run().
At this point go run ./cmd/burnrate demo already produces a live, ticking dashboard with real burn-rate math behind it. The next lesson adds the two ways burnrate gets its numbers — a simulated demo feed and a real JSON snapshot — and wraps up with the README and credit that go with a finished, shared tool.
Mark this lesson complete to store local progress and unlock a cleaner resume path the next time you visit.