gotextlog

gotextlog
git clone https://git.ryansepassi.com/git/gotextlog.git
Log | Files | Refs

commit dc15f71d5b581d239ad02d3a8087f617e9f8a80d
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Tue, 25 Aug 2026 21:10:03 -0700

Plan Charmbracelet TUI implementation

Diffstat:
Adoc/plan/charmbracelet-tui.md | 78++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 78 insertions(+), 0 deletions(-)

diff --git a/doc/plan/charmbracelet-tui.md b/doc/plan/charmbracelet-tui.md @@ -0,0 +1,78 @@ +# Charmbracelet TUI implementation plan + +## Architecture + +The Go module is `github.com/ryan/gotextlog`. The executable is `cmd/textlog`. + +`internal/textlog` owns API v1.1 wire types and HTTP/SSE behavior. It exports a +`Client` with methods for public/authenticated feeds, search, posts and replies, +profiles and relationship collections, tags, authentication, account mutation, +post mutation, moderation, and a reconnectable-consumer-friendly `Firehose`. +Methods take `context.Context`; collection methods take `limit int` and +`cursor string`. The TUI defines its own narrow service interface from these +methods so model tests can use a fake. + +`internal/config` owns URL normalization, environment precedence, platform +config paths, and atomic owner-only persistence. It exposes `Load(env)`, +`Save(config, env)`, and `NormalizeBaseURL`. + +`internal/domain` owns note validation, relative timestamps, terminal-safe +text, rich-text tokenization, ASCII-art detection, and reply-thread ordering. +It consumes `internal/textlog` wire types and has no terminal framework state. + +`internal/tui` owns the Bubble Tea model, commands, navigation stack, async +message handling, list/editor/menu state, rendering, key bindings, theme, and +browser launch. API and persistence calls are commands. The root model remains +the owner of navigation, current-user/session state, and global status. + +## W1: API client + +Files: `internal/textlog/types.go`, `internal/textlog/client.go`, and their +`*_test.go` files. + +Deliver all JSON endpoints represented by the reference implementation, bearer +headers, structured errors with Retry-After, URL encoding/query pagination, and +SSE parsing that tolerates chunk boundaries and malformed events. The coarse +test drives an `httptest.Server` through representative GET, mutation, error, +and split firehose requests. + +Verification: `go test ./internal/textlog` and `go test -race ./internal/textlog`. + +Dependency: none. + +## W2: configuration and domain behavior + +Files: `internal/config/config.go`, `internal/config/config_test.go`, +`internal/domain/domain.go`, and `internal/domain/domain_test.go`. + +Deliver environment-aware configuration with atomic mode-0600 persistence and +the complete pure helper behavior from the reference, including Unicode note +limits, link/reference tokenization, terminal whitespace safety, and cycle-safe +reply ordering. Domain types import `internal/textlog`. + +Verification: `go test ./internal/config ./internal/domain`. + +Dependency: W1 types (both workstreams may proceed concurrently because their +files are disjoint). + +## W3: Bubble Tea application and executable + +Files: `internal/tui/*.go`, `cmd/textlog/main.go`, root acceptance tests, +`go.mod`, and `go.sum`. + +Start with a coarse Bubble Tea model test covering initial feed load, keyboard +navigation into a note, reply composition and preview, successful publication, +and back navigation. Implement responsive feed/search/thread/profile/tag/live, +compose/login/account/settings/help screens; guest and authenticated tabs; +cursor pagination; rich note rendering and target navigation; mutations and +moderation; SSE pause/retry; CLI flags and TTY checks. Use Bubble Tea, Bubbles, +and Lip Gloss from Charmbracelet. + +Verification: `go test ./...`, `go test -race ./...`, and `go build ./cmd/textlog`. + +Dependency: W1 and W2. Integration is done in this workstream. + +## Documentation and completion + +Add `README.md` with build, controls, configuration, and API coverage. Remove +this plan after all tests and build pass; retain durable behavior in the README.