Ask the blocking questions where they arise, cut the index, and finish the button primitive - #5
Merged
Merged
Conversation
Nineteen buttons, four padding scales, one unused primitive. They now all go through it, and two hazards had to be handled first — neither of which a test here would have caught. **Download.tsx assigns `href` imperatively.** It resolves the real asset URL after mount and writes it onto the anchor through a ref. A button component that swallowed the ref would have left both download buttons pointing at the generic releases page: a broken download, on the download page, silently. React 19 passes `ref` to function components as an ordinary prop, so the primitive takes one. **Download.tsx also swaps the two buttons' classes at runtime**, to make whichever architecture it detected the primary one. That hard-coded both class strings, so the imperative half and the rendered half would drift apart the first time either changed — which is the exact failure the primitive exists to prevent, reintroduced one layer down. `buttonClasses()` is now exported and both halves read from it. Three buttons keep their own element and borrow only the class list, because they are not links: the header's dropdown trigger carries `aria-expanded` and `aria-haspopup` and a keyboard handler, the iPhone toggle carries `aria-controls`, and the email form's is a submit. Sharing the classes without forcing the element is the right shape for those.
…he index Four content decisions, and one script so the fifth can be answered. **The two questions that stop a download now sit under the hero.** "Is it really free, or free for now?" and "Can I use TablePro at work under AGPLv3?" used to be items one and two of a FAQ at position fifteen — behind roughly three thousand words, past the point where a reader holding either objection has already left. The AGPL one blocks the highest-value visitor there is: someone evaluating a Team licence for a company. **"Can the AI drop a table on production?" moves into the Agents section**, which is the section that raises the fear. It answered it two positions and several hundred words later. **"Can I move my connections from another client?" is dropped** from the homepage: SwitchFrom is an entire section on exactly that, and it now sits at position seven rather than eleven. None of these leave the site. `home-faqs.ts` splits into `homeFaqs` (the four that stay in the FAQ block) and `relocatedFaqs` (the four rendered inline), and `/faq` spreads both — so it still lists all fourteen, and each answer exists in exactly one place. Both StaleClaimsTest counts stay true, and still mean what they say. **DepthGrid goes from twelve cells to six.** Three repeated a section above it — Vim mode from the workbench ledger, connection import from the whole SwitchFrom section, plugin verification from the database grid's own lede — so cutting them is deduplication, not taste. Three more were table stakes every competitor also ships. The `spec` line goes with them: shortcuts, thresholds and defaults are genuinely useful and genuinely documentation, and they were roughly 250 words standing between the reader and the next call to action. The section's own comment called itself "an index rather than twelve more pitches"; it is now an index of six. **/faq gets an h1.** It had none at all — SectionShell emits h2, so the page started its heading tree at level two. sr-only, because the FAQ section already opens with its own headline and two stacked headlines saying the same thing is worse than none. **Sponsors gain a description slot.** Structure only: the copy is eight facts about eight real companies and is not mine to write. A sponsor without one still renders its mark, so filling them in later is a data edit. **scripts/measure-cold-start.sh** measures launch-to-first-window for TablePro and any competitor you name, purging the page cache between runs and refusing to report if it could not — a warm start quoted as a cold one is exactly what this is meant to prevent. It prints hardware, OS build, version and range along with the median. The point is not the number; it is that the method is runnable by anyone, which is what turns "Under 1s" from a claim into a measurement.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The four content decisions you asked me to draft, the button migration, and a
script so the cold-start number can stop being a claim.
The two questions that stop a download now sit under the hero
"Is it really free, or free for now?" and "Can I use TablePro at work under
AGPLv3?" were items one and two of a FAQ at position fifteen — behind roughly
three thousand words, past the point where a reader holding either objection has
already left. The AGPL one blocks the highest-value visitor there is: someone
evaluating a Team licence for a company.
"Can the AI drop a table on production?" moves into the Agents section, which is
the section that raises the fear. It was being answered two positions and
several hundred words later.
"Can I move my connections from another client?" is dropped from the homepage —
SwitchFrom is an entire section on exactly that, and since #2 it sits at
position seven rather than eleven.
Nothing leaves the site.
home-faqs.tssplits intohomeFaqs(the fourthat stay in the block) and
relocatedFaqs(the four rendered inline), and/faqspreads both — still fourteen questions, each answer existing in exactlyone place. Verified in the rendered page. Both
StaleClaimsTestcounts staytrue and keep meaning what they say, so neither assertion needed weakening.
DepthGrid: twelve cells to six
Three repeated a section above it, which makes cutting them deduplication rather
than taste — I verified each: Vim mode against the workbench ledger,
connection import against the whole SwitchFrom section, plugin
verification against the database grid's own lede. Three more (ER diagram,
query history, import/export) are table stakes every competitor also ships, and
"Import and export, including XLSX" already appears in the pricing comparison.
What survives is the set a reader could not assume: EXPLAIN visualised, server
dashboard, users and roles, Quick Switcher, CSV inspector, backup and restore.
The
specline goes with them — shortcuts, thresholds and defaults, genuinelyuseful and genuinely documentation, and roughly 250 words standing between the
reader and the next call to action. The section's own comment called itself "an
index rather than twelve more pitches". It is now an index of six.
/faq gets an h1
It had none at all:
SectionShellemitsh2, so the page started its headingtree at level two.
sr-only, because the FAQ section already opens with its ownheadline and two stacked headlines saying the same thing is worse than none.
Sponsors: structure only
A
descriptionslot per sponsor, and the cell becomes a column so a line can situnder the mark. The copy is not in this PR — it is eight facts about eight
real companies and not mine to invent. A sponsor without one still renders its
mark, so filling them in is a data edit whenever you have them.
The button migration, and two hazards it had to clear first
Nineteen buttons, four padding scales, one primitive nobody imported. They all go
through it now. Neither of these would have been caught by a test here:
Download.tsxassignshrefimperatively through a ref after resolvingthe real asset URL. A primitive that swallowed the ref would have left both
download buttons pointing at the generic releases page — a broken download, on
the download page, silently. React 19 passes
refas an ordinary prop, so theprimitive takes one.
Download.tsxalso swaps the two buttons' classes at runtime to make thedetected architecture primary, and hard-coded both strings. That is the exact
drift the primitive exists to prevent, reintroduced one layer down.
buttonClasses()is exported and both halves now read from it.Three keep their own element and borrow only the class list, because they are
not links: the header's dropdown trigger (
aria-expanded,aria-haspopup, akeyboard handler), the iPhone toggle (
aria-controls), and the email form'ssubmit.
scripts/measure-cold-start.sh
You said the benchmark is measurable, so here is the thing to run. It times
launch to first window for TablePro and any competitor you name, purges the page
cache between every run, and refuses to report if it could not purge — a warm
start quoted as a cold one is precisely what this exercise exists to prevent. It
prints hardware, OS build, app version and the range alongside the median.
The point is not the number. It is that the method is runnable by anyone, which
is what turns "Under 1s" from a claim into a measurement — and whatever lands on
the page should link here.
Give me the output and I will build the EXPLAIN cost tree and the dated
methodology footnote on top of it.
Still outstanding
The hero recapture, which you are doing — that unlocks the Plate component and
the workbench two-state toggles as well. And the eight sponsor lines.
Verification
typecheck, build and pint clean; 96 tests / 1828 assertions with
REQUIRE_SSR=1. Rendered HTML checked for the objection strip, the inline AIanswer, four questions left in the FAQ block, fourteen on
/faq, oneh1onboth, and the download buttons still rendering.