Skip to content

Commit e74a86a

Browse files
RyanAlbertsclaude
andcommitted
feat(phase-2): cohort filter bar + per-company atlas (Options B + C)
The user asked for a customer-facing product improvement and picked the top two of three options: Option B - Interactive cohort filter (in dashboard.html) Adds a filter bar with search, industry/capability/OSS-posture dropdowns, and a "has traction" toggle. The 5 LLM charts re-render client-side from a JSON blob of per-company rows whenever the filter changes. Pure client-side, no LLM cost. Dropdown options reflect what's actually in the cohort (no dead options). Low- confidence rows are excluded from the filter dataset (same contract as the static charts). Option C - Per-company static pages (companies/<slug>.html + index) Every Tier-A/B + high-or-medium-confidence company in the cohort now has a permalinkable static page with: tagline, industry, capabilities, tech stack, OSS posture + evidence URL when present, traction signals (with source links), rationale, and a "siblings in same industry" block linking to other cohort companies. The browseable companies/index.html lists everyone with a client-side search box. Cross-link wiring: drill-down tables under the LLM charts now link the slug column to companies/<slug>.html. Filter-bar status row links to the index. Each per-company page links back to the main dashboard and the index. Anti-XSS: every interpolation site uses _escape. The recompute JS uses textContent (not innerHTML) to update the filter count. Test test_company_page_escapes_user_content pins the contract. New module: src/ycai/dashboard_company.py Modified: src/ycai/dashboard.py (filter bar HTML + JS + _build_company_rows) .secrets.baseline updated for new captured artifact. CLI surface unchanged - `ycai dashboard <run-dir>` now also emits companies/ alongside dashboard.html. Tests: 15 new (8 filter, 7 per-company). 176 total passing. ruff + mypy strict clean. Artifacts: examples/output/dashboard-w26-pr21-2026-05-04.html plus examples/output/companies-pr21/{index,runanywhere,strand-ai,cardboard}.html. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent e2ae1d3 commit e74a86a

11 files changed

Lines changed: 2162 additions & 19 deletions

