Trigger: Paul 2026-04-25 07:49 PDT — "take a creative pass on enhancing our data exploration and visualization in the chat. ... 20 good ideas, then narrow that down to 10 for my review."
Method: Perplexity deep research (35 raw ideas) + my filter for fit with Firmwatch's actual stack (React + hand-rolled SVG per DriftTrajectoryPlot.jsx pattern, no new chart libs, dark editorial palette, partner-on-phone read use case, must answer a real partner question on Day 1).
Constraint reminders:
src/components/render-tools/ (per spec 026)functions/api/chat/tools-render.tsfunctions/api/chat/tool-schemas.tssrc/hooks/useRenderToolRegistry.jsfunctions/api/chat/system-prompt.ts
1. renderCoInvestorGraph — force-directed graph of which firms have co-led deals; node size = deal count, edge thickness = shared deals, color = tier. Click to focus. Already half-built in spec 028 Stream C as a SQL view; add the visualization layer.
2. renderDealProvenanceCard — per-deal timeline showing source pipeline (RSS feed → Apify → Sonnet enrichment → score → digest), with timestamps + cost. Feels like a "trace view" for deals; useful for trust/debug.
3. renderEntityRelationshipGraph — firm → deal → company → people graph centered on a chosen entity. Hop expansion on click.
4. renderDealMap — geo heatmap of deal locations (HQ city), clustered by sector. Good answer to "which firms invest in EU?" 5. renderHQHotspotMap — for a chosen sector, map of where founder HQs are concentrated; overlay each firm's deals.
6. renderFirmDuelCard — head-to-head firm vs firm comparison (deal count, sector mix, avg check size, drift slope, overlap rate). Replaces "compare X and Y" being a markdown table.
7. renderSectorRotationSlope — slope chart showing each firm's sector rank Q1 vs Q4. Reveals "Mainsail moved from Healthcare to Fintech."
8. renderRadarSpec — per-firm 7-axis radar (sector breadth, check spread, drift rate, follow-on rate, etc.) — note: similar to existing renderExplainabilityCard but firm-level, not deal-level.
9. renderParallelCoordinatesDeals — multi-axis line plot for filtering deals across 5+ dimensions interactively. Power-user tool.
10. renderAnomalyScatter — UMAP projection of all deals; flagged anomalies (firm's first sector entry, unusually large check, weird investor combo) marked with halos. Hypothesis-generation tool. 11. renderHeatmapMatrix — firms (rows) × sectors (columns), cell = deal count; with sparkline trend in each cell. Gives "where's the activity" at a glance. 12. renderRegimeShiftLine — line chart with detected breakpoints (e.g., "Mainsail's deal pace tripled after Mar 2025"). Annotated with the inferred cause if available.
13. renderNextDealHypothesis — for a chosen firm, model predicts likely next sector + check range with confidence. Output: a prose-y card with "based on the last 12 deals, Mainsail's most likely next move is..." — needs Sonnet inference + cited evidence. 14. renderSectorMomentumCard — for a sector, momentum index (deal count delta), top-3 active firms, best comparable companies, drift signals. "Is healthcare hot right now?"
15. renderWeeklyDigestPreview — render the next-morning digest in the chat right now. Gives partners a heads-up without waiting for cron.
16. renderThesisChangelog — timeline visualization of thesis_versions evolution with diffed prose. Useful for "what changed in our thesis last quarter?"
17. renderFirmStoryCard — auto-generated 3-sentence "what's different about Firm X this quarter" with citations to specific deals.
18. renderSavedViewLauncher — list a partner's saved dashboards (saved_dashboards table) inline; click to replay any. Personal "home" surface for the chat drawer.
19. renderScenarioSlider — sliders for thesis weights; live preview of "if we scored deals with weights X, top 5 would be: ...". Built on the existing scoring code.
20. renderDrillDownTreemap — sunburst/treemap of firms → sectors → deals. Click any wedge to refocus. Best general-purpose "give me the lay of the land" tool.
Filtered for: (a) answers a real partner question, (b) buildable on hand-rolled SVG without a chart lib, (c) data exists today or in spec 027/028 scope, (d) doesn't duplicate an existing tool, (e) <300 LOC component.
| # | Tool | What partner question it answers | Data needed (status) | Effort | Risk |
|---|---|---|---|---|---|
| 1 | renderHeatmapMatrix | "Where's everyone investing right now?" | deals.firm_slug, deals.sector (gated on spec 027 T1 enrichment) | M (~250 LOC) | Sector field is 86% null today |
| 2 | renderCoInvestorGraph | "Who has Mainsail co-invested with most?" | deals.lead_investors + firm_co_investments table (spec 028 Stream C) | L (~350 LOC, force-directed SVG) | Dataset is small (17 firms), graph could be sparse |
| 3 | renderFirmDuelCard | "How does Mainsail compare to Arthur?" | Existing — firms + deals + thesis_match_scores | M (~220 LOC) | None — pure aggregation |
| 4 | renderSectorRotationSlope | "Has any firm pivoted thesis recently?" | deals.sector + announced_at (gated on T1) | S (~180 LOC, simple slope chart) | Same null issue |
| 5 | renderDealMap | "Where are firms hunting geographically?" | deals.raw_json.location or company HQ — 90%+ null today | L (~300 LOC + GeoJSON) | Data not there — file as gated on a future "geo extraction" ticket |
| 6 | renderAnomalyScatter | "What's unusual happening this week?" | UMAP needs deal embeddings (we have tms.score_breakdown.cosine) | L (~280 LOC + clustering) | Needs anomaly detection logic; non-trivial |
| 7 | renderWeeklyDigestPreview | "What's tomorrow's digest going to say?" | Existing digest cron + digest_items (gated on spec 027 T2) | S (~150 LOC, reuses Brief.jsx render path) | Digest table is empty until 027 ships |
| 8 | renderSavedViewLauncher | "Show me my pinned dashboards" | saved_dashboards table (exists, empty) | S (~120 LOC) | None — small + standalone |
| 9 | renderDrillDownSunburst | "Give me the lay of the land — firms by sector" | firms + deals.firm_slug + deals.sector (T1) | M (~250 LOC SVG arc paths) | Sector null limits drill resolution |
| 10 | renderFirmStoryCard | "What's different about Mainsail this quarter?" | Sonnet narrative over deals + thesis_match_scores. Reuses the why-narrative pattern. | M (~200 LOC + Sonnet call) | Latency (Sonnet streaming inside a render tool) |
Tier 1 (build now, ships value Day 1, no data-blocker):
renderFirmDuelCard — partners ask compare-firm questions constantly; existing data is sufficient.renderSavedViewLauncher — small, easy, gives the chat drawer a "home" surface.Tier 2 (build alongside spec 027 — they unlock together):
renderHeatmapMatrix — payoff scales 1:1 with how complete deals.sector becomesrenderSectorRotationSlope — same data dependencyrenderDrillDownSunburst — sameTier 3 (build alongside spec 028 — Stream C unblocks):
renderCoInvestorGraph — depends on firm_co_investments materialized viewTier 4 (need new data not yet specced):
renderDealMap — needs geo extraction (file follow-up spec)renderAnomalyScatter — needs embedding-based clustering (file follow-up)renderWeeklyDigestPreview — gated on digest_items writes (spec 027 T2)renderFirmStoryCard — needs Sonnet streaming pattern, gated on T4 narrative workThe real risk isn't building "more tools" — it's that we already have 5 render tools that worked perfectly when we got them wired right today, and we're considering adding 10 more on top of a substrate that took 4 different bug fixes (FIRM-360/361/371/373) to make the existing 5 fire correctly.
A more conservative path: ship Tier 1 (2 tools) only, then sit on it and watch usage for a week. If partners actually use the chat drawer and reach for these, expand. If they don't, we just doubled the surface area without proving the demand.
If you say "go, build all 10," that's a Strata Standard brief — ~30-40 child tickets across 4 layers, gated on spec 027/028 for full payoff.
If you say "Tier 1 only," that's a Fast Track Minimal Brief — 2 tools, ~8-10 tickets total, mostly built on existing data, ships in a few hours of orch time.
What's your call?
~/Documents/Mojo/Morty/briefs/firmwatch-chat-viz-ideation-2026-04-25.md