Skip to content

feat(docs): live-demo hero panel via @wavehouse/sdk - #290

Merged
EricAndrechek merged 24 commits into
mainfrom
docs-demo
Jun 8, 2026
Merged

feat(docs): live-demo hero panel via @wavehouse/sdk#290
EricAndrechek merged 24 commits into
mainfrom
docs-demo

Conversation

@EricAndrechek

@EricAndrechek EricAndrechek commented Jun 6, 2026

Copy link
Copy Markdown
Member

What

This branch rebuilds the docs landing experience around a live @wavehouse/sdk consumer and, in the process, turns the docs from "a polished landing bolted onto stock Starlight" into one coherent, branded, accessible system. Four loosely-coupled workstreams plus the fixes the review gate shook loose:

  1. Live-demo hero panel — the landing page now renders real data from stats.wavehouse.dev.
  2. Site-wide design-system pass — one radius scale, one button shape, AA-correct light theme, branded Starlight chrome, a wide-screen layout that uses the space.
  3. Mermaid diagrams — fixed the label-clipping bug, made big diagrams readable (vertical layout + click-to-zoom), and set a house style.
  4. Docs-accuracy corrections + backend/test fixes surfaced by getting make ci honestly green and 7 rounds of dual-reviewer self-review.

A focused "Where this deviates from Astro/Starlight defaults" section is near the bottom, since that's easy to lose track of.


1. Live-demo hero panel (docs/src/components/LiveDemo.astro, new)