.secrets.baseline

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,15 @@
145145
"line_number": 102
146146
}
147147
],
148+
"examples/output/dashboard-w26-pr21-2026-05-04.html": [
149+
{
150+
"type": "Base64 High Entropy String",
151+
"filename": "examples/output/dashboard-w26-pr21-2026-05-04.html",
152+
"hashed_secret": "3c09e03744a49c6020501c9b7ef6218ad440976e",
153+
"is_verified": false,
154+
"line_number": 148
155+
}
156+
],
148157
"src/ycai/dashboard.py": [
149158
{
150159
"type": "Base64 High Entropy String",
@@ -155,5 +164,5 @@
155164
}
156165
]
157166
},
158-
"generated_at": "2026-05-03T19:16:51Z"
167+
"generated_at": "2026-05-06T17:09:58Z"
159168
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width,initial-scale=1" />
6+
<title>Cardboard (cardboard) — yc-ai-pulse</title>
7+
<style>
8+
:root {
9+
--bg: #F5F1E8;
10+
--fg: #1B1B1B;
11+
--muted: #6B6B6B;
12+
--accent: #D24E01;
13+
--line: #DDD8CB;
14+
--ok: #15803D;
15+
--warn: #B45309;
16+
--bad: #B91C1C;
17+
}
18+
body { background: var(--bg); color: var(--fg);
19+
font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Source Serif Pro", Georgia, serif;
20+
margin: 0; padding: 0; }
21+
.wrap { max-width: 920px; margin: 32px auto; padding: 0 24px; }
22+
h1 { font-size: 32px; margin: 0 0 4px; }
23+
h2 { font-size: 18px; margin: 32px 0 12px; }
24+
h3 { font-size: 14px; text-transform: uppercase; letter-spacing: 0.5px; color: var(--muted);
25+
margin: 20px 0 8px; }
26+
.subtitle { color: var(--muted); margin: 0 0 24px; }
27+
.nav { font-size: 14px; margin: 0 0 24px; }
28+
.nav a { color: var(--accent); text-decoration: none; }
29+
.nav a:hover { text-decoration: underline; }
30+
.pill { display: inline-block; padding: 2px 10px; border-radius: 12px; font-size: 12px;
31+
background: #FFF; border: 1px solid var(--line); margin: 0 4px 4px 0; }
32+
.pill-accent { background: #FED7AA; border-color: var(--accent); color: #7C2D12; }
33+
.pill-ok { background: #DCFCE7; border-color: var(--ok); color: #14532D; }
34+
.pill-warn { background: #FEF3C7; border-color: var(--warn); color: #78350F; }
35+
.pill-bad { background: #FEE2E2; border-color: var(--bad); color: #7F1D1D; }
36+
.card { background: white; border: 1px solid var(--line); padding: 20px 24px; margin: 0 0 16px;
37+
border-radius: 4px; }
38+
table { width: 100%; border-collapse: collapse; margin: 8px 0 16px; font-size: 14px; }
39+
th, td { padding: 8px 10px; border-bottom: 1px solid var(--line); text-align: left;
40+
vertical-align: top; }
41+
th { background: #FAFAFA; font-weight: 600; font-size: 13px; text-transform: uppercase;
42+
letter-spacing: 0.4px; color: var(--muted); }
43+
td.detail { font-size: 13px; }
44+
td.detail a { color: var(--accent); }
45+
.quote { font-style: italic; color: #444; }
46+
.meta-row { display: flex; flex-wrap: wrap; gap: 12px; margin: 12px 0; }
47+
.meta-row .item { background: #FFF; border: 1px solid var(--line); padding: 8px 14px;
48+
border-radius: 4px; min-width: 120px; }
49+
.meta-row .item .label { color: var(--muted); font-size: 11px; text-transform: uppercase;
50+
letter-spacing: 0.4px; }
51+
.meta-row .item .value { font-weight: 600; margin-top: 2px; }
52+
.source-list { font-size: 13px; }
53+
.source-list li { word-break: break-all; }
54+
footer { color: var(--muted); font-size: 13px; margin: 48px 0 24px;
55+
padding-top: 24px; border-top: 1px solid var(--line); }
56+
input[type=search] { width: 100%; max-width: 400px; padding: 8px 12px;
57+
border: 1px solid var(--line); border-radius: 4px; font-size: 15px; }
58+
.siblings { font-size: 13px; }
59+
.siblings a { color: var(--accent); margin-right: 8px; }
60+
</style>
61+
</head>
62+
<body>
63+
<div class="wrap">
64+
<p class="nav">
65+
<a href="../dashboard.html">← Cohort dashboard</a> ·
66+
<a href="index.html">Browse all companies</a>
67+
</p>
68+
<h1>Cardboard</h1>
69+
<p class="subtitle">YC slug <code>cardboard</code> · Winter 2026</p>
70+
71+
<div class="card">
72+
<p class="quote" style="margin: 0;">Browser-native agentic video editor that turns raw footage into publish-ready cuts in minutes for growth and marketing teams.</p>
73+
</div>
74+
75+
<div class="meta-row">
76+
<div class="item"><div class="label">Industry</div><div class="value">B2B SaaS</div></div>
77+
<div class="item"><div class="label">OSS posture</div><div class="value"><span class="pill pill">closed</span></div></div>
78+
<div class="item"><div class="label">Confidence</div><div class="value"><span class="pill pill-ok">confidence: high</span></div></div>
79+
</div>
80+
81+
<h2>Capabilities</h2>
82+
<p><span class="pill pill-accent">agents</span><span class="pill pill-accent">multimodal</span><span class="pill pill-accent">vision</span><span class="pill pill-accent">nlp-classic</span><span class="pill pill-accent">speech</span></p>
83+
84+
<h3>Secondary industries</h3><p><span class="pill">Media / Content</span><span class="pill">Consumer</span></p>
85+
86+
<h2>Tech stack</h2>
87+
<p><span class="pill">unknown</span></p>
88+
89+
90+
91+
<h2>Traction signals</h2>
92+
<table><thead><tr><th>Kind</th><th>Detail (verbatim)</th><th>Link</th></tr></thead><tbody><tr><td><span class="pill">other</span></td><td class="detail quote">Backed by</td><td class="detail"><a href="https://www.usecardboard.com/">source</a></td></tr><tr><td><span class="pill">other</span></td><td class="detail quote">7-day money-back guarantee</td><td class="detail"><a href="https://www.usecardboard.com/pricing">source</a></td></tr><tr><td><span class="pill">other</span></td><td class="detail quote">0.0.22 April 27, 2026</td><td class="detail"><a href="https://www.usecardboard.com/changelog">source</a></td></tr></tbody></table>
93+
94+
<h2>Sources</h2>
95+
<ul class="source-list">
96+
<li><a href="https://www.ycombinator.com/companies/cardboard">https://www.ycombinator.com/companies/cardboard</a></li><li><a href="https://www.usecardboard.com/">https://www.usecardboard.com/</a></li><li><a href="https://www.usecardboard.com/pricing">https://www.usecardboard.com/pricing</a></li><li><a href="https://www.usecardboard.com/changelog">https://www.usecardboard.com/changelog</a></li>
97+
</ul>
98+
99+
<h3>Why this classification</h3><p class="quote">YC tags 'SaaS, Video, Media, AI' and the description explicitly targeting 'growth/marketing teams' confirm B2B SaaS primary with Media/Content secondary; AI capabilities are evidenced by 'agentic video editor,' 'Multimodal LLMs can finally reason over footage,' 'Natural language commands,' and 'Automated captions.' No specific LLM provider is named in any crawled page, so tech_stack is unknown.</p>
100+
101+
<h3>Other B2B SaaS companies in this batch</h3><p class="siblings"><a href="aurorin-cad.html"><code>aurorin-cad</code></a> <a href="autumn-ai.html"><code>autumn-ai</code></a> <a href="booko.html"><code>booko</code></a> <a href="bubble-lab.html"><code>bubble-lab</code></a> <a href="caretta.html"><code>caretta</code></a> <a href="chasi.html"><code>chasi</code></a> <a href="constellation-space.html"><code>constellation-space</code></a> <a href="crow.html"><code>crow</code></a> <a href="eigenpal.html"><code>eigenpal</code></a> <a href="ishiki-labs.html"><code>ishiki-labs</code></a> <a href="jinba.html"><code>jinba</code></a> <a href="lance.html"><code>lance</code></a></p>
102+
103+
<footer>
104+
<p>This page is generated from <code>analyses.jsonl</code> by yc-ai-pulse.
105+
Every field above is the LLM's classification with sources cited; nothing is invented.
106+
See <a href="../dashboard.html#dropped">the dropped register</a> for excluded companies.</p>
107+
<p style="margin-top: 8px;">
108+
Source code: <a href="https://github.com/RyanAlberts/yc-ai-pulse">github.com/RyanAlberts/yc-ai-pulse</a>
109+
</p>
110+
</footer>
111+
</div>
112+
</body>
113+
</html>

0 commit comments

Comments
 (0)