feat(tui): interactive reader — palette + fetch + bordered frame#10
Merged
Conversation
Captures exploration, proposal, spec, design, tasks, and verify report for the reader screen change. Verify verdict: PASS WITH WARNINGS (0 critical / 1 warning / 1 suggestion). 127/127 tests green.
OpenTUI's <text> only accepts strings, TextNodeRenderable, or StyledText children. <input> is its own Renderable, so nesting it inside <text> crashed the reconciler on the awaiting-state initial render: TextNodeRenderable only accepts strings, TextNodeRenderable instances, or StyledText instances Fix: render <input> as a sibling of the surrounding <text> borders instead of a child. Also drop the ANSI-escape fg attribute on the parse-error line (color attrs want hex, not escape strings) and rely on the ⚠ glyph for the error signal. 127/127 tests still pass; manual smoke now needed to confirm rendering.
App owns a phase state — boots in 'welcome', any non-q keypress transitions to 'reader'. Q/q quits from either phase. Keeps the brand splash as the entry impression while making the reader the working default. Welcome source files were already retained as Rule 13 canonical example; this re-mounts them in front of the reader.
…n welcome Replaces the hand-drawn ASCII box (┌─...─┐, side │ pillars, ├──┤ divider) with OpenTUI's native <box border> primitive. Reference goes in the top title slot, keybinds in the bottom title slot, body content fills the interior. The frame now renders as a proper rectangle at full terminal width regardless of verse length — no more bobbing right border. Also updates the welcome screen's hint line to list the actual reader commands the user will land in (any key to start • / palette • ] next ch • [ prev ch • q quit), replacing the aspirational "? help" that pointed to a help screen we haven't built. Sweeps the file-banner and code-paraphrase comments from welcome-screen.tsx per Rule 14 as part of the touch.
SDD cycle closed. PASS WITH WARNINGS verify + 3 user-sanctioned post-verify fixes (crash, welcome phase, native border). 127/127 tests pass. Manual PTY smoke confirmed by user. Out-of-scope follow-ups (paging, verse cursor, keybind rebinding, palette key-conflict gate) tracked for the next SDD change tui-reader-paging.
This was referenced May 12, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
First interactive consumer of the hexagonal architecture's TUI seam.
useEffect + cancelled-flagcallsgetPassage(repo, ref), chapter renders inside an OpenTUI-native bordered frame (<box border title=... bottomTitle=...>).awaiting/loading/loaded/network-error.parseReferencenow accepts chapter-only refs (john 3) in addition to verse refs.verbumno-args boots to the welcome screen; any non-qkey transitions into the reader. Welcome's hint line was also updated to list the actual commands (any key to start • / palette • ] next ch • [ prev ch • q quit).tuiDriver(repo)signature change;createHelloAoBibleRepository()instantiated insrc/index.tsx(mirrorssrc/cli/run.ts).What does NOT change
(state, action) => Statereducer,useEffect + cancelled-flagfor async, no Effect descriptor pattern.Verify
Original SDD verify: PASS WITH WARNINGS (0 critical / 1 warning / 1 suggestion) — 22 REQs and 14 SCNs covered. Three follow-on commits after manual PTY smoke caught a crash and addressed UX feedback:
cd9945dCrash fix:<input>cannot nest inside<text>in OpenTUI. Saved as engram observation #276 for future reference.9b77009Restore welcome screen as brand splash; transition to reader on first key.5c22012Native bordered frame (replaces hand-drawn ASCII pillars); welcome hint shows real commands.bun test: 127/127 pass.bun run tsc --noEmit: exits 0.Test plan
bun test— 127/127 pass[/]), palette reopen (/),q/Qquit from either welcome or reader.Out of scope (next PR:
tui-reader-paging)[/]reassigned to page nav).↑/↓arrow keys (▶marker on focused verse, matchesui-sketches.mdline 122).n/pto free[/]for paging.state.kind !== "awaiting"so/doesn't clear the query while typing.Full SDD trail in
openspec/changes/archive/tui-reader-screen/.