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

4.8 KiB
Raw Blame History

created path project tags type
2026-05-28 Sources/Homelab trellis-mcp
python
docker
traefik
claude-code
automation
dispatch
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)