Skip to content

Add a hosted read-only demo - #2

Merged
Bruce1508 merged 13 commits into
mainfrom
hosted-demo
Sep 21, 2026
Merged

Bruce1508 merged 13 commits into
mainfrom
hosted-demo

Conversation

@Bruce1508

Copy link
Copy Markdown
Owner

Summary

  • Static, read-only demo of RootLens: real captured investigation runs served through a Next.js static export — $0 hosting, zero ongoing maintenance (no server, no database, no API keys in the deployed site)
  • All frontend requests still funnel through the existing fetchJson/api-client.ts seam; in demo mode it resolves from apps/web/public/demo/ fixtures instead of the network — the demo renders through the exact same components the live app uses
  • 3 real investigations + 1 real evaluation run captured via scripts/capture_demo.py against a live local stack (Postgres + Ollama), not hand-authored
  • The two dynamic routes (/investigations/[id], /evaluations/[id]) split into a thin server component (for generateStaticParams) plus the existing client view, since output: "export" requires static params that a "use client" page can't export
  • Visible "read-only demo" banner naming the capture date and why (the investigation loop needs a local LLM); investigate button and date pickers disabled in demo mode
  • CI now builds and e2e-tests the demo export on every push (needs no LLM/backend — the fixtures are committed)

See docs/superpowers/specs/2026-09-11-hosted-demo-design.md for the design and docs/superpowers/plans/2026-09-11-hosted-demo.md for the implementation plan.

Test plan

  • Frontend unit tests: 28/28 passing (npm run test)
  • Typecheck clean (npm run typecheck)
  • Existing e2e specs unaffected (npm run test:e2e)
  • E2e spec against the real built static export (npm run build:demo && npm run test:e2e:demo) — the test that catches demo-vs-real drift, now wired into CI
  • Normal (non-demo) build byte-for-byte unaffected — confirmed no output: "export", no demo-mode branch taken when the flag is unset
  • Six task-scoped reviews plus one final whole-branch review, each with fix rounds where findings surfaced

Not included

Deploying to Vercel and linking the demo from the portfolio site is a manual follow-up (new hosting account, separate repo) — not part of this PR.

🤖 Generated with Claude Code

Bruce1508 and others added 13 commits September 11, 2026 18:55
RootLens can't be deployed as-is: the investigation loop needs a local
Ollama model and no free tier hosts one. This records the approach we
settled on -- run investigations locally, capture every API response the
UI touches, and resolve from those fixtures in the built site.

Two findings worth keeping: repointing the API base URL at static files
does not work (GETs carry query params, two endpoints are POSTs), and
the static export forces a split of the two dynamic routes because a
"use client" page cannot export generateStaticParams.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FwJbsXDAjQAERfSQbYkgMc
Seven engineering tasks plus one manual deploy step, sequenced per the
spec's build order: resolver -> fetchJson branch -> capture script ->
route split -> demo affordances -> e2e -> deploy. Every code block is
concrete (real file paths, real component names pulled from the actual
source, real Playwright selectors verified against evidence-drawer.tsx)
so a fresh executor needs no guesswork.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FwJbsXDAjQAERfSQbYkgMc
…e demo path

The demo-mode test asserted only the fixture value, which the mock's
fallback branch would also return under the old (pre-demo-mode) fetchJson
path. Assert the mock's first call was to /demo/manifest.json so a
regression that drops the demo-mode branch fails the test.
Runs the bounded investigation loop against a live local stack (Postgres
+ qwen3:8b via Ollama) and captures every API response the demo frontend
touches: the homepage metrics summary, 3 completed product_revenue
investigations with distinct periods/questions, their event streams and
evidence, the investigations list, and the (empty) evaluations list.

scripts/capture_demo.py's INVESTIGATIONS list uses product_revenue for
all 3 entries -- it's the only metric app/analytics/segment_metric.py
implements segmentation for today, so it's the only metric that can
reach a completed report; "orders" isn't in the metric catalog at all
(422 on creation) and "cancellation_rate" creates fine but always dies
at the segmentation step.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Runs Playwright against the real npm run build:demo static output
(served via serve@latest), exercising the same InvestigationView and
EvidenceDrawer components the live app uses: banner text, disabled
controls, a completed investigation, and a working evidence citation.

The brief's literal `/^E1/` locator was ambiguous against real captured
data — the finding's inline citation and the sidebar Evidence Ledger's
exhibit entry both render "E1" and call the same openEvidence() handler
for the same evidence id. Scoped to .first() (the inline citation, first
in DOM order); this doesn't weaken the assertion since both elements
open the identical evidence drawer.
Gate the evaluation-case investigation link on demo mode, fold the
investigations-list filter and held_out eval-run selection into
capture_demo.py, read the API base URL from an env var instead of a
hardcoded workaround port, add CI coverage for the static demo build,
align page.tsx's demo-flag check with the rest of the codebase, and
pin the demo Playwright server's serve version.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Sep 18, 2026

Copy link
Copy Markdown

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Advanced

Run ID: 01aa6541-f6d8-465f-8144-434a8dc466e8


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@Bruce1508
Bruce1508 merged commit b2a902d into main Sep 21, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant