Files
coder/docs/.style
Nick Vigilante b95f2531b5 feat: populate docs prose style guide as a landing page plus subpages (#26632)
Replace the `docs/.style/style-guide.md` scaffold with the populated
prose style guide,
structured as a `README.md` landing page plus one subpage per topic so
GitHub auto-renders the landing when readers open the style-guide
folder.

## Layout

```text
docs/.style/
  style-guide/
    README.md                          (landing: intro, section list, editing conventions, Vale enforcement)
    audience-and-scope.md              (one audience, one outcome, declared up front; canonical personas)
    voice-and-tone.md
    word-choice.md
    accessibility-and-inclusion.md     (new)
    capitalization-and-punctuation.md
    formatting.md                      (text formatting + block elements + screenshots sparingly)
    numbers-units-and-dates.md
    editor-setup.md                    (placeholder)
```

Every repo reference to the old path is rewired to the new path:
`AGENTS.md` (and its `CLAUDE.md` / `.cursorrules` symlinks),
`.claude/docs/DOCS_STYLE_GUIDE.md`,
`docs/about/contributing/documentation.md`, `docs/.style/README.md`,
`docs/.style/styles/Coder/README.md`, and a comment in
`.github/workflows/ci.yaml`. The touched paragraph in each of those
files is reformatted to one sentence per line per the touch-paragraph
rule (refer to [Conventions the guide
dogfoods](#conventions-the-guide-dogfoods)).

## What each page covers

- **Audience and scope** (new): every page targets **one audience
working toward one outcome**; the **install-vs-deploy Coder example**
(workspace user vs platform engineer); pick one audience per page (write
two pages and cross-link rather than tagging sections); pick one outcome
per page (`Configure SSO with Okta` is one outcome, `Configure SSO` is
not); declare audience and scope up front (the H1 names the outcome; the
first paragraph names the audience); **canonical Coder personas**
inlined as four primary (Dave the Developer, Ada the Infrastructure
Admin, Perry the Platform Engineer, Steven the Sponsor) and six
secondary (Melissa the Machine Learner, Tommy the Tester, Caitlin the
Citizen Developer, Felipe the FinOps, Sergio the Security Officer, Tara
the Team Leader), each with a `Coder surface:` line covering the
relevant CLI/workspace/template/RBAC surfaces.
- **Voice and tone**: address the reader directly, avoid first-person
singular, reserve first-person plural for **Coder Technologies the
company** (with an explicit ban on `we` for the product itself and on
combined `you and the docs`), active voice, present tense with a
**conditional/predictive `will` exception** (`If you do X, Y will
happen`), **no sentence-ending prepositions** with a clunky-exception
note.
- **Word choice**: Coder product and feature names with the **Coder CLI
always in backticks (`coder`)** rule, brand names with a parallel
**Terraform CLI in backticks (`terraform`)** rule, **Dev Container**
terminology (proper-noun specification vs lowercase instance, parallel
to Coder / workspace), **phrasal verbs and their noun forms generalized
as a table** (set up/setup, log in/login, sign in/sign-in, log
out/logout, back up/backup, roll out/rollout, start up/startup, shut
down/shutdown, with the `Quickstart` exception), `refer to` / `check
out` / `visit` over `see`, `Learn more` versus `Next steps` with an
**ableism rationale** (`steps` as a physical-mobility metaphor),
`tutorial` versus `walkthrough` with an **ableism rationale**,
**`select` over `click`**, **`Don't assume simplicity or
difficulty`** (covers both `simple`/`easy` and `complex`/`non-trivial`),
**`Avoid weasel words`** (vague attributions in the Wikipedia sense like
`many believe`, `experts agree`, `studies show`), plain language for
product actions with an **industry-term exception scope** for the Linux
`kill` command, the `SIGKILL` signal, and the `disabled` config flag
state.
- **Accessibility and inclusion** (new): WCAG 2.1 Level AA as the
minimum target with AAA as a stretch goal; heading structure (one H1 per
page, no skipped levels, **substantive content between headings**);
inclusive pronouns; inclusive-language substitutions including a
**dedicated `sanity check` row** with `smoke testing` / `confidence
testing` / `acceptance testing` alternatives; descriptive link text; alt
text and decorative-image conventions; **plain English for international
readers** (no idioms; common Latin abbreviations `e.g.`, `i.e.`, `etc.`,
`vs.`, and `et al.` allowed, less common ones not); page descriptions in
`docs/manifest.json` (the docs site does not yet support YAML front
matter); reading level; color contrast deferred to the docs site theme.
- **Capitalization and punctuation**: sentence-case headings, no
gerund-leading headings with **documented exceptions** (`Pricing`,
`Billing`, `Logging`, `String formatting`, etc.), **trailing heading
punctuation in three tiers** (periods and exclamation marks forbidden at
error severity, question marks allowed sparingly at suggestion severity,
characters inside backticks exempt for both), no em or en-dashes with a
**corrected example** showing parenthetical em-dash use rather than
series-joining, Oxford comma, US-style quotation, semicolons sparingly,
rare exclamation marks, numeric ranges.
- **Formatting**: text formatting (bold for UI with **explicit
greater-than separator rule for navigation paths**, italics for
emphasis, code font for identifiers presented as a **bulleted list**)
and block elements (code blocks with language fences plus **link to the
Prism supported-languages reference**, callouts with tightened
scenarios, tabs with the actual `` syntax and a **macOS/Linux/Windows
example**, lists with a **five-item prose-list cap rule** and an
**explicit terminal-punctuation rule** (complete sentences end in
periods, phrases completing a lead-in paragraph end in periods,
single-word labels carry no terminal punctuation, no mixing styles in
one list), tables with a **narrow-table guideline** that reconsiders the
structure when many columns are needed, links including the rule that
**non-docs codebase links also use relative paths**, images,
**screenshots sparingly** with a maintenance-burden rationale and an
adapted quote from Lorna Jane Mitchell's `Short tech writing style
guide for developers`), with cross-references to the accessibility page
for link text and alt text.
- **Numbers, units, and dates**: digits everywhere preference,
non-breaking space between number and unit with **separate pre-render
(Markdown source) and post-render (visible output) demonstrations** plus
a **window-shrink tip** for confirming the rule visually, `Month Day,
Year` date format, 12-hour time with AM/PM, ordinals exception.
- **Editor setup**: placeholder.

## Conventions the guide dogfoods

- **One sentence per line**. Source lines follow a one-sentence-per-line
policy: each sentence sits on its own Markdown source line, sentences
are not split across lines, and lines do not wrap to a fixed column
width. The same convention applies corpus-wide through an **incremental
touch-paragraph rule**: when a contributor edits any line inside a
paragraph, the whole paragraph is reformatted to one sentence per line
as part of the same edit. Bullet items, numbered list entries, and
blockquote lines are each their own paragraph for the rule. Headings,
fenced code blocks, and tables are out of scope. `markdownlint`'s
`MD013` is already disabled, so the convention is editorial.
- **No navigational `see`**. Replaced with **refer to** (formal
default), **check out** (informal/tutorials), or **visit** (external
URLs). `See` is reserved for the observational meaning.
- **HTML entities for em-dashes inside demos**. The em-dash demo encodes
`—` / `–` so the source stays ASCII while the rendered output still
shows the character.
- **No semicolons in body prose**. Body prose prefers two sentences over
a semicolon. Semicolons survive only in heading and rule labels where
they act as separators.
- **Common Latin abbreviations allowed in own prose**. `e.g.`, `i.e.`,
`etc.`, `vs.`, and `et al.` (citation contexts) are fine. Less common
Latin abbreviations (`a priori`, `q.v.`, `viz.`, `n.b.`, `cf.`, `ibid.`)
are not. The rule covers punctuation too: prefer parentheses around
`e.g.` and `i.e.` clauses, one period when `etc.` ends a sentence, both
periods when `etc.` ends a parenthetical that ends a sentence.
- **No idioms or industry-jargon idioms**. `deep dive`, `paved path`,
etc. are rewritten in plain language.

## Rule conventions

Each rule pairs a rationale with **Do** / **Don't** blockquoted
examples and a parenthetical noting the Vale rule that enforces (or will
enforce) the policy. Documentation-only rules are explicitly labeled as
such. Substitution rules use tables.

## Out of scope

- Wiring any new Vale rule. Per-rule PRs land separately per the
rule-authoring doctrine in `docs/.style/README.md`.
- Editor setup page population.
- Redirecting `docs/about/contributing/documentation.md` to the
populated guide (needs a coordinated `coder.com` PR after merge).
- Trimming the `Writing Style` block in
`.claude/docs/DOCS_STYLE_GUIDE.md` and removing the `currently a
scaffold` framing in the agent docs.
- A separate demo PR for the callout types rendered against an existing
docs page.
- Sweeping navigational `see` out of other docs files. The new rule only
dogfoods on the style guide itself; a corpus-wide sweep is a separate
ticket.

## Validation

- `make fmt/markdown`: clean.
- `make lint/markdown`: 0 errors across 494 files.
- `./scripts/check_emdash.sh`: clean.
- Pre-commit-light: passes (fmt + lint + emdash + shellcheck + typos +
actionlint + migrations + helm).
- Dogfood scan: no first-person singular in own prose, no idioms, only
the five allowed Latin abbreviations in own prose, no `walkthrough` or
`Next steps` outside rule definitions and examples, no navigational
`see`, no `click` outside rule definitions and examples, no semicolons
in body prose.

<details>
<summary>CI flake note: <code>check-docs</code> (linkspector)</summary>

The `check-docs` job can fail intermittently on pre-existing external
links in `docs/about/contributing/documentation.md` (lines 29 and 30):
Merriam-Webster occasionally returns HTTP 403 to GitHub Actions runners
and Chicago Manual of Style can time out at 30s. Neither link is touched
by this PR. `docs/.style/` itself is in `.github/.linkspector.yml`
`excludedDirs`, and linkspector annotations confirm zero broken links
from the new pages.

</details>

Resolves DOCS-434.

---

*Filed via [Coder Agents](https://coder.com/docs/ai-coder/agents) on
Nick&#39;s behalf.*
2026-06-25 21:11:39 +00:00
..

docs/.style/

Contributor-facing style and content guidance for the Coder documentation. Nothing under this directory is published to coder.com/docs.

What lives here

Path Purpose
content-guidelines.md Canonical content rules: what belongs in docs/, what doesn't, why
style-guide.md Canonical prose style guide for docs/
styles/Coder/ Custom Vale rules specific to Coder (product voice, terms)

See content-guidelines.md for the canonical rules on what content belongs in docs/ and what should be routed elsewhere (blog, changelog, Support KB, etc.).

See style-guide.md for the prose style guide. The styles/Coder/ directory holds the custom Vale rules that enforce parts of the guide; Vale's StylesPath in the repo-root .vale.ini points at docs/.style/styles/.

Why a hidden directory

The leading dot mirrors the .github/, .vscode/, and .claude/ convention already used in this repo for tooling-internal directories. Vale and the structural Markdown linters still pick it up; coder.com's docs site does not.

How exclusion from coder.com works

coder.com/docs routes and search are manifest-driven:

Net result: not adding anything from docs/.style/ to docs/manifest.json gives us no route, no Algolia record, and no sidebar entry. Two defense-in-depth changes in .github/workflows/deploy-docs.yaml keep the deploy workflow from running on .style-only commits and exclude the directory from the surgical-reindex payload on mixed commits.

What still runs against this directory

  • make lint/markdown (markdownlint-cli2) processes every Markdown file here. The repo-root package.json invokes markdownlint-cli2 --fix $(find docs -name '*.md').
  • make fmt/markdown (markdown-table-formatter) reflows tables here for the same reason.
  • Vale lints the entire docs/**/*.md set, including docs/.style/style-guide/. Refer to the repo-root .vale.ini for the active configuration. Run make lint/prose locally to reproduce.

What does not run against this directory

  • linkspector: excluded via excludedDirs in .github/.linkspector.yml. External-link checking is overkill for contributor tooling.
  • The deploy-docs workflow: its paths: filter negates docs/.style/**, and the surgical-reindex git-diff invocation excludes the same path. See .github/workflows/deploy-docs.yaml.
  • The docs-preview workflow: its paths: filter negates docs/.style/**, so .style-only PRs produce no preview comment. The selection logic also skips .style files when picking the preview target on mixed PRs. See .github/workflows/docs-preview.yaml.

Editing the content guidelines

Open a PR against docs/.style/content-guidelines.md. The rules in that file apply to humans and AI-assisted workflows alike; when it conflicts with another style or contributing doc in the repo, it governs.

Editing the style guide

Open a PR against the appropriate subpage of docs/.style/style-guide/. Follow-up PRs add each rule and the matching style-guide section together.

Adding a Vale rule

Each rule in the repo-root .vale.ini ships clean: zero baseline findings against the current docs/ corpus. The PR that adds a rule is the rule's complete unit:

  1. Cleanup commit: fix every existing-content violation of the new rule so make lint/prose reports zero findings for it. The cleanup ships in the same PR as the enable, ordered first.
  2. Enable commit: add the rule to .vale.ini at its chosen severity, write a corresponding section under the matching subpage of docs/.style/style-guide/, and add the custom rule YAML under docs/.style/styles/Coder/ if applicable. The rule's message: field points at the relevant style-guide subpage anchor.

Severity is a deliberate per-rule choice:

  • error blocks merge. Use for hard policy where any violation is wrong: brand-name casing, first-person pronouns we ban outright, em-dash bans.
  • warning surfaces an annotation without failing CI. Use for strong guidance with legitimate human-judgment exceptions: terms that need context (disabled as a technical state vs. ableist usage), judgment-bound style preferences.
  • suggestion surfaces a notice annotation. Use for soft guidance where the right fix is contextual: noun-as-adjective patterns like desired state, wordiness, optional sentence reshaping.

The severity choice and the cleanup discipline are independent. A rule landing at warning or suggestion still ships with zero baseline findings; the rule's purpose is to catch new violations, not to surface a backlog of existing ones. A rule that surfaces a standing backlog teaches contributors to ignore the annotation channel, which erodes trust in CI regardless of the severity at which the noise arrives.

PR title: feat(docs/.style): enable <RuleName>.

False-positive policy: one confirmed false positive after enable, either refine the rule or revert. We do not maintain rules that occasionally cry wolf, regardless of severity.

If a policy is judgment-bound (passive voice, weasel words, sentence-case headings on a corpus with many proper nouns), write a Coder-authored rule with the precision the situation needs instead of accepting an imprecise third-party rule at any severity.

This applies equally to Coder-authored rules (under docs/.style/styles/Coder/) and third-party rules from Google, alex, and write-good. Third-party rules are not loaded by default. Each returns through the same per-rule PR pattern after its corpus is clean.