Skip to content

Commit 18d7739

Browse files
bloveclaude
andauthored
feat(website): replace the Yes wall with the reliability band (#996)
The Yes wall was not earning its place at the top of the homepage. The dark contrast band it occupied was, so the proof strip moves into it: same cells, same sources, re-toned for the dark surface scope. - Delete YesWall (component, spec, CSS, and its home_yes_wall_docs id). - Move ProofStrip up to the slot under the logo ribbon and switch it from surface="tinted" to surface="dark". It keeps the radial glow and a gradient Garamond watermark, the devices that gave that band its presence. - Stack the rail header above the cells. Beside them the four Garamond numerals were down to 176px columns and wrapping ("#13 of / 119"); full width gives each cell 265px. 2-up under 900px, 1-up under 560px. - Add min-width:0 to .proof-strip-cell. Without it the long mono source URLs pushed the grid ~240px past the container — invisible behind body's overflow-x clip, but the section's own clip cut a card in half. - Link the OpenSSF number to the scorecard.dev viewer instead of api.securityscorecards.dev, which renders as raw JSON, and guard every sourceHref against api hosts and /api/ paths. - Re-verify all four numbers per the file's own contract: the category rank is #8 of 119 (was #13) and Scorecard is 8.2 (was 8.1). Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
1 parent fddb26c commit 18d7739

10 files changed

Lines changed: 173 additions & 399 deletions

File tree

apps/website/e2e/website.spec.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,9 +25,10 @@ test('landing page renders hero headline', async ({ page }) => {
2525
expect(headline?.toLowerCase()).toContain('angular');
2626
});
2727

28-
test('landing page renders the Yes wall', async ({ page }) => {
28+
test('landing page renders the dark proof band', async ({ page }) => {
2929
await page.goto('/');
30-
await expect(page.locator('#yes-wall-heading')).toBeVisible();
30+
await expect(page.locator('#proof-heading')).toBeVisible();
31+
await expect(page.locator('#proof[data-surface="dark"]')).toBeVisible();
3132
});
3233

3334
test('landing page renders feature blocks (Stream/Render/Ship)', async ({ page }) => {

apps/website/src/app/page.tsx

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Hero } from '../components/landing/Hero';
22
import { LogoRibbon } from '../components/landing/LogoRibbon';
3-
import { YesWall } from '../components/landing/YesWall';
3+
import { ProofStrip } from '../components/landing/ProofStrip';
44
import { FeatureBlock } from '../components/landing/FeatureBlock';
55
import { StackDiagramSection } from '../components/landing/StackDiagramSection';
66
import { HomeConceptGrid } from '../components/landing/HomeConceptGrid';
@@ -9,7 +9,6 @@ import { MediumSwitcher } from '../components/landing/MediumSwitcher';
99
import { SECTION_MEDIA } from '../lib/section-media';
1010
import { buildPanes } from '../lib/build-panes';
1111
import { PilotBlock } from '../components/landing/PilotBlock';
12-
import { ProofStrip } from '../components/landing/ProofStrip';
1312
import { WhitePaperBlock } from '../components/landing/WhitePaperBlock';
1413
import { HomeFAQ } from '../components/landing/HomeFAQ';
1514
import { FinalCTA } from '../components/landing/FinalCTA';
@@ -38,7 +37,7 @@ export default async function HomePage() {
3837
<>
3938
<Hero />
4039
<LogoRibbon />
41-
<YesWall />
40+
<ProofStrip />
4241

4342
<StackDiagramSection
4443
id="architecture"
@@ -108,8 +107,6 @@ export default async function HomePage() {
108107
/>
109108

110109
{/*
111-
The homepage claims human-in-the-loop in the Yes wall, but nothing
112-
before this section showed it.
113110
This is the only section whose heading the approval clip actually
114111
illustrates — the same rule the solutions pages follow.
115112
*/}
@@ -135,7 +132,6 @@ export default async function HomePage() {
135132

136133
<PilotBlock />
137134
<WhitePaperBlock formPolicy={formPolicy} />
138-
<ProofStrip />
139135
<HomeFAQ />
140136
<RecentArticles />
141137
<FinalCTA variant="dark" />

apps/website/src/components/landing/ProofStrip.spec.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,4 +18,32 @@ describe('ProofStrip', () => {
1818
const badge = screen.getByAltText(/HVTrust grade/i);
1919
expect(badge.getAttribute('src')).toBe('https://hvtracker.net/badge/threadplane.svg');
2020
});
21+
22+
it('renders on the dark contrast band, with a watermark carrying no text', () => {
23+
const { container } = render(<ProofStrip />);
24+
25+
const section = container.querySelector('[data-ui="section"]');
26+
expect(section?.getAttribute('data-surface')).toBe('dark');
27+
expect(section?.getAttribute('id')).toBe('proof');
28+
29+
const mark = container.querySelector('.proof-strip-watermark');
30+
expect(mark?.getAttribute('aria-hidden')).toBe('true');
31+
expect(mark?.getAttribute('data-watermark-text')).toBe('Proof');
32+
expect(mark?.textContent).toBe('');
33+
});
34+
35+
it('keeps the "Reliable to the core" framing on the band', () => {
36+
render(<ProofStrip />);
37+
expect(screen.getByText('Reliable to the core')).toBeTruthy();
38+
const heading = screen.getByRole('heading', { name: 'Audited, scored, published.' });
39+
expect(heading.id).toBe('proof-heading');
40+
});
41+
42+
it('links every number to a human-readable page, never a raw API', () => {
43+
for (const cell of PROOF_CELLS) {
44+
const { hostname, pathname } = new URL(cell.sourceHref);
45+
expect(hostname.startsWith('api.'), cell.sourceHref).toBe(false);
46+
expect(pathname.startsWith('/api/'), cell.sourceHref).toBe(false);
47+
}
48+
});
2149
});

apps/website/src/components/landing/ProofStrip.tsx

Lines changed: 64 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -14,89 +14,102 @@ interface ProofCell {
1414
}
1515

1616
/**
17-
* Verified 2026-08-27 against live sources (see the homepage design spec,
17+
* Verified 2026-09-04 against live sources (see the homepage design spec,
1818
* "Verification results"). The rank and score drift over time — re-verify on
1919
* touch, and never "round up". The HVTrust grade is deliberately a LIVE badge:
20-
* it sits at 81.2 against an A-band floor of 80 and has flipped grade six
21-
* times in one month; a hardcoded letter would be wrong on some days.
20+
* it sits at 84.3 against an A-band floor of 80 and has flipped grade several
21+
* times in a month; a hardcoded letter would be wrong on some days.
22+
*
23+
* Every href must be a page a human can read. The Scorecard number comes from
24+
* api.securityscorecards.dev, but the LINK goes to the scorecard.dev viewer —
25+
* the API URL renders as raw JSON.
2226
*/
2327
export const PROOF_CELLS: readonly ProofCell[] = [
2428
{
25-
value: '#13',
29+
value: '#8',
2630
suffix: 'of 119',
2731
caption: 'Of all agent frameworks ranked',
2832
sourceLabel: 'hvtracker.net',
2933
sourceHref: 'https://hvtracker.net/categories/agent-frameworks/',
3034
},
3135
{
32-
value: '8.1',
36+
value: '8.2',
3337
suffix: '/10',
34-
caption: 'OpenSSF Scorecard, official API',
35-
sourceLabel: 'securityscorecards.dev',
38+
caption: 'OpenSSF Scorecard, official scan',
39+
sourceLabel: 'scorecard.dev',
3640
sourceHref:
37-
'https://api.securityscorecards.dev/projects/github.com/cacheplane/angular-agent-framework',
41+
'https://scorecard.dev/viewer/?uri=github.com/cacheplane/angular-agent-framework',
3842
},
3943
{
4044
value: null,
4145
caption: 'HVTrust supply-chain grade, live',
42-
sourceLabel: 'hvtracker.net/agents/threadplane',
46+
sourceLabel: 'hvtracker.net/agents',
4347
sourceHref: 'https://hvtracker.net/agents/threadplane/',
4448
},
4549
{
4650
// Revived per the homepage design spec's condition: npm @latest publishes
4751
// ^20 || ^21 || ^22 (verified 2026-08-31). Derived, never hardcoded.
4852
value: `${WEBSITE_SUPPORTED_ANGULAR_MAJORS[0]}${WEBSITE_SUPPORTED_ANGULAR_MAJORS.at(-1)}`,
4953
caption: 'Angular majors supported, CI-tested',
50-
sourceLabel: 'npmjs.com/@threadplane/langgraph',
54+
sourceLabel: 'npmjs.com',
5155
sourceHref: 'https://www.npmjs.com/package/@threadplane/langgraph',
5256
},
5357
];
5458

5559
export function ProofStrip() {
5660
return (
57-
<Section surface="tinted" tight id="proof" ariaLabelledBy="proof-heading">
61+
<Section surface="dark" id="proof" ariaLabelledBy="proof-heading">
5862
<Container>
59-
<div className="proof-strip-grid">
60-
<SectionHeader
61-
variant="rail"
62-
eyebrow="Reliable to the core"
63-
heading="Audited, scored, published."
64-
headingId="proof-heading"
65-
aside="Not self-reported — every number links to its source."
63+
<div className="proof-strip">
64+
{/* Garamond watermark; the glyph comes from the data attribute so no
65+
* stray text reaches screen readers or getAllByText. */}
66+
<div
67+
className="proof-strip-watermark"
68+
aria-hidden="true"
69+
data-watermark-text="Proof"
6670
/>
67-
<ul className="proof-strip-cells" role="list">
68-
{PROOF_CELLS.map((cell) => (
69-
<li className="proof-strip-cell" key={cell.caption}>
70-
{cell.value ? (
71-
<p className="proof-strip-value">
72-
{cell.value}
73-
{cell.suffix ? (
74-
<span className="proof-strip-suffix"> {cell.suffix}</span>
75-
) : null}
76-
</p>
77-
) : (
78-
<img
79-
className="proof-strip-badge"
80-
src="https://hvtracker.net/badge/threadplane.svg"
81-
alt="HVTrust grade for Threadplane (live badge)"
82-
width={91}
83-
height={20}
84-
loading="lazy"
85-
referrerPolicy="no-referrer"
86-
/>
87-
)}
88-
<p className="proof-strip-caption">{cell.caption}</p>
89-
<a
90-
className="proof-strip-source"
91-
href={cell.sourceHref}
92-
target="_blank"
93-
rel="noopener noreferrer"
94-
>
95-
{cell.sourceLabel}
96-
</a>
97-
</li>
98-
))}
99-
</ul>
71+
<div className="proof-strip-grid">
72+
<SectionHeader
73+
variant="rail"
74+
eyebrow="Reliable to the core"
75+
heading="Audited, scored, published."
76+
headingId="proof-heading"
77+
aside="Not self-reported — every number links to its source."
78+
/>
79+
<ul className="proof-strip-cells" role="list">
80+
{PROOF_CELLS.map((cell) => (
81+
<li className="proof-strip-cell" key={cell.caption}>
82+
{cell.value ? (
83+
<p className="proof-strip-value">
84+
{cell.value}
85+
{cell.suffix ? (
86+
<span className="proof-strip-suffix"> {cell.suffix}</span>
87+
) : null}
88+
</p>
89+
) : (
90+
<img
91+
className="proof-strip-badge"
92+
src="https://hvtracker.net/badge/threadplane.svg"
93+
alt="HVTrust grade for Threadplane (live badge)"
94+
width={91}
95+
height={20}
96+
loading="lazy"
97+
referrerPolicy="no-referrer"
98+
/>
99+
)}
100+
<p className="proof-strip-caption">{cell.caption}</p>
101+
<a
102+
className="proof-strip-source"
103+
href={cell.sourceHref}
104+
target="_blank"
105+
rel="noopener noreferrer"
106+
>
107+
{cell.sourceLabel}
108+
</a>
109+
</li>
110+
))}
111+
</ul>
112+
</div>
100113
</div>
101114
</Container>
102115
</Section>

apps/website/src/components/landing/YesWall.spec.tsx

Lines changed: 0 additions & 60 deletions
This file was deleted.

0 commit comments

Comments
 (0)