Skip to content

docs: Rewrite documentation to follow Vercel's writing guidelines #419

Description

@wasimxyz

Summary

The documentation is difficult to read. Just for example, the App Model page breaks Vercel's own writing guidelines in many places, and it breaks plain-language rules too. This issue asks for a full rewrite of all documentation pages using the Vercel writing guidelines as the standard.

Vercel writing guidelines violations

Em dashes used as punctuation. The page uses em dashes about 12 times to join clauses. The guidelines ban em dashes as punctuation. Use colons, commas, or periods instead. Examples:

  • "compiled to native code at build time — TypeScript Cores covers that tier in depth"
  • "the rest of this page — wiring, identity, hot reload — applies to both"
  • "Your code never handles a raw event — input lands on a widget"
  • "A zero-config app never writes this — the build graph generates it"

Spec-sheet voice in the intro. The four-part list reads like a datasheet. The guidelines flag the "is a…" pattern. Rewrite each line as what the part does, not what it is:

  • "Model — a plain data structure holding all app state"
  • "Msg — a tagged union of everything that can happen"
  • "View — a Native markup file that derives the UI from the model"

Metaphor verbs instead of the literal step. The guidelines say to name the action, not reach for cadence. The page uses:

  • "input lands on a widget" — input does not land; it goes to a widget
  • "neither ever rides the stack" — use "neither is stored on the stack"
  • "app_state.markup_diagnostic carries line, column, and message" — use "stores"
  • "they double as the blueprint for porting a core to Zig by hand" — cut the metaphor

Vague quantifiers. The guidelines say to give the figure and cite it, not use vague qualifiers:

  • "within about two seconds" — give the measured number
  • "the multi-MB app struct" — give the size
  • "Rebuilds are cheap and safe by design" — give a concrete claim or cut
  • "first-class by choice" — cut

Cold-open paragraphs. Several sections open with a sentence that works as a standalone heading, with no antecedent. The guidelines say to carry the prior subject forward:

  • "The source wins."
  • "Errors degrade, they never crash."
  • "Markup can never mutate state."

Stop-start fragments. "Errors degrade, they never crash." splits one idea into choppy fragments. Merge into one sentence.

Long sentences. The guidelines target under 20 words. Several sentences run 30 to 55 words:

  • The "By default the core is TypeScript…" sentence is about 55 words.
  • The "This is the pattern for any UI that mixes…" sentence is about 45 words.
  • The keyed/unkeyed identity sentence is about 40 words.

Headings. The guidelines say page headings should be sentence case and user-shaped, and subheadings should be descriptive, not cute or generic:

  • "App Model" is feature-shaped (the engineer's name), not a user question.
  • "The loop in full" is cute, not descriptive.
  • "Wiring" is a single generic word.
  • "Side effects" is generic.
  • "Dropping down" is cute.

Suggested rewrites:

  • "App Model" → "How a Native SDK app is structured"
  • "The loop in full" → "A minimal counter example"
  • "Wiring" → "Wiring the loop to the runtime"
  • "Side effects" → "Side effects and the effects channel"
  • "Dropping down" → "Using the lower-level App and Runtime"

Jargon used before being spelled out. The guidelines say to spell out acronyms and define terms on first use:

  • "GPU" is not spelled out.
  • "GUI" is not spelled out.
  • "comptime" is a Zig keyword used with no explanation.
  • "closed grammar" is undefined.
  • "goldens" is nickname jargon for saved reference images.

Missing TL;DR. The page opens with a list of the four parts, not a one-paragraph statement of what the page covers. The guidelines say every page opens with a one-paragraph TL;DR.

Broken inline code. In the "Rebuilds and widget identity" section, there is an empty inline code reference: "so an that inserts or removes". A widget name appears to have failed to render.

Code blocks. The .native markup code block has no language tag. The guidelines say all code blocks need a language tag for syntax highlighting.

Plain-language violations (summary)

A second review applied a plain-language standard: no jargon, no forced metaphors, lead with the answer, flows as lists. The page breaks these rules too.

Invented jargon with no everyday explanation. These terms are used with no plain definition:

  • "tagged union" — a value that can be one of several fixed forms, each labeled
  • "pure update" — a function that does not change anything outside its inputs
  • "the arm's kind" — one branch of a switch statement
  • "bounded error ring" — a fixed-size list of recent errors
  • "controlled patterns echo runtime-applied values back through the model" — the model holds the value the runtime set, so the next rebuild uses it

Forced metaphors. Machines do things that only people or physical objects do:

  • "input lands on a widget"
  • "List items carry key"
  • "engine-owned state like carets and scroll can hop"
  • "the model asserts a different value"
  • "the markup keeps everything it can"
  • "boot-time work goes in .init_fx"

Slogans and catchy labels. These read as taglines, not sentences:

  • "The source wins."
  • "Errors degrade, they never crash."
  • "Rebuilds are cheap and safe by design"
  • "first-class by choice"

Opens with what something is not. State the positive instead:

  • "Markup can never mutate state." → "Markup only reads the model."
  • "Your code never handles a raw event" → "The runtime handles raw events for you."

Flows crammed into one sentence. The core loop is described as one long sentence with five actions joined by commas. It should be a numbered list with one sentence per step:

  1. Input goes to a widget.
  2. The widget sends its bound message to update.
  3. update returns a new model.
  4. The view rebuilds from the new model.
  5. The engine repaints the changed parts.

The side-effects section has the same problem.

Dense shorthand. These lines are short but need decoding:

  • "Widget identity is structural."
  • "Unkeyed same-kind siblings take positional identity (sibling index)"
  • "re-disambiguates the trailing ones"
  • "compile the runtime engine out entirely"

Names used with no plain explanation. These names appear with no everyday description of what they do:

  • Msg
  • Cmd
  • Sub
  • UiApp
  • scene
  • fx (in update_fx and init_fx, short for "effects", never stated)

Synonym rotation. The page uses different words for the same thing:

  • "the runtime" and "the engine" for the same component
  • "markup", "view", and "markup fragments" for the same .native files

Suggested fix

Rewrite the page using the Vercel writing guidelines as the standard. The guidelines are a checklist that covers voice, tone, structure, headings, code, and plain language. Applying them would resolve most of the issues above in one pass.

Sources

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions