Skip to main content

oat-latte

oat-latte is a component-based TUI (terminal UI) framework for Go. It gives you a declarative component model, a two-pass layout engine, and a full widget library — all rendered through tcell.

Three things to know

Every oat-latte application is built from exactly three kinds of thing:

What it does
CanvasOwns the terminal screen and runs the event loop. You create one Canvas per application and call Run().
LayoutsContainers that position their children — VBox, HBox, Border, Grid, and more. You nest them to build any UI structure.
WidgetsThe interactive and display elements — Text, Button, EditText, List, CheckBox, ProgressBar, and more. Widgets live inside layouts.

That's the whole model. A minimal app looks like this:

body := layout.NewBorder(
layout.NewVBox(
widget.NewText("Hello!"),
widget.NewButton("Quit", func() { app.Quit() }),
),
).WithTitle("My App")

app := oat.NewCanvas(
oat.WithTheme(latte.ThemeDark),
oat.WithBody(body),
)
app.Run()

You pick widgets, arrange them in layouts, hand the root layout to a Canvas, and call Run(). Everything else — focus, key handling, theming, redraws — is handled for you.

Why it exists

After spending time with Bubble Tea and genuinely enjoying it, I found myself wondering whether there was space for a different mental model — one that felt more familiar to developers coming from GUI frameworks.

My background includes a good stretch of Flutter development, and Flutter's approach to UI always clicked with me: a component tree, a constraint-based layout pass, widgets that know how to measure and paint themselves, and a clear separation between the "what does it want to be?" and "where does it actually live?" phases. When I sat down to build terminal tools in Go, that model felt like the natural fit. oat-latte is the result of trying to bring that ideology to the terminal.

How it compares to Bubble Tea

Bubble Tea is a wonderful framework and the right choice for many programs. It is worth understanding the difference in philosophy before choosing one over the other.

Bubble Tea's model

Bubble Tea is built on the Elm architecture: your entire application is a single Model, events arrive as Msg values, an Update function returns the next model, and a View function renders it as a string. The framework is intentional about keeping you close to the metal — you compose views by concatenating strings and ANSI sequences, which gives you complete control over every character on screen.

This is a powerful model. It is explicit, pure, and very testable. If you want to deeply understand what your TUI is doing at every step, or if you need fine-grained control over rendering, Bubble Tea is likely the better tool.

oat-latte's model

oat-latte takes a different approach. The UI is a tree of components. Layout containers own their children, pass constraints down, and allocate regions. Widgets are self-contained: they own their state, handle their own key events, and paint themselves. You wire them together with callbacks rather than routing messages through a central update function.

This makes it straightforward to build structured UIs — forms, dashboards, list-detail views — without writing layout arithmetic by hand. The trade-off is that you are further from the raw terminal than you would be with Bubble Tea.

When to use which

oat-latteBubble Tea
Mental modelComponent tree (Flutter-like)Elm architecture
LayoutAutomaticManual string composition
State managementPer-widget, callback-drivenCentral model + Update
Best forStructured UIs, forms, dashboardsAny TUI; especially custom or artistic layouts
Control over renderingHigh-levelLow-level

If you want to go deep into how terminal UIs work at the core — raw sequences, full control over the render loop, and a functional reactive style — Bubble Tea is still the better approach. oat-latte is for when you want to skip the layout plumbing and think in components.

Next step

Install oat-latte →