Skip to content

Sell the plain-language prompt and cross-model quality on /why-webjs #1201

Description

@vivek7405

Problem

The /why-webjs pitch page argues that an AI agent can read the whole framework, so no training data and no single blessed model are required. That argument is currently pitched entirely at the model side: the agent reads the source, so any model works.

It never states the consequence that matters most to the person typing the prompt. Someone with no technical background can write a plain-language request ("build me a page where customers can book a table") and still get back correct routing, a real database schema, server actions on the right side of the server boundary, progressive enhancement, and a coherent design system. That happens because the framework's conventions are file-and-folder shaped and the whole stack is readable, so the model is not being asked to invent an architecture from a vague prompt. It is being asked to follow one that is already on disk.

The page also stops short of connecting model-agnosticism to output quality. Today it says any model can work; it does not say the result stays consistently good whether the model is large or small. That is the claim a non-technical reader actually cares about, and it is the claim the existing four reason cards already support without ever saying out loud.

Design / approach

Add one new <section> to app/why-webjs/page.ts, placed between the "Four reasons the loop just works" bento grid and the existing "Experiment with any model, freely" section, then fold the quality-consistency point into that following section's prose so the two read as one argument rather than two overlapping ones.

The new section makes two linked points:

  1. A simple prompt is enough. Non-technical phrasing still lands on the right architecture, because the conventions are structural (the app/ file router, *.server.ts as the one server boundary, components as custom elements, the ActionResult envelope) rather than something the model has to reconstruct from taste. The agent is filling in a shape, not inventing one.
  2. The output quality does not swing with the model. Large or small, the model is reading the same source and following the same conventions, so the architecture, the code, and the design system come out consistent.

Prose rules that govern this copy, both already recorded as standing feedback:

  • Do NOT undermine WebJs (no "even a small model can sort of manage"). Frame the small-model case as a genuine capability, not a concession.
  • Do NOT frame Drizzle / Tailwind / SQLite as what WebJs is. They are scaffold defaults. If the copy mentions a database or styling, say the scaffold wires them, not that the framework requires them.
  • Honest claim boundary: the claim is that the architecture and conventions hold across models, NOT that any model produces identical code or that WebJs removes the need to review output. Do not overclaim.