The hero's visual column is a real SDK consumer against the public read-only role on the WaveHouse-Stats dogfood deployment (PUBLIC_WAVEHOUSE_STATS_URL-overridable):

  • Live counts — stars, forks, events-over-7d (168h), open issues/PRs, lifetime total — from one cached gh_summary pipe call. setCount() writes every [data-wh-live="<key>"] on the page, so the same fetch also feeds the hero star chip and the closer-band chip.
  • Live activity feed — backfilled from the server-curated/deduped cached gh_activity_recent pipe, then a live SSE stream() tail. The stream connects before the backfill so nothing lands in the gap; a composite-key dedup absorbs the overlap and webhook redeliveries.
  • Live "wow" metrics⚡ ingested → live in ~N ms (per-event, 30-sample median, skew-clamped → Stats#33) and an events/min sparkline (gh_events_per_minute pipe → Stats#34).
  • Three-tier graceful degradation: gh_summary → per-number pipes; gh_activity_recent → a structured-query backfill; both gone → a layout-stable SSR skeleton with an "offline" pill. A stats-stack rollback makes the panel slower, never blank.
  • SSE normalization (load-bearing): live rows are raw producer payloads, so normTs() converts zone-less ClickHouse timestamps → ISO-8601 UTC; the wire filter is type-only (an action IN-filter would drop rows whose action is absent), with a VERBS allowlist as the final arbiter.
  • View-transition lifecycle: per-mount re-init + teardown (SSE close(), all timers). is:global styles because feed rows are runtime-created DOM.

Hero.astro drops terminalLines, the .wh-terminal block, and the .wh-hero__mesh SVG; the pnpm add hint becomes a click-to-copy command chip; the "View on GitHub" glyph finally renders (Starlight parses icon: external into an object, so the old string compare never matched).

Built on the upstream pipes filed + merged on WaveHouse-Stats: #18 (gh_activity_recent), #19 (gh_summary). Per-visitor load is 2 cached, singleflight-collapsed pipe hits + SSE (was 3 uncached reads + SSE).

2. Site-wide design-system / UI consistency pass (docs/src/styles/global.css)

A measured audit (every page × both themes, computed-style harness) drove a unification:

  • Radius — ~11 ad-hoc values collapsed to one scale (--radius-xs/sm/md/lg/pill = 4/8/12/16/999px). All buttons 8px; cards/panels/code-frames/tables 12px (no more 1px frame lip).
  • Buttons — the same CTA rendered three ways; the closer-band pills are now 8px rectangles matching the hero.
  • Light theme (AA) — accent-as-text was 2.6:1; new --wh-accent-text role (6:1) rewired through links/sidebar/focus-ring/stats. Status hues (amber/emerald/rose) got light overrides; page bg stepped darker so white cards read as layers (was 1.04:1, flat).
  • Layout--sl-content-width is now a responsive track (45rem → 50rem ≥72rem → 58rem ≥100rem; prose held to 46rem so text stays ~70–75ch while code/tables/diagrams use the width). .main-frame caps + centers at ≥100rem, killing ~590px of one-sided dead space at 2560px. Zero horizontal overflow across 14 pages × 8 widths (320–2560) × both themes.
  • Grid background — was a hero-only shrinking center-blob, invisible in light; now two page-level fixed layers (full-bleed signal-field grid + breathing hero glow), visible in both themes, scoped via body:has(.wh-hero). Required body:has(.wh-hero){background:transparent} to defeat Starlight's layered opaque body background.
  • Starlight chrome — pagination, tables, blockquotes, search trigger, and the sidebar (group eyebrows + hover + current item) are now branded. (The old sidebar selector …nav > ul > li > a matched 0 elements — the DOM has no nested nav — so it was a silent no-op until rewritten.)

3. Mermaid diagrams — clipping fix, vertical layout, click-to-zoom

The most visible regressions you flagged on the preview:

  • Label clipping (Buffer ConsumerBuffer Consume). Root cause: the build-time Chromium measures each node's box, then the browser displays it — and global.css renders node labels at font-weight 500 while Mermaid measured them at the default 400, so every box came out ~1px too narrow and the longest label in each node clipped on the right. Present on main too (across all 116 nodes), which is why it kept coming back. Fixed upstream in astro-themed-mermaid (new measurementCss option, v0.3.0) that injects the consumer's label metrics into the render page so Mermaid measures what the browser shows. mermaid-theme.mjs passes the node-label weight/letter-spacing + a 1.5px safety pad; selectors are bare (.nodeLabel p) because Mermaid measures before the flowchart <svg> wrapper exists. Verified 0/116 nodes clip after the fix.
  • Diagrams "side-by-side and hard to see." The diagrams themselves are byte-identical to main (same source, same Mermaid config, no version bump) — nothing in the geometry regressed. What you were seeing is the .diagram-pair wrapper (the DIY-vs-WaveHouse comparison): it flipped to a side-by-side row at ≥1500px, shrinking each diagram to ~450px on a wide monitor. That ≥1500px variant is removed — the pair now always stacks vertically at full content width.
  • Click-to-zoom (MermaidZoom.astro, new) — clicking any diagram opens it in a lightbox: small diagrams scale up (capped 2.5×), wide ones show at natural size with pan-scroll for full detail. Esc / backdrop / button closes; keyboard-focusable (Enter). View-transition-safe (one delegated document listener, re-enhanced on astro:page-load). The clone is re-id'd so its id-scoped inline <style> (font, themed fills) and url(#…) refs keep working.
  • House styleAGENTS.md §"Authoring Mermaid diagrams": author vertically (TB/TD) over horizontal (LR) so diagrams fit the page; never sit two large diagrams side-by-side; keep labels short.

Cross-repo note: the astro-themed-mermaid dependency is pinned to the v0.3.0 fix commit while Wave-RF/astro-themed-mermaid#1 (draft) awaits a human merge — the PR-discipline gate blocks an agent from publishing/merging it. Once it's merged and tagged, the pin moves from the SHA to #v0.3.0.

4. Docs-accuracy corrections (prose, surfaced by the review gate)

Each is a code↔docs accuracy fix: all ten ?table= curls quoted (unquoted ? aborts on zsh before curl runs — the first runnable landing command was one); /v1/admin/query example gains its missing Authorization header; the silent 10k limit cap, time_range until semantics, and admin-only callouts + error tables documented across /v1/schema* and /v1/dlq/stats; the DLQ payload corrected to the EventMessage envelope (+X-DLQ-* headers); wh.dlq.stream() marked non-functional (#197); the fictional "SSE/WS fan-out" removed from ingest-pipeline.md; schema-refresh 404 caveats in the quickstarts; and the false "secretless ⇒ no token validates / pure public deployment" framing removed from api.md / access-control.md / configuration.md (see #291 below).

5. Backend / test fixes (surfaced by the gate)

6. Docs preview / tooling

  • Sticky preview comment (ci.yml) now shows the commit subject (linked) and upload time (UTC) alongside the URL, so a stale preview is obvious at a glance.
  • screenshot.mjs: networkidleload (the SSE stream never goes idle); the screenshot-ready signal moved to the visual column's entrance, independent of live data.
  • @wavehouse/sdk is a docs workspace dep; check-docs / dev-docs gained a build-ts prerequisite.

Where this deviates from Astro/Starlight defaults

The bits a future reader (or Starlight upgrade) needs to know are non-stock:

Config (docs/astro.config.mjs)

  • Component overridesHero, SiteTitle, Footer, Head are all replaced with local components. SiteTitle renders a custom <WaveMark/> (theme-aware currentColor) and Starlight's logo is deliberately omitted so it never renders; Footer re-renders Starlight's EditLink/LastUpdated/Pagination itself (overriding Footer drops them) and now also mounts <MermaidZoom/>; Head live-swaps the theme-adaptive favicon.
  • Expressive CodeborderRadius: calc(0.75rem - 1px) (so the frame's outer corner lands at exactly 12px; EC adds the border width and derives inner corners from the same base), custom codeFontFamily/uiFontFamily, frames.shadowColor, themes pinned to github-dark/github-light, and shiki.langAlias (env→bash, dns→ini).
  • Markdown pipelinesyntaxHighlight.excludeLangs: ["mermaid"]; remark [remarkMath, mermaid.remarkInjectClassdefs]; rehype [mermaid.rehypeMermaid, rehypeKatex]. Mermaid is the in-house astro-themed-mermaid integration (build-time SVG via headless Chromium + a per-diagram disk render cache), themed entirely from CSS variables.
  • Plugins beyond stockstarlight-image-zoom, starlight-llm-tools, and starlight-links-validator (conditionally dropped when WAVEHOUSE_DOCS_WATCH is set, so the dev rebuild loop doesn't fail on a mid-edit dangling link).
  • OthertrailingSlash: "never"; explicit favicon set + full Open Graph / Twitter image meta that Starlight doesn't emit; customCss = the design system + KaTeX; custom sidebar; lastUpdated; Tailwind 4 via @tailwindcss/vite inside a Starlight site.

CSS-level Starlight overrides (global.css) — remapped --sl-* tokens (--sl-color-text-accent, the responsive --sl-content-width, --sl-sidebar-width); branded pagination/tables/blockquotes/search-trigger/sidebar; .main-frame ultrawide cap; and the body:has(.wh-hero){background:transparent} workaround for Starlight's layered opaque body background.

Deploy — the site is not built by Cloudflare Workers Builds (no headless browser there for Mermaid); it ships from the CI tail steps (wrangler deploy on main, wrangler versions upload per PR), and a cloudflare-md-router Worker provides .md content negotiation. Workers Builds must stay disconnected from the Worker or it double-deploys.


⚠️ Security finding filed, not fixed here — #291

The docs gate surfaced a pre-existing auth-forgery vulnerability: a secretless deployment (the default compose quickstart, no WH_AUTH_JWT_SECRET) verifies HMAC tokens against []byte(""), so anyone can forge {"role":"admin"} signed with the empty string and reach /v1/admin/query. Verified against golang-jwt v5.3.1. Per maintainer decision it's tracked in #291 for a security-reviewed fail-closed fix and kept out of this docs PR — which only removes the sentences that restated the masking "secretless ⇒ no token validates" claim.

Verification

  • make ci green locally; astro check + full docs build green; markdownlint/biome/typecheck clean.
  • Mermaid: 0/116 node labels clip after the fix (measured on the rebuilt site); click-to-zoom verified open/clone/Esc across pages; diagram-pair confirmed vertical.
  • Live demo: headless Playwright across three data paths (pipes-live, new-pipes-blocked, full blackout) + the 10 viewport×theme sweep, no-overflow, view-transition round-trip.

Follow-ups

🤖 Generated with Claude Code

EricAndrechek and others added 10 commits June 5, 2026 20:05
Replace the static terminal mock + wave-mesh animation in the landing
hero with a live demo panel: real star/fork counts and a curated live
GitHub-activity feed for Wave-RF/WaveHouse, queried in the visitor's
browser from the public read-only role on stats.wavehouse.dev — counts
via pipe(), an events-over-7-days aggregation via the structured query
builder, and the feed via liveQuery() (backfill + SSE). The docs site
becomes a real @wavehouse/sdk consumer (workspace dep; check-docs and
dev-docs now build the SDK first).

The panel renders a layout-stable skeleton without JS and degrades to
it if the demo instance is unreachable. A live stargazer chip joins the
closer band, fed by the same fetch. screenshot.mjs switches networkidle
→ load (the SSE stream never goes idle) and waits on the visual
column's entrance instead of the deleted terminal lines.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Two more pre-existing timing knife-edges surfaced by the runner
migration (#283), both test-only:

- query.test.ts max_execution_time_ms: a zero-row query on a tiny
  table can complete sub-millisecond and beat the 1ms deadline before
  cancellation is ever observed, so a single attempt is a coin flip.
  The enforced property is existential — a 1ms budget must produce
  deadline 500s — so retry via waitForCondition (unique event_id per
  attempt, never cache-served) and pass on the first deadline error.
  Broken enforcement still fails: every attempt succeeds and the wait
  times out.

- batching.test.ts 500-item flush test: the ack rides 500 sequential
  JetStream publish-fsyncs (5104ms observed on APFS vs a 5000ms
  bound), and when the ack outlasts the 5s linger the timer fires
  mid-publish, splits the batch, and the buffer never holds 500 rows
  — the size-trigger property is unobservable in that regime, not
  merely slow (review finding). Now: 15s sanity bound on the ack;
  strict <5s flush assertion only when the publish beat the linger
  with margin (ack <4s); integrity-only verification otherwise; 45s
  explicit test timeout so the worst honest path clears the 30s
  default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
nats-server's Start() installs a process-wide SIGINT handler unless
NoSigs is set; its handler races main's graceful shutdown — either
os.Exit(0)ing past run()'s deferred cleanup, or double-Shutdown
panicking ("close of nil channel", exit 2), which also skips the Go
coverage flush and zeroes the e2e suite's coverage gate. WaveHouse owns
the lifecycle and already stops the server via EmbeddedNATS.Close().

Also backfills the CHANGELOG entry for the live-demo hero panel
(previous commit on this branch).

Closes #287.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dening, docs)

Code review: NoSigs on testutil.NewJetStream's twin options literal
(#287 sweep); anchor the batching size-trigger proof to startTime —
measured from apiEndTime, a broken trigger flushing on the first-row
linger would still pass (supersedes the #283 version of the bound);
LiveDemo drops the action prefilter (liveQuery applies filters to raw
producer rows client-side — VERBS stays the arbiter, backfill margin
24→48) and normalizes zone-less producer timestamps on live SSE rows.

Docs review: sdk.md stops promising '7d' durations (#285), quote all
ten zsh-hostile ?table= curls, Getting Started warns about the 60s
schema-refresh 404 window (+ admin-only tags on /v1/schema/refresh
mentions), development.md documents the docs→SDK build prereq, e2e
file lists gain ndjson.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The 10s SIGINT-to-kill budget was calibrated when the embedded NATS
signal handler os.Exit(0)'d the process early (#287). A real graceful
exit with no OTel collector running — the e2e default — serializes the
traces/metrics/logs exporter shutdowns at ~5s of gRPC dial backoff
apiece and lands ~15s (#288), so the orchestrator was SIGKILLing the
binary before the Go coverage flush, zeroing the e2e coverage gate.
Fast exits are unaffected: the wait selects on process exit.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…, api.md admin docs)

Code: normalize every rowKey part across the two row sources (backfill
is CH-materialized RFC3339/defaults, live SSE is raw producer payload —
raw interpolation could double-render a star landing in the backfill
window); scope the prefilter comment + CHANGELOG claim to the backfill
leg (the SSE leg filters in-browser); byline now names all three SDK
surfaces honestly.

Docs: api.md schema/DLQ sections get the admin-only callout + 401/403
(and 500 for refresh) error rows the rest of the reference has;
time_range row mirrors the #285 duration caveat; sdk.md links #285 per
file convention; getting-started names the 60s worst case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…oc truth)

The closer-band chip had the same [hidden]-vs-author-display bug the
feed empty-state already guarded: display:inline-flex beat the UA
[hidden] rule, flashing the "★ —" placeholder at exactly the no-JS /
demo-down visitors the skeleton protects (verified by computed style
both ways now, not attribute presence). EmbeddedNATS.Close() and the
testutil cleanup gain WaitForShutdown() — owning the lifecycle (#287)
means waiting it out. ast.go's Until comment catches up with what
resolveTimeValue accepts.

Docs: sdk.md stops presenting wh.dlq.stream() as working (no
server-side DLQ stream exists — caveated against #197 in all three
spots); the admin-only sweep reaches /v1/dlq/stats (callout + error
rows), wh.dlq (role note), and the SDK README codegen section
(--auth note).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… notes)

sdk.md says since AND until take relative durations (matching api.md
and resolveTimeValue); api.md states relative values mean that long
ago and that until without since is silently ignored; the README and
deployment quickstarts get the same 60s schema-refresh 404 note
getting-started gained; query-builder's DEFAULT_LIMIT comment stops
claiming it matches backend DefaultMaxRows (1000 vs 10000 — it is a
deliberately tighter client default).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…curl that can 404

api.md's structured-query limit row now states the DefaultMaxRows
clamp (omitted or >10,000 → 10,000, policy max_rows lowers further),
matching sdk.md. The README quickstart's schema-refresh 404 note moves
below the ingest command — /v1/stream accepts any table value and can
never produce it.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
api.md and architecture.md claimed the DLQ payload is the inner data
object; sendToDLQ (worker.go:502) republishes the full EventMessage
envelope with the failure context in X-DLQ-* headers — an operator
parsing per the old docs would mis-read every message. Also drops
architecture.md's phantom jsInput/dlqOutput identifiers (nothing in
the repo has those names) in favor of the real shape + a pointer to
the Ingest Pipeline page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 6, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR enables NoSigs for embedded NATS and waits for server shutdown; adds a LiveDemo landing-hero with SSE-backed feed, counts, and styling; standardizes docs (curl examples, admin-only notes, DLQ envelope, duration formats); updates docs build/screenshot tooling; and hardens e2e tests for timing variability.

Changes

Embedded NATS Shutdown Lifecycle Fix

Layer / File(s) Summary
Embedded NATS lifecycle ownership
internal/mq/embedded.go, internal/testutil/natsjs.go
Enables NoSigs: true in embedded NATS options and waits for shutdown (WaitForShutdown()) in Close/cleanup to prevent signal-handling races.
Orchestrator grace period
scripts/orchestrator/main.go
Increases graceful shutdown timeout from 10s to 30s after SIGINT to allow embedded server teardown to finish.
NATS shutdown changelog entry
CHANGELOG.md
Documents the embedded NATS signal-handling lifecycle fix in Unreleased notes.

Interactive Live Demo Feature

Layer / File(s) Summary
LiveDemo component implementation
docs/src/components/LiveDemo.astro
New Astro component rendering a GitHub-activity feed with SDK-backed counts/backfill and SSE live stream, deduplication, trimming, relative timestamps, and CTA analytics.
Hero section LiveDemo integration
docs/src/components/Hero.astro
Refactors hero to render <LiveDemo />, updates screenshot-ready signaling to .wh-hero__visual animationend, and tightens replay-guard selectors.
LiveDemo and star-counter styling
docs/src/styles/global.css
Adds styling for the live demo panel, feed rows, stream status, and the .wh-closer__count star-chip.
Homepage star-counter markup
docs/src/content/docs/index.mdx, docs/src/styles/global.css
Adds placeholder/markup for a live star counter (data-wh-live="stars") in the homepage closer.
Docs build and screenshot tooling
Makefile, docs/package.json, docs/scripts/screenshot.mjs
Requires building the TypeScript SDK before docs dev/check; adds @wavehouse/sdk workspace dep; changes Playwright screenshot navigation to use load for SSE pages.
Live demo feature changelog entry
CHANGELOG.md
Documents the landing-hero redesign and docs tooling updates in Unreleased notes.

API Contract & Documentation Clarifications

Layer / File(s) Summary
API endpoint contract clarifications
docs/src/content/docs/api.md
Reformats curl examples for safety, documents limit silent cap (10,000) and time_range formats/semantics, adds admin-only notes and error-response tables, and specifies DLQ messages contain the full EventMessage envelope with failed row under data.
Schema discovery and admin-only clarifications
docs/src/content/docs/architecture.md, docs/src/content/docs/configuration.md, docs/src/content/docs/deployment.md
Clarifies DLQ routing uses the full EventMessage envelope with X-DLQ-* headers, marks POST /v1/schema/refresh admin-only, and notes transient 404 unknown table before schema discovery.
SDK duration format and DLQ operation clarifications
docs/src/content/docs/sdk.md
Limits timeRange() relative durations to hour-max Go units (no 7d), marks DLQ ops admin-only, and documents that .dlq.stream() currently receives no server-side events.
Development docs curl formatting and test suite updates
docs/src/content/docs/development.md, docs/src/content/docs/getting-started.md
Standardizes quoted, multiline curl examples, expands pnpm/Playwright guidance, and updates E2E test listings to include NDJSON/dlq suites.
Code comments and docstrings
clients/ts/src/query-builder.ts, internal/query/ast.go
Clarifies QueryBuilder.DEFAULT_LIMIT doc and TimeRange.Until accepted formats (RFC3339, relative durations, empty→now).
README schema-discovery note
README.md, clients/ts/README.md
Adds quickstart note about transient 404 unknown table and documents admin-only /v1/schema introspection requiring an admin JWT.
Documentation changelog entries
CHANGELOG.md
Adds Unreleased entries for doc corrections, CI/contributor automation updates, favicon/head changes, and the query-builder ordering change.

E2E Test Flakiness Fixes

Layer / File(s) Summary
Batching test timing adaptivity
tests/e2e/sdk/batching.test.ts
Replaces fixed timing assertions with adaptive fast/slow paths based on measured ackMs; fast path asserts ClickHouse visibility within 5s, slow path verifies eventual receipt.
Query timeout test retry loop
tests/e2e/sdk/query.test.ts
Replaces single-run assertion with a retry loop issuing unique queries per attempt and waits until an execution-timeout error is observed, then asserts status 500.

🎯 3 (Moderate) | ⏱️ ~25 minutes


Note

🎁 Summarized by CodeRabbit Free

Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Pro by visiting https://app.coderabbit.ai/login.

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

@github-actions github-actions Bot added documentation Improvements or additions to documentation dependencies Pull requests that update a dependency file go Pull requests that update go code area/query Structured query AST, SQL builder area/sdk TypeScript SDK (clients/ts/) area/docs Documentation, site/, README area/infra CI, build, deploy, Docker, release labels Jun 6, 2026
@github-actions

github-actions Bot commented Jun 6, 2026

Copy link
Copy Markdown

📚 Docs preview is live: https://eb2c5361-wavehouse-docs.wave-rf.workers.dev

Live on 34ca5aa — fix(docs): stop mermaid label clipping, stack paired diagrams, add diagram zoom
Updated 2026-06-08 15:15 UTC

EricAndrechek and others added 3 commits June 5, 2026 22:49
…ctivity_recent)

Builds on the WaveHouse-Stats follow-ups now merged (Stats#18/#19):
every headline number comes from one cached gh_summary call (incl.
reconciler-observed open_issues/open_prs, live for any future
[data-wh-live] placement), and the feed backfills from the
server-curated, server-deduped, cached gh_activity_recent pipe — the
SSE tail connects first so nothing lands between backfill and stream
(composite-key dedup absorbs the overlap). The pre-pipe reads stay as
runtime fallbacks: a stats-stack rollback degrades the panel to
slower, not blank.

Per-visitor load drops from 3 uncached reads + SSE to 2 cached,
singleflight-collapsed pipe hits + SSE. Verified all three paths
headless: pipes live (exactly 1+1 pipe calls, 0 legacy reads, 6 rows,
stream live), new pipes blocked (legacy fallback renders), full
blackout (layout-stable skeleton, chip computed-hidden).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…it needs

The only admin-endpoint example without a token — 403s as written
against every documented setup (trial policy default_role is public).
Adds the bearer header + a pointer to the JWT-generation section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…-out

/v1/dlq/stats error table gains its real 500 (stream info failed,
dlq.go:43) + the pre-failure 200 empty shape; the JWT-testing section
says where change-me-in-production comes from and that the compose
quickstart ships no secret (set WH_AUTH_JWT_SECRET first); four
ingest-pipeline.md spots stop asserting an SSE/WS fan-out — no
WebSocket transport exists anywhere in the tree.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EricAndrechek and others added 5 commits June 6, 2026 05:11
)

A secretless deployment actually accepts admin tokens forged with the
empty-string HMAC key (#291, verified against golang-jwt v5.3.1) — so
that parenthetical was a false safety claim. Removed the clause I'd
added this round; the operational guidance (set WH_AUTH_JWT_SECRET on
the compose service) stays. The pre-existing instances of the same
claim in five other docs files, and the code-level fix, are tracked
in #291.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The hero's live panel had a hard ~325px min-width floor and the hero's
overflow:hidden chopped its right edge on any screen narrower than
~365px: on a 360px phone the stream "live" pill, the EVENTS·7d stat,
every feed timestamp, and "Full demo ↗" were all sliced off.

Root cause was a min-content chain: .wh-hero__visual is a flex
container (child min-width defaults to auto) and .wh-live__stats was
repeat(3, 1fr) (tracks floored at min-content), so the three stat
columns set a floor the panel couldn't shrink below — and the mobile
hero track was a bare 1fr (also min-content-floored). Fix breaks the
chain at every level: minmax(0,1fr) on the mobile hero track and the
stat grid, min-width:0 on the visual wrapper and each stat. Labels get
nowrap+ellipsis (single-line) and the mobile breakpoint tightens the
number/label/padding; the feed-row title now ellipsis-truncates
instead of being dropped.

Verified headless: 320/360/375/390 × dark/light all clean (zero
document overflow, panel + stream label + star button + Full demo +
stats + timestamps all within viewport, no truncated labels), and
desktop/wide 1024–2560 unchanged (panel holds 480px).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…me, layout, chrome)

A measured audit (every page, both themes, via a screenshot+computed-
style harness and parallel auditors) found the docs reading as a
polished landing bolted onto stock Starlight. This unifies the system:

- Radius: ~11 ad-hoc values → one scale (4/8/12/16/999px). All buttons
  8px, all cards/panels/code-frames/tables 12px (EC borderRadius set so
  frame + inner share one value, no 1px lip).
- Buttons: the same CTA rendered three ways — the closer-band pills are
  now 8px rectangles matching the hero; "View on GitHub" renders its ↗
  (Starlight parses icon:external into an object, so the string compare
  never matched); stat strip no longer fake-lifts; dead .action.* gone.
- Light theme: new --wh-accent-text role (AA in light, was 2.6:1);
  light status-hue overlays; page bg stepped darker so white cards read
  as layers (was ~1.04:1); ink-subtle/terracotta lifted to clear 4.5:1;
  focus ring AA-safe and no longer squares corners.
- Layout: content widens to 58rem at ≥100rem (TOC-safe), 50rem on
  laptops; prose held to ~46rem; .main-frame caps+centers on ultrawide
  (kills ~590px stranded dead space at 2560); fixed-layout reference
  tables can't overflow. Zero overflow across 14 pages × 8 widths ×
  2 themes.
- Grid bg: full-bleed + visible in light + faint page texture (was a
  shrinking center blob, hero-only, invisible in light).
- Starlight chrome branded: pagination, tables, blockquotes, search
  trigger, sidebar group eyebrows + hover + current item. Dead
  data-section accent system and unused grid/orb/glass utilities removed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ess-control + configuration

The docs gate found the masking framing for #291 still shipping in two
files this PR hadn't touched: access-control.md called a secretless
deployment "a pure public deployment" and configuration.md said "no
token can validate" — both contradicted by internal/auth (an
empty-string-HMAC token validates and can carry role:admin). Pure
deletions of the false guarantee, matching the api.md edit earlier in
this PR; the legitimate tokenless-quickstart wording in
getting-started.md is left intact. The underlying code fix
(fail-closed when no verifier is configured) remains tracked in #291.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…elevate hero CTAs

The grid/glow lived inside .wh-hero, whose overflow:hidden clipped them
to a centered ~1080px box — flat margins on wide screens, a hard
rectangular edge, the glow sliced into an abrupt colored corner, nothing
under the navbar or below the hero. Moved them to two page-level fixed
layers scoped via body:has(.wh-hero): a continuous full-viewport
signal-field grid (teal-tinted, soft vignette, edge-to-edge under the
glass navbar and down the whole page) + a soft breathing teal hero glow
with pure radial falloff (no clipped edges). Genuinely full-bleed,
top-anchored, continuous, both themes.

Hero CTAs: the pnpm-add hint is now a click-to-copy command chip (copy→
check feedback, clipboard API + selection fallback), and a live "★ N
stars" chip joins the meta — fed by the same demo pipe() data as the
panel, so the hero carries live social proof.

Removed the hero's clip + orb elements and the now-dead orb keyframes/
light rules. No overflow 320–2560 × both themes; grid is landing-only
(scoped); breathe respects reduced-motion. Demo wow-factor metrics
(ingest→live latency, events/min sparkline) filed as Stats#33/#34.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
EricAndrechek and others added 6 commits June 6, 2026 11:13
…-metrics

The re-architected page-level grid/glow (fc8685b) were structurally
correct but invisible: they sit at negative z-index, and Starlight's
LAYERED opaque `body { background }` (@layer starlight.reset) painted
over them. Deploying as-is would have shown no grid at all. Fix: set the
landing `body` transparent (scoped via :has(.wh-hero)) so html's base
color is the canvas and the grid/glow paint above it. Grid is now
visibly full-bleed, under the navbar, continuous — both themes.

Wire in the live "wow" metrics now that Stats#33/#34 shipped: an
"⚡ ingested → live in ~N ms" latency readout (browser computes
Date.now() − received_timestamp per SSE event, clamped for skew), a
live events/min sparkline (new gh_events_per_minute pipe), and a
lifetime "N tracked" total (gh_summary.total_events). All degrade to
placeholders when the stream is quiet or a pipe is unavailable.

Implemented + verified by subagent: grid visible both themes, no
overflow 320–2560, astro check clean, 0 console errors in the prod
build, reduced-motion respected.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…ush review)

The gh_events_per_minute pipe's row order is a cross-repo contract;
drawEpm (plots left→right) and bumpEpm (treats last as current minute)
both assume ascending. Sort in loadEpm so a descending pipe response
can't silently reverse the sparkline / misfire the live bump.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	CHANGELOG.md
#	docs/src/content/docs/api.md
#	docs/src/content/docs/sdk.md
#	internal/query/ast.go
Merging origin/main (#292) closed #285 — `7d`/`2w` now resolve to hours
in the structured-query builder, so two rationale comments that justified
"168h, not 7d, because #285" are now false:

- LiveDemo.astro:259 — fallback comment's `("168h" not "7d" — see #285.)`
- CHANGELOG.md — the live-demo entry's `(168h, since day-suffixed
  durations are #285)`

The `168h` literal in the fallback query is unchanged (an explicit hours
value is still perfectly valid); only the obsolete justification is removed.
Flagged by the pre-push code review after the merge.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
# Conflicts:
#	tests/e2e/sdk/query.test.ts
…agram zoom

Addresses the live-demo PR feedback round (diagrams + preview comment):

- Mermaid node labels clipped their last glyph on the live preview
  (`Buffer Consumer` -> `Buffer Consume`): the build-time Chromium measured
  each box at the default font-weight 400 while global.css displays labels
  at weight 500, so every box was ~1px too narrow. Fixed upstream in
  astro-themed-mermaid via a new `measurementCss` option (v0.3.0) that lets
  the consumer inject its label metrics into the render page so Mermaid
  measures what the browser displays. mermaid-theme.mjs passes the node
  label weight/letter-spacing + a 1.5px safety pad and resets cluster
  titles (overflow:visible pills) to default. Verified 0/116 nodes clip.

- `.diagram-pair` no longer flips to a side-by-side row at >=1500px; the
  DIY-vs-WaveHouse comparison stacks vertically at full content width
  (the side-by-side variant shrank each diagram to ~450px on wide monitors).

- Click-to-zoom lightbox for every diagram (MermaidZoom.astro): small
  diagrams scale up, wide ones show at natural size with pan-scroll. View-
  transition-safe; the clone is re-id'd so its id-scoped <style> survives.

- AGENTS.md gains a top-level "Authoring Mermaid diagrams" directive:
  favour vertical (TB/TD) over horizontal (LR) so diagrams fit the page.

- Richer docs-preview sticky comment: the head commit's subject (linked)
  and the upload time, so a stale preview is obvious (ci.yml).

The astro-themed-mermaid pin is the v0.3.0 fix commit
(Wave-RF/astro-themed-mermaid#1, draft pending your merge); switch the pin
to #v0.3.0 once that PR is merged and tagged.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the github_actions Pull requests that update GitHub Actions code label Jun 8, 2026
@EricAndrechek
EricAndrechek marked this pull request as ready for review June 8, 2026 15:10
@EricAndrechek
EricAndrechek merged commit 4cf1f2e into main Jun 8, 2026
8 of 9 checks passed
@EricAndrechek
EricAndrechek deleted the docs-demo branch June 8, 2026 15:11
@github-project-automation github-project-automation Bot moved this from Backlog to Done in WaveHouse Task Board Jun 8, 2026
@github-actions
github-actions Bot requested a review from taitelee June 8, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/docs Documentation, site/, README area/infra CI, build, deploy, Docker, release area/query Structured query AST, SQL builder area/sdk TypeScript SDK (clients/ts/) dependencies Pull requests that update a dependency file documentation Improvements or additions to documentation github_actions Pull requests that update GitHub Actions code go Pull requests that update go code

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants