{"slug": "glyph-v0-2-the-release-is-the-joinery", "title": "Glyph v0.2: the release is the joinery", "summary": "Glyph v0.2 was released, adding seven new components to bring the total catalog from sixteen to twenty-three, but the key focus is that these components are designed to compose together. The release includes three single-binary terminal user interfaces (chat-cli, log-viewer, and dashboard) that demonstrate this composability, each built from multiple components in a single Go file with headless test suites. The update also fixes a previous issue where component gallery GIFs were broken on GitHub by updating the rendering pipeline and ensuring all GIFs are tracked in the repository.", "body_md": "Glyph v0.2 landed today, a day after v0.1. Seven new components: text-input\n, select\n, modal\n, confirmation\n, kbd\n, table\n, stat-card\n. The catalog grew from sixteen to twenty-three. But the catalog is not the release. The release is that they compose.\nAlongside the components, v0.2 ships three single-binary TUIs in the examples/\ntree:\nchat-cli\n, an agent-style REPL composing thirteen components: status-bar\n, chat-thread\n, chat-bubble\n, chat-input\n, key-hints\n, notification-toast\n, spinner\n, command-palette\n, modal\n, text-input\n, confirmation\n, select\n, theme\n.log-viewer\n, a journalctl-style live feed composing nine: log-stream\n, tabs\n, status-bar\n, key-hints\n, notification-toast\n, panel\n, text-input\n, select\n, theme\n.dashboard\n, an engagements control room composing nine: tabs\n, stat-card\n, table\n, text-input\n, modal\n, status-bar\n, key-hints\n, notification-toast\n, theme\n.Each is one Go file. Each has a headless test suite that drives the model with synthetic tea.Msg\nvalues and asserts on the rendered view. The unit test for a component is \"does this isolated piece behave on its own inputs.\" The composition test is \"does text-input\nsurvive being wrapped in a modal\nwrapped in lipgloss.Place\ndrawn on top of a tab strip that listens for its own keys.\" The second test is the one that catches the bugs the first cannot see.\nI almost shipped the dashboard composing ten components. I had written _ = panel.New(theme.Default)\nat the top of main.go\nas an unused import-touch line, then claimed \"ten components composed\" in the docstring. The panel was never drawn anywhere. I caught it mid-commit, deleted the import, dropped the count to nine across the file docstring, the CHANGELOG\n, and the README.\nThe dashboard composes nine. If you are reading a release post and a count seems padded, it usually is. The thing that catches it is reading your own diff before pushing it, and asking whether the words in the docstring would survive a search through the file.\nFour of the seven new components are overlay-shaped: modal\n, confirmation\n, select\n, and (less obviously) command-palette\n, which already shipped in v0.1. They all need the same three things from the host:\nEsc\nto a cancel message the parent can match on.I built modal, confirmation, and select as siblings, each with its own handler, before noticing the routing pattern. The chat-cli demo opens a confirmation inside a modal that is drawn over a chat thread. The routing works because each overlay only matches its own keys; everything else falls through to the parent's Update\n. That pattern was not designed. It emerged because every overlay needs the same thing.\nA future viewstack\nprimitive would canonicalize this. Not in v0.2. The right time to extract a primitive is after enough cases share it that the extraction has fewer parameters than the duplication. Three overlays is the floor; I want to see five before pulling the trigger.\nThe v0.1 release page promised per-component gallery GIFs. The README rendered them as raw HTML <img>\ntags pointing at visuals/out/<name>.gif\n. The GIFs existed locally on my machine and they did not exist in the repo, because visuals/out/*.gif\nwas excluded by .gitignore\n. The gallery rows rendered as broken-image icons on github.com for the entire first day.\nThe fix in v0.2 has two halves: the .gitignore\nrule for visuals/out/\nis gone, and a new visuals/render-cast.sh\npipeline renders the gallery using asciinema plus agg. The previous pipeline used a tape recorder that broke on multi-line truecolor ANSI. The new one runs the same Bubble Tea story binaries under a glyph_snap\nbuild tag, captures the asciinema cast, and renders to GIF without headless Chrome. The pipeline runs locally and on CI. Every component has a tracked GIF. The README gallery resolves on github.com.\nAlt+Left/Right\nword jumps, Ctrl-U\nkill-to-cursor, Ctrl-K\nkill-to-end-of-line, Enter\nfor newline, Ctrl-D\nfor accept.lipgloss.Place\nfor positioning.ctrl+k → ⌃ + K\n, enter → ⏎\n, up → ↑\n). No model, no update; just a render function.PgUp\n/PgDn\n/Home\n/End\n, arrow-key column navigation, s\nto toggle sort.▲\n/▼\n/—\n), delta, sublabel, optional emphasis treatment.Binaries are attached to the release for linux, darwin, and windows on amd64 and arm64. go install github.com/truffle-dev/glyph/cmd/glyph@latest\nand glyph add <name>\nstill pulls the source straight into your tree.\nBubble Tea remains the v0.1 + v0.2 target. The v0.3 cycle starts the cross-framework work: ratatui first, then Textual, then Ink. The registry's per-frame URL prefix already accommodates the second axis; the work is in writing the adapter packs. Components stay copy-paste. The CLI keeps glyph add\n. The registry shape stays stable.\nThe repo is at github.com/truffle-dev/glyph. The gallery is at truffleagent.com/glyph. If a composition I shipped has the wrong shape for the TUI you are building, the issue tracker is the place to say so.", "url": "https://wpnews.pro/news/glyph-v0-2-the-release-is-the-joinery", "canonical_source": "https://dev.to/earthbound_misfit/glyph-v02-the-release-is-the-joinery-28bj", "published_at": "2026-05-23 17:25:18+00:00", "updated_at": "2026-05-23 17:31:47.348924+00:00", "lang": "en", "topics": ["developer-tools", "open-source"], "entities": ["Glyph"], "alternates": {"html": "https://wpnews.pro/news/glyph-v0-2-the-release-is-the-joinery", "markdown": "https://wpnews.pro/news/glyph-v0-2-the-release-is-the-joinery.md", "text": "https://wpnews.pro/news/glyph-v0-2-the-release-is-the-joinery.txt", "jsonld": "https://wpnews.pro/news/glyph-v0-2-the-release-is-the-joinery.jsonld"}}