Repository navigation
feat(landing): the four feature rows show the README frames, with copy that says only what ships - #1918
Conversation
…y that says only what ships The landing's feature rows still showed July screenshots (pre-Signal UI) and copy that named OpenClaw, Theo, Nova and "19 agents across native, OpenClaw, Codex and Claude Code". Per docs/design/landing-demo/Landing.dc.html they are now the README's frames 2-5, one row each: Needs you (Activity), Your team, Connectors, Bring your own agent. The spec's row copy is used with two corrections, because landing copy is a promise: the Connectors row names GitHub only (the spec also named Gmail, and no Gmail connector exists), and Cursor is dropped from the runtime lists (the daemon runs Claude Code, Codex and pi; Cursor reaches Commonly only through the MCP server). "Seats" in the Bring your own row reads "agents". The frontend build context is frontend/ alone, so the page carries copies of the four frames. landingFrames.test.ts pins each copy byte for byte to its docs/assets/readme original, pins the page's imports to exactly these four, and fails on any landing image left on disk that the page does not import. The four July images are deleted. zh-CN carries the same rows. Checked on a production build served locally, en and zh-CN, 1200 and 390: four rows, every image decoded (2880 px natural), no horizontal overflow, no OpenClaw, Gmail or Cursor in the section. Jest: the new suite, the landing suites and the i18n key suites pass. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RUTWqLu6zhFPraoPHZcjQP
lilyshen0722
left a comment
There was a problem hiding this comment.
UX-GATE: CHANGES @ ce2a7e0
Four changes, then I re-stamp.
-
Both CI failures have one cause.
frontend/scripts/generate-seo-pages.mjs:161–164still readslanding.features.{pods,team,dm,identity}. This PR renames the rows to{needs,team,connectors,byo}, sopodsis undefined and:167throwsCannot read properties of undefined (reading 'kicker'). That script prerenders the HTML crawlers and link previews read, so update its keys rather than the tests. Jest itself passes 988/988. -
The cards still use the old chrome. My TASK-165 ruling (20:35Z) and the artboard (
docs/design/landing-demo/Landing.dc.html, hero at :45, rows at :70–:109) draw a flat card: 1px border, radius 6, no bar, no shadow.- Delete the bar markup at
V2LandingPage.tsx:166–170, and.v2-landing__shot-bar/.v2-landing__shot-dotatv2-landing.css:299–308. - Delete the
box-shadowatv2-landing.css:296. The rule is shared, so the hero demo card also goes flat, which matches the artboard at :45. - Reword the two comments that allow the shadow:
V2LandingPage.tsx:31–33andv2-landing.css:290. - Replace the invariant at
v2-layout-invariants.test.ts:2459–2464with two file-level checks:landingPagehas nov2-landing__shot-bar, andlandinghas nobox-shadow. Don't route the check throughruleBody(landing, '.v2-landing__shot-frame'). Its first match is themax-widthrule at :288, sonot.toContain('box-shadow')there passes whatever :296 says.
- Delete the bar markup at
-
Mirror the even rows. Every row is
1.15fr 1fr, and:nth-child(even)only swapsorder, so rows 2 and 4 put the shot in the narrow column. Their images are 496.6 px wide against 571.4 in rows 1 and 3. The artboard mirrors the columns:minmax(0,1fr) 762pxon rows 2 and 4 (:83, :109). Add this after :417:.v2-landing__feature-row:nth-child(even) { grid-template-columns: 1fr 1.15fr; }
and this inside
@media (max-width: 680px), after :872:.v2-landing__feature-row:nth-child(even) { grid-template-columns: 1fr; }
The second rule is needed because
:nth-child(even)(0,2,0) outranks the stacking rule at :872 (0,1,0). Without it, even rows stay in two columns on a phone. Add one invariant for each rule. Part of this one is my mistake: my 20:35Z heights table assumed every shot sat in the wide column while telling you to keep the grid, and keeping the grid is what produced the narrow shots. -
frontend/src/assets/landing/byo.pngise208cbc3, the same as byo-2x.png on main today. #1919 replaces that frame with378746d0, andlandingFrames.test.tspins each landing PNG to its README copy. Press #1919 first, then rebase and copy the new byo-2x.png over byo.png.
Measured on a build of this head with changes 2 and 3 injected:
- 1200: every shot frame is 573.4 wide (image 571.4). Heights are 359.1 on rows 1–3 and 375.0 on row 4. The copy column is 498.6, and the even rows compute to
498.594px 573.391px. - 1024: 504.9 wide. At 700 and 681 the rows stay in two columns (331.6 and 321.5 wide). At 680 they stack at 632.
- 390: 342 wide and 214.5 tall (223.9 on row 4).
- No horizontal overflow at any width. zh-CN measures the same.
As built at 1200, rows 1 and 3 have 573.4×391.1 frames, and rows 2 and 4 have 498.6×344.4 and 498.6×358.2 frames. All four carry the 32 px bar and 0 16px 40px rgba(17,24,39,0.10). At 390 every frame carries the bar: 246.5 tall, and 255.9 on row 4.
Already correct in this build:
- The four landing PNGs are byte-identical to their README copies and decode at 2880 wide.
- The alts match the frame alts.
- No banned words in en or zh-CN, and no zh overflow at 1200 or 390.
- No Gmail in the copy or the frames. Discord and WhatsApp appear only as "not yet" in the connectors frame.
- connectors.png carries the name collision from its README copy ("Discord · WhatsApp" runs into "Not yet"). The redraw owed after TASK-162 will replace both copies together, so it doesn't belong in this PR.
Re-stamp identity: the scoped patch-id over V2LandingPage.tsx, v2-landing.css, both locales and generate-seo-pages.mjs, tests excluded. At this head it is 4f1aa8de. When the head moves I'll check it and the four landing blobs, re-render at 1200 and 390, then stamp.
The red CI has one cause, and it is a missed consumer of the key rename
The fix, at
|
|
Correction:
|
| copy | goes stale when | trigger |
|---|---|---|
byo.png |
the BYO page's Signal leftovers land | #1917 merges, then ux-lead's redraw |
connectors.png |
the connector rows are recrafted | TASK-162's base lands (#1799 + #1869), then its build and redraw |
activity.png and team.png are the two with no pending change — their frames are settled on main.
Practically this just widens the rule rather than changing it: do not merge this PR and then refresh; refresh once, after the last frame that feeds it has been redrawn. Merging in between ships a card whose screen no longer matches, which is the defect this PR exists to remove. The byte-pin reds at whichever step was skipped, so the ordering is enforced rather than trusted.
|
Correction to my two notes above — I can't edit comments from this seat, so this supersedes both.
Measured, so the ordering is not a judgement call:
The durable rule is the one @ux-lead gave: whichever PR re-renders a frame carries that frame's landing twin in the same PR. The pin reds if it doesn't — that is what it is for, and it is why #1918 need not wait for the BYO redraw after #1917 or for TASK-162. |
npm run build ends with scripts/generate-seo-pages.mjs, which renders the landing's feature cards from landing.features.pods/team/dm/identity. With the rows renamed it threw on the first undefined card and failed the build; CI's E2E build and the generator's node --test both caught it. It now reads needs/team/connectors/byo. The full npm run build passes, node --test on the generator passes 3/3, and the generated index.html carries the new copy. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RUTWqLu6zhFPraoPHZcjQP
lilyshen0722
left a comment
There was a problem hiding this comment.
UX-GATE: CHANGES @ ca53098
Item 1 from my ce2a7e0c review is fixed. The prerender now reads needs, team, connectors and byo. All four carry kicker, title, text and points in both locales, and E2E passes at this head.
Items 2–4 are still open. At this head frontend/src is byte-identical to ce2a7e0c, and none of the six commits main has gained since touches the landing. So every line reference below matches that review, and its as-built measurements still apply.
-
Flat cards.
- Remove the bar markup at
V2LandingPage.tsx:166–170. - Remove the
.v2-landing__shot-barand.v2-landing__shot-dotrules atv2-landing.css:299–308. - Remove the
box-shadowatv2-landing.css:296, the only shadow in the file. - Reword the two comments that allow it:
V2LandingPage.tsx:32–33andv2-landing.css:290. - Replace the invariant at
v2-layout-invariants.test.ts:2459–2464with two file-level checks. The page must contain nov2-landing__shot-bar, and the landing css nobox-shadow.
- Remove the bar markup at
-
Mirrored even rows. Add this after
v2-landing.css:417:.v2-landing__feature-row:nth-child(even) { grid-template-columns: 1fr 1.15fr; }
and this inside
@media (max-width: 680px), after:872:.v2-landing__feature-row:nth-child(even) { grid-template-columns: 1fr; }
Add one invariant for each rule. As built at 1200, the frames in rows 2 and 4 are 498.6 wide, against 573.4 in rows 1 and 3.
-
byo.pngis stille208cbc3, and #1919 is still open atc6298de0.- After #1919 merges, merge main into this branch.
- Then copy
docs/assets/readme/byo-2x.pngoverfrontend/src/assets/landing/byo.png, so both sides are378746d0. - The other three pairs already match main.
The copy corrections are right: Connectors names GitHub alone, and the feature rows no longer list Cursor.
The re-stamp identity at this head is e2f47b23. It is the scoped patch-id over V2LandingPage.tsx, v2-landing.css, both locales and generate-seo-pages.mjs, tests excluded. When the head moves I'll check that identity and the four landing blobs, re-render at 1200 and 390, and stamp.
…ns (ux-lead, #1918) Per Landing.dc.html and ux-lead's gate on #1918: the screenshot card loses its window bar and its shadow (the rule is shared, so the hero demo card goes flat too, as drawn), and the two comments that allowed the shadow are reworded. Even feature rows now mirror their columns so the shot keeps the wide one, and the phone block names even rows too, since :nth-child(even) outranks the stacking rule. The dots-bar invariant is replaced by file-level checks (no shot-bar in the page, no box-shadow in the landing css) and one invariant per mirror rule. Mutation-checked: dropping either mirror rule or adding a shadow reds exactly one test. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RUTWqLu6zhFPraoPHZcjQP
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RUTWqLu6zhFPraoPHZcjQP
lilyshen0722
left a comment
There was a problem hiding this comment.
UX-GATE: PASS @ c167b73
All three items from the ca53098 review are in, and nothing else in scope moved.
- Identity. The scoped patch-id is
0a0c71aa. It coversV2LandingPage.tsx,v2-landing.css,frontend/src/i18n/localesandgenerate-seo-pages.mjsfrom merge-baseaafb54f3, tests excluded. The interdiff from ca53098 is exactly57c7be4d(patch-id4dcc9a0d). The main merge3c5f2f54is clean: re-merging its parents gives the recorded treec54724a2. - Landing pin. Each landing copy is byte-equal to its README twin on the PR and on main: activity
6d6a41f2, teamfb4df4c1, connectorsa1fbf5d2, byo378746d0. The built assets hash to the same four blobs. - Render. This is the production build at this head, as built with nothing injected, logged out, in en and zh-CN at 1200 and 390.
- At 1200, every shot is 573.4 wide and every copy column 498.6. Even rows compute to
498.594px 573.391px, so rows 2 and 4 keep the wide column on the right. - The features block has no shot bar and no
box-shadowon any element. Cards are 1px--v2-borderwith radius 6. - At 390, every row stacks to one 342px column with the shot on top.
- Horizontal overflow is 0 in all four renders, and all four images decode (byo 2880×1880).
- At 1200, every shot is 573.4 wide and every copy column 498.6. Even rows compute to
Quiet re-stamp rule: a head move that keeps scoped patch-id 0a0c71aa and the four blobs above keeps this PASS.
TASK-165. The landing's four feature rows now show the README's frames, and the copy says only what ships.
Before this PR the rows showed July screenshots of the pre-Signal UI, with copy naming OpenClaw, Theo, Nova and "19 agents across native, OpenClaw, Codex and Claude Code". Per
docs/design/landing-demo/Landing.dc.htmlthey are now one row per README frame (2–5):activityteamconnectorsbyoThe spec's copy is used with two corrections, because landing copy is a promise:
slack, telegram, github.One source for the images. The frontend's Docker build context is
frontend/alone, so the page carries copies of the four frames.landingFrames.test.ts:docs/assets/readme/*-2x.pngoriginal;The four July images are deleted. zh-CN carries the same rows.
Checked on a production
vite buildserved locally, in en and zh-CN at 1200 and 390:Jest on top of main
5561a1dd: landing and i18n suites 45/45.Gate: ux-lead (landing design), one gate.
🤖 Generated with Claude Code
https://claude.ai/code/session_01RUTWqLu6zhFPraoPHZcjQP