Consider whether the same point deserves a shorter echo on /what-is-webjs, whose CAPABILITIES array (app/what-is-webjs/page.ts L161) is the natural place for a one-line version. That page targets the "what is webjs" search query, so keep it to a single capability entry there rather than a second full section, and make sure the two pages do not chase the same phrasing verbatim (the site's own anti-cannibalization rule in website/AGENTS.md).

The home page (app/page.ts) is deliberately NOT in scope: #1087 already reworked its lead around the model-agnostic benefit, and adding a third telling of the same story there is the cannibalization the site's SEO conventions warn about.

Implementation notes (for the implementing agent)

Where to edit

  • website/app/why-webjs/page.ts (198 lines) is the primary file.
    • REASONS array at L56 to L73 holds the four bento cards. The new section goes AFTER the section that renders them (the <section> closing at L167) and BEFORE the "Experiment with any model, freely" section at L169.
    • Shared class strings at L48 to L52 (WIN, WINBAR, WINNAME, DOTS, CARD) are copied from app/page.ts on purpose, per the file's own header comment, so reuse them rather than writing new class strings. Section heading pattern to match: class="font-display font-bold text-h2 leading-[1.12] tracking-[-0.03em] my-3 text-balance" wrapped in <div class="max-w-3xl mx-auto ... text-center"> inside <div class="max-w-6xl mx-auto px-6">.
    • generateMetadata() at L22 to L44 owns the page description. If the new section changes what the page is fundamentally about, the description should reflect it; if it is an elaboration of the existing argument, leave the metadata alone (the SSR test pins title/og/twitter self-consistency and will fail on a half-update).
    • The hero lede at L83 to L90 already runs long. Do not extend it; put the new argument in the new section.
  • website/app/what-is-webjs/page.ts if the echo is included: CAPABILITIES array at L161, rendered by the "What WebJs does for you" section at L275. H2 (L156) and PROSE (L157) constants exist there; use them. That page also carries a FAQ array at L52 that feeds FAQPage JSON-LD, and per website/AGENTS.md the FAQ must be BOTH visible and in the schema, so if a FAQ entry is added it has to render too (the existing code already does both, just do not add to only one).

Landmines / gotchas

  • Invariant 11 (prose punctuation), hook-enforced. .claude/hooks/block-prose-punctuation.sh BLOCKS the write, so a violation is not a review nit, it is a failed edit. No em-dashes, no space-surrounded hyphen or semicolon used as a pause between words, no colon-then-prose after a code-shaped left-hand side. And WebJs is capitalized wherever it names the project in prose; lowercase webjs only as a literal code token. The hook scans NEW content only.
  • Invariant 9: no backtick characters inside an html\...`` body, including inside comments. This page is one large template literal, so a stray backtick in new copy 500s in prod. The SSR test exists partly to catch this.
  • The page is pure marketing markup with no components of its own (stated in test/ssr/why-webjs-ssr.test.ts L4). Keep it that way: a page never hydrates, so adding an interactive widget here means adding a real custom element, which is out of scope for a copy change.
  • /why-webjs is referenced from app/llms.txt/route.ts L77 as "the case for the architecture, and who it is not for", from lib/ui/site-footer.ts, and from app/sitemap.ts. A copy-only change needs no edit to those, but if the page's framing shifts materially, the llms.txt one-liner should track it.
  • #1094 renamed /why to /why-webjs and polished /what-is-webjs; #1087 led the OG cards and home page with the model-agnostic benefit. Read both before writing so the new copy extends that line rather than restating it.

Invariants to respect

  • Framework root AGENTS.md invariant 11 (prose punctuation and brand casing) and invariant 9 (no backticks in html bodies), as above.
  • website/AGENTS.md: light DOM, Tailwind utilities, @theme tokens from the root layout; each section is its own <section> wrapper for predictable scroll anchors; do not let two pages chase the same exact keyword.
  • Standing copy rules: do not undermine WebJs in marketing prose, and do not frame the scaffold's defaults (Drizzle, Tailwind, SQLite) as framework lock-in.

Tests + doc surfaces

  • website/test/ssr/why-webjs-ssr.test.ts is the layer that covers this page. Add an assertion pinning a distinctive phrase from the new section (the existing tests use the out.includes(...) pattern against renderToString(Why()), see L16 to L25), and verify the counterfactual by removing the section and watching the assertion fail.
  • website/test/ssr/seo-ssr.test.ts and test/ssr/render-determinism.test.ts also touch this page; run the website test suite, not just the one file.
  • If /what-is-webjs is edited, its own SSR coverage in website/test/ssr/ applies the same way.
  • No framework packages/*/src change here, so the doc-sync gate does not apply. This is website copy only.

Acceptance criteria

  • /why-webjs carries a new section stating that a non-technical, plain-language prompt still produces correct architecture, code, and design, and that the result holds whether the model is large or small
  • The claim is framed as a capability, never as a concession, and never overclaims (it does not promise identical output across models or remove the need to review)
  • The new copy does not present Drizzle / Tailwind / SQLite as framework requirements
  • The section reuses the page's existing design-system class strings and section rhythm, so it is visually indistinguishable from the sections around it
  • /what-is-webjs either carries a single short echo of the point or deliberately does not, without duplicating /why-webjs phrasing verbatim
  • website/test/ssr/why-webjs-ssr.test.ts pins a distinctive phrase from the new section
  • A counterfactual proves the new assertion actually fires when the section is removed
  • The full website test suite passes, and webjs check reports no violations
  • The page renders correctly in the browser at both mobile and desktop widths, in light and dark theme

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

Status
In progress

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions