I want to build a reusable terminal UI template, but I do not want to start by assuming the stack.
That is the point of this first post. Before I commit to a language, framework, and project shape, I want to write down what I actually need from the template and compare the obvious options. If I skip this step, I will probably still build something, but I will not learn as much from the decision.
Most of my recent work has been web and cloud-heavy. Next.js is great when I need a real web UI. APIs, dashboards, auth flows, and hosted products all fit that world. But not every developer tool needs to become a browser tab. Some ideas feel more natural as a local, keyboard-first app that opens fast and gets out of the way.
Problem(Working question)
If I wanted a reusable base for terminal apps, what stack gives me the best balance of fast iteration, clean architecture, good UI primitives, and easy distribution?
What I Am Trying to Build
I am not trying to build one specific terminal app yet.
I am trying to build the base I would want before building several of them.
The template I have in mind
The rough shape:
- app shell
- screen routing
- keyboard shortcuts
- help overlay
- command palette
- theme system
- debug/log view
- release workflow
The template should feel like a project starting point, not a framework I have to study for a week.
What "good" means here
For this experiment, "good" means:
| Requirement | Why it matters |
|---|---|
| Fast startup | Terminal tools should feel immediate |
| Simple distribution | I want to hand someone a binary or a clear install command |
| UI structure | Screens, layout, focus, and keyboard handling should not be improvised every time |
| Styling primitives | A TUI still needs visual hierarchy |
| Testable state | I want to test behavior without manually inspecting a terminal |
| Low ceremony | The template should help future projects, not slow them down |
Important
The real constraint is not performance by itself. It is repeatability. I want the boring decisions handled once so future terminal apps can start with structure.
The Candidates
The four stacks I keep circling are Go, Rust, Python, and Node.
None of them are wrong. They just optimize for different things.
Go
Go is interesting because the language already feels close to the kind of tool I want to build: small command-line programs, clear packages, straightforward compilation, and practical deployment.
The official Go tutorial shows go build compiling a program into an executable, and the Go docs also recommend go install for installing commands at a specified version. That matters for this project because distribution is part of the developer experience, not an afterthought.
Relevant docs:
Strengths
- compiled binary workflow
- simple project structure
- good standard tooling
- practical for local developer tools
- enough type safety without a heavy learning curve
Concerns
- terminal UI ecosystem is smaller than web UI
- visual polish depends heavily on the library stack
- some advanced UI patterns may need custom architecture
Remark
Go feels like the boring option in the best sense. If the goal is a local tool that can be built, copied, released, and understood later, boring is a feature.
Rust
Rust is tempting for terminal apps because it is fast, safe, and has a serious CLI culture. The TUI library that comes up immediately is Ratatui, which describes itself as a Rust library for fast, lightweight, rich terminal interfaces.
Rust also has Cargo, which gives a strong build/package workflow. The official Cargo book documents cargo build, and the Rust ecosystem has plenty of examples of polished terminal tools.
Relevant docs:
Strengths
- very strong performance profile
- excellent correctness story
- mature CLI culture
- Ratatui is purpose-built for rich terminal UI
Concerns
- slower iteration for me personally
- ownership/lifetime complexity can distract from UI exploration
- template contributors may need more Rust knowledge before they can modify it comfortably
Intuition
Rust feels like a strong choice if the terminal app itself is close to systems work: file indexing, hardware, local agents, network tools, or anything where correctness and performance dominate.
For a general starter template, I need to ask whether that power is worth the extra complexity.
Python
Python has the fastest path from idea to prototype. If I wanted to explore UI behavior quickly, Python would be hard to ignore.
The big candidate is Textual, which describes itself as a Rapid Application Development framework for Python. The getting-started docs say Textual runs on Linux, macOS, Windows, and likely anywhere Python runs.
Relevant docs:
Strengths
- very fast experimentation
- Textual has a high-level app model
- good for data/API/cloud-heavy workflows
- easier scripting and prototyping
Concerns
- packaging applications is a separate topic
- runtime/environment management can become part of the user's setup
- a template may feel less "drop in and run" unless distribution is solved well
Node
Node is attractive because I already spend time in the JavaScript/TypeScript world. For web UI, Next.js is a strong default. For CLI tooling, Node has a huge ecosystem.
Node also has official support for single executable applications, but the docs show that it is a packaging process rather than the default development shape.
Relevant docs:
Strengths
- familiar language and tooling
- huge package ecosystem
- easy to connect with web/API projects
- good if the terminal tool is adjacent to an existing JS codebase
Concerns
- runtime and dependency weight
- terminal UI is not where Node feels most natural to me
- single-executable distribution exists, but it is not as direct as
go build
Comparing the Tradeoffs
Here is the rough decision table before I write much code.
| Stack | Best reason to choose it | Main risk |
|---|---|---|
| Go | Practical binaries and a clean local-tool workflow | UI layer may need careful architecture |
| Rust | Performance, correctness, serious TUI ecosystem | More complexity than I may need |
| Python | Fastest prototyping and high-level UI framework | Packaging/distribution can become the project |
| Node | Familiar web-adjacent tooling | Runtime/dependency weight for a local TUI |
The decision axis
The question is not "which language is best?"
The better question is:
- Which stack makes the template easiest to reuse?
- Which stack keeps distribution boring?
- Which stack lets me build UI structure without inventing everything?
- Which stack will I still want to maintain six months from now?
That last one matters. A starter template is not just code. It is future maintenance.
The Go TUI Ecosystem
If Go stays in the running, the obvious ecosystem to study is Charm.
Charm describes its toolset as open-source tools for building terminal software, including Bubble Tea for terminal UIs, Lip Gloss for terminal style and layout, and Bubbles as the component toolkit.
Bubble Tea
Bubble Tea uses a model-update-view style that should be familiar if you have seen Elm-like architecture.
The basic idea:
Modelholds state.Updatereceives messages and returns the next state.Viewrenders the state as terminal UI.
That sounds like a good fit for a template because it gives the app a repeatable shape. Instead of every screen becoming its own pile of callbacks, the app can route messages through known boundaries.
Lip Gloss
Lip Gloss is the styling/layout layer.
This matters more than I expected. Terminal apps can look messy quickly because there is no browser layout engine saving you. Spacing, borders, colors, width, height, and alignment have to be intentional.
If the template is going to include a header, sidebar, main panel, footer, and overlays, I need styling primitives that make those pieces consistent.
Bubbles
Bubbles is useful because I do not want to rebuild every widget from scratch.
Lists, inputs, tables, spinners, progress indicators, and viewports are all common TUI pieces. A template should make it easy to add those without turning the first app into a component-library project.
Conjecture(Working hypothesis)
If Go wins, the strongest reason will probably not be raw performance. It will be the combination of simple binaries plus Bubble Tea's app architecture plus Lip Gloss's visual primitives.
What I Still Need to Test
I do not want to decide only from documentation.
The next step should be small experiments.
Experiment 1: app shell
Can I build a header, sidebar, main region, and footer that resize cleanly?
Questions:
- How much layout code does this require?
- Does the result stay readable in smaller terminals?
- Is the shell reusable across future apps?
Experiment 2: screen routing
Can each screen own its own state while the root app controls navigation?
Questions:
- What does the
Screeninterface look like? - How do screens expose keybindings?
- How do screens receive size changes?
Experiment 3: command palette
Can commands become a central registry instead of scattered shortcuts?
Questions:
- Can the same command data power search, help, and keyboard shortcuts?
- Should commands return messages, functions, or both?
- Does this make the app easier to extend or just more abstract?
Experiment 4: themes
Can themes be semantic instead of random colors?
Questions:
- What are the minimum tokens?
- Does the app still work in multiple terminal color profiles?
- Should theme choice persist between runs?
Problem(A template-specific risk)
The danger is building too much before the first real app exists. A template should capture repeated decisions, but I only know which decisions repeat after using it more than once.
Possible Future Subposts
This post should be a parent node for later updates.
Decision update
Once I choose the initial stack, I can write a follow-up explaining what changed from this comparison and why.
Charm ecosystem notes
A subpost could go deeper on Bubble Tea, Lip Gloss, Bubbles, and the history of Charm's terminal-first design.
Rust comparison follow-up
If Rust still feels tempting after the Go prototype, a rebuttal-style post could argue for Ratatui instead.
Packaging notes
Python and Node are not bad choices. They mostly raise packaging questions. That could become a focused post on distributing local developer tools.
What's Next
The next post should not announce the final template yet.
It should run the first experiment: build the smallest useful app shell and see how the stack feels under pressure. I want to test the things that matter for this project:
- startup and run loop
- terminal resizing
- layout boundaries
- screen switching
- keyboard hints
- first pass at styling
If Go + Bubble Tea + Lip Gloss feels clean there, then the decision starts to make itself. If it feels awkward, I still have Rust, Python, and Node as real alternatives instead of imaginary ones.
Summary
I am starting this series before the template exists on purpose. The goal is to choose a TUI stack by comparing tradeoffs, then testing small experiments. Go, Rust, Python, and Node all have reasonable paths, but the template needs fast local startup, boring distribution, reusable UI structure, and a maintenance story I can live with.
