wiki-vault/Sources/Homelab/2026-05-28-trellis-dashboard-ui-iteration.md

52 lines
4.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

---
created: '2026-05-28'
path: Sources/Homelab
project: trellis-mcp
tags:
- python
- docker
- traefik
- claude-code
- automation
- dispatch
type: session-notes
---
## Outcome
Iterated the trellis-dashboard Streamlit app (read-only UI over the petalbrain trellis schema, fronted by Traefik at `threads.herbylab.dev`) from its initial layout through two passes of changes in a single Dispatch session.
First pass (commit `dc5c26d`): made the thread list selectable with a detail box moved below it, added an inner two-view layout (Threads, Projects) with the same list-on-top / detail-below pattern, and moved the fork-tree viz to the Projects detail only.
Second pass (commit `88ef1e0`): cross-tab jump from a project's threads table → Threads view with that thread preselected, selection persistence across reruns via `st.session_state`, URL deep-linking via `st.query_params` (`?view=...&thread=...` / `?project=...`), sidebar free-text search across title/slug/goal, a manual cache-refresh button, hand-rolled relative timestamps, default sort by last activity desc, and a friendly empty state.
Both passes went through ruff/pyright/pytest, zero-check 5/5, a-review (clean on the second pass), and headed-browser verification before being declared done. Container is healthy and serving the new build. Branch `claude/epic-franklin-f16a5c` is on Gitea awaiting merge to `main` (direct push to `main` is permission-railed).
## Topics Covered
- Streamlit selectable lists via `st.dataframe` with `on_select="rerun"` and `selection_mode="single-row"`
- Cross-view navigation in Streamlit — and the `st.tabs()` limitation that broke it
- `st.segmented_control` (Streamlit 1.40+) as a tab replacement when programmatic view-switching is required
- The `_pending_view` indirection pattern for mutating widget-bound `session_state` between reruns
- URL deep-linking via `st.query_params` for shareable thread/project links
- Worktree-based deploy friction when `deploy/.env` only lives in the main checkout
- a-review (Gemini) coverage extending to the Traefik / Authentik middleware config
- The gap between headless `curl` health probes and real browser walkthrough for UI work
## Key Learnings
- **Headless probes are insufficient for UI verification.** Streamlit serves HTTP 200 even when widgets are broken or empty. Headed browser walkthrough (Playwright via Claude-in-Chrome) should be the default definition-of-done for any UI change, not an opt-in second pass. The first round here shipped before a single row click was simulated.
- **Recommend → ship → recommend → ship works as a deliberate iteration cadence on proof-of-concepts.** Asking for UX suggestions immediately after the first deploy — while context was hot and the codebase still in working memory — produced eight high-value follow-ons with no re-discovery cost. Worth baking in as a step.
- **`st.tabs()` cannot be programmatically activated.** Any feature that needs to switch views from a click in another view requires `st.segmented_control` + `session_state`. Discovered mid-build when wiring the cross-tab jump.
- **`deploy/.env` lives only in the `main` checkout** (correctly gitignored) → worktree-based deploys break until the file is copied in. The repo should either commit a `.env.example` or document the copy-in step in the deploy README.
- **Plan PR-flow from the start for `main`-protected repos.** Discovering the push is denied mid-deploy adds a beat. The working pattern: feature branch → push → rebuild container from the worktree (compose project name stays the same so it manages the same container) → PR-merge separately.
- **a-review's pass over the *full* deploy/Traefik config (not just the diff) caught the Authentik exposure** that would otherwise stay hidden. Keep that audit envelope when scope touches deploy.
- **The home-dir mirror path `/home/herbyadmin/dev-projects/...` is not present for every repo.** Falling back to `/opt/projects/...` is fine but a single `check first` beats reflexive try-then-fail.
## Follow-ons
- [ ] Merge branch `claude/epic-franklin-f16a5c` into `main` so the source matches the deployed container
- [ ] Decide whether to restore Authentik forward-auth on `threads.herbylab.dev` (lines 3553 of `deploy/traefik/threads.herbylab.dev.yml` are commented out; site is currently reachable with no auth)
- [ ] Capture the two Streamlit/deploy gotchas in `trellis-dashboard/CLAUDE.md` (`st.tabs()` not programmatically activatable → use `st.segmented_control`; `deploy/.env` not in worktrees → copy in before build)
- [ ] Fix the page URL/route name — `threads.herbylab.dev` no longer fits since the UI now spans threads + projects
- [ ] Consider whether trellis-dashboard deserves its own vault `project-plan` rather than living as a session-note under `trellis-mcp` (parallel to the trellis thread 583 backfill question)