Skip to content

Landing: make every heading a sentence, and let the comparison concede - #142

Open
adnaan wants to merge 1 commit into
mainfrom
landing-voice-pass
Open

Landing: make every heading a sentence, and let the comparison concede#142
adnaan wants to merge 1 commit into
mainfrom
landing-voice-pass

Conversation

@adnaan

@adnaan adnaan commented Aug 15, 2026

Copy link
Copy Markdown
Contributor

Rewrite number five for this page. The last four drifted back, so this one records the rule as well as applying it.

The heading defect

The complaint was that "A shared greeting wall, running on this page." is not how anyone speaks, and that it reads passive. It isn't passive — it's a verbless noun phrase punctuated as a sentence. A determiner, a noun, a participle, and a full stop pretending. No finite verb, so nothing in it is doing anything, which is the same effect passive has.

Four headings were like that:

before after
A shared greeting wall, running on this page. Everyone reading this page writes to the same wall.
The parts of that worth a second look. Four of those lines are worth a second look. One thing is missing.
Other things in here. The rest of the docs covers the ordinary screens.
Getting started. Install it, then pick a recipe.

The distribution is the finding worth keeping. Headings that make a technical claim were already sentences — "The button's name is the action", "The HTML rule runs again in Go", "Two calls sync your tabs". Every fragment was a heading that orients the reader rather than argues. The register broke where the page navigated, so the connective headings are the ones to check.

The comparison table

Worse than a voice problem. Every row sat under a neighbour's name and described LiveTemplate instead — read the Alpine.js row cold and it parses as a description of Alpine. And it conceded nothing: five rows, five wins, no losses, from a library whose own eyebrow says alpha.

Each row now describes the neighbour and names what it does better. htmx works against any backend in any language. templ type-checks markup at compile time and html/template cannot. Alpine keeps real state in the browser. LiveView is years ahead on production use and ecosystem. The React row reuses the canvas-editor line from getting-started/introduction.md so the two pages agree.

These are positioning judgments, not copy edits. Overrule any of them.

One correctness bug caught in review

The first draft of the Alpine row said it "answers a click without a round trip, which nothing here can do." False. reference/client-attributes.md documents native DOM event triggers that "execute client-side with no server round-trip", with click, mouseenter and click-away listed — the dropdown case exactly. It also contradicted the escape-hatch note two screens up. An overstated concession is the same credibility problem in reverse.

Also

  • #diff in the rail pointed at no section — a fossil from Landing: show the finished app first, then explain it #136, where the diff step folded into Multi-user. validate, the sweep and the e2e suite all passed over it because nothing resolves in-page anchors.
  • "The first is the way to reach for" — mangled idiom.
  • "It targets what Go teams actually ship" — product as subject, through a pronoun that dodges the checker's ^LiveTemplate regex.
  • A relative clause in the section intro that didn't attach, plus "and which says so" — the document narrating itself.
  • The hero's triadic negation, which the front-matter description repeated verbatim. Two copies, one edit.
  • The CTA heading promised the counter tutorial that neither button linked to.

No new checker rule

"Heading lacks a finite verb" needs a parser, and a fragile approximation gets switched off within a week. Same call as rhetorical reversals, and that precedent held. It goes in VOICE.md with the reading test: every heading here ends in a period, so every heading has to earn one.

Verification

  • voice-check.sh — pass, every ceiling unchanged (passive 34/34, triad 1/1, exclamation 3/3 all had zero headroom)
  • tinkerdown validate — 98/98, 0 errors
  • go test ./e2e/ against a local build — pass, 140s
  • make sweep at desktop + iphone-14 — 196 visits, 2 flagged, both the pre-existing large-table timeout. The row-v cells are ~3× longer now, so mobile was the real risk.
  • Read at 1440px in a browser
  • All 11 headings now carry a finite verb; no dead in-page anchors remain

🤖 Generated with Claude Code

https://claude.ai/code/session_0166MK1arBYbVZq6wfm8EsQZ

…concede

Four headings were verbless noun phrases punctuated as sentences: "A
shared greeting wall, running on this page.", "The parts of that worth a
second look.", "Other things in here.", "Getting started." No finite verb,
so nothing in them is doing anything. That reads as passive even though it
isn't one.

The split is the interesting part. Headings that make a technical claim
were already sentences — "The button's name is the action", "The HTML rule
runs again in Go", "Two calls sync your tabs". The four fragments were all
headings that orient the reader rather than argue. The register broke
where the page navigated.

The comparison table had a worse problem. Every row sat under a
neighbour's name and described LiveTemplate instead, so the Alpine.js row
read as a description of Alpine. Five rows, five wins, no losses, from a
library whose own eyebrow says alpha. Each row now describes the neighbour
and says where it still wins: htmx works against any backend, templ
type-checks markup at compile time, Alpine keeps real state in the
browser, LiveView is years ahead. The React row reuses the line from
getting-started/introduction.md so the two pages agree.

The first draft of the Alpine row claimed it "answers a click without a
round trip, which nothing here can do." That is false — reference/
client-attributes.md documents native DOM event triggers that "execute
client-side with no server round-trip", which is the dropdown case
exactly. An overstated concession is the same credibility problem in
reverse, and it contradicted the escape-hatch note two screens up.

Also fixed:
- #diff in the rail pointed at no section — a fossil from #136, where the
  diff step folded into Multi-user. Nothing resolves in-page anchors, so
  validate, the sweep and the e2e suite all passed over it.
- "The first is the way to reach for" — mangled idiom.
- "It targets what Go teams actually ship" — product as subject, via a
  pronoun that dodges the checker's ^LiveTemplate regex.
- A relative clause in the section intro that didn't attach, plus "and
  which says so", which is the document narrating itself.
- The hero's triadic negation, which the front-matter description
  repeated verbatim — two copies, one edit.
- The CTA promised the counter tutorial that neither button linked to.

No checker rule for the heading defect: "lacks a finite verb" needs a
parser, and a fragile approximation gets switched off within a week. It
goes in VOICE.md with the reading test, same call as rhetorical reversals.
Every ratchet ceiling is unchanged.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0166MK1arBYbVZq6wfm8EsQZ
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant