diff --git a/.claude/docs/DOCS_STYLE_GUIDE.md b/.claude/docs/DOCS_STYLE_GUIDE.md index e5c7a60b301..ac3e6496072 100644 --- a/.claude/docs/DOCS_STYLE_GUIDE.md +++ b/.claude/docs/DOCS_STYLE_GUIDE.md @@ -8,12 +8,9 @@ This guide documents structure, research, and content patterns for documentation > Read that first. When this style guide conflicts with the content > guidelines, the content guidelines govern. > -> **For prose rules**, the canonical Coder documentation style guide lives -> at [`docs/.style/style-guide.md`](../../docs/.style/style-guide.md) and -> will be enforced by the Vale rules under `docs/.style/styles/Coder/`. -> That guide is currently a scaffold; continue using the **Writing Style** -> section below until it is populated. This file also remains authoritative -> for structure, research, and content patterns. +> **For prose rules**, refer to the canonical Coder documentation style guide at [`docs/.style/style-guide/`](../../docs/.style/style-guide/README.md). +> Vale rules under `docs/.style/styles/Coder/` enforce those rules incrementally as each rule lands. +> This file remains authoritative for structure, research, and content patterns. See [CONTRIBUTING.md](../../docs/about/contributing/CONTRIBUTING.md) for general contribution guidelines. diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 321c647bdf6..ad15f5ddbbd 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -183,7 +183,7 @@ jobs: # `**.md` (not `docs/**.md`) because the action's globber collapses a # `**` adjacent to `.md` to a single path segment, so `docs/**.md` # only matches top-level docs/*.md and misses nested pages such as - # docs/.style/style-guide.md. The prose step below re-filters to + # docs/.style/style-guide/README.md. The prose step below re-filters to # docs/ paths. # Cache split into restore + conditional save to avoid letting PR # runs populate a cache that other branches restore from (the diff --git a/AGENTS.md b/AGENTS.md index 7c93c4e696a..988a81dcdd9 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -12,7 +12,8 @@ Rule #1: If you want exception to ANY rule, YOU MUST STOP and get explicit permi - Docs content scope: Use [Coder Docs Content Guidelines](docs/.style/content-guidelines.md) to decide whether a piece of content belongs in `docs/` at all. The Documentation Style Guide above covers prose and formatting; the content guidelines govern scope and routing and supersede the style guide on conflicts. - Compatibility: `.agents/docs` symlinks to `.claude/docs` for agent runtimes that look there. - Frontend: Read [Frontend Development Guidelines](site/AGENTS.md) before changing anything under `site/`. -- Docs prose: When editing anything under `docs/`, see the prose style guide at [`docs/.style/style-guide.md`](docs/.style/style-guide.md). It is currently a scaffold; until it is populated, use the **Writing Style** section in [`.claude/docs/DOCS_STYLE_GUIDE.md`](.claude/docs/DOCS_STYLE_GUIDE.md). That file also covers structure, research, and content patterns. +- Docs prose: When editing anything under `docs/`, refer to the prose style guide at [`docs/.style/style-guide/`](docs/.style/style-guide/README.md). + For supporting agent-specific guidance, refer to [`.claude/docs/DOCS_STYLE_GUIDE.md`](.claude/docs/DOCS_STYLE_GUIDE.md), which covers structure, research, and content patterns. ## Foundational rules diff --git a/docs/.style/README.md b/docs/.style/README.md index db03fefec44..e9649ff9f83 100644 --- a/docs/.style/README.md +++ b/docs/.style/README.md @@ -56,9 +56,9 @@ directory from the surgical-reindex payload on mixed commits. `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.md`. See the repo-root `.vale.ini` for the - active configuration; run `make lint/prose` locally to reproduce. +- 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 @@ -80,8 +80,8 @@ with another style or contributing doc in the repo, it governs. ## Editing the style guide -Open a PR against `docs/.style/style-guide.md`. Follow-up PRs add each -rule and the matching style-guide section together. +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 @@ -92,12 +92,8 @@ 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 - `docs/.style/style-guide.md`, and add the custom rule YAML under - `docs/.style/styles/Coder/` if applicable. - The rule's `message:` field points at the relevant `style-guide.md` - anchor. +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: diff --git a/docs/.style/style-guide.md b/docs/.style/style-guide.md deleted file mode 100644 index 1065287a868..00000000000 --- a/docs/.style/style-guide.md +++ /dev/null @@ -1,104 +0,0 @@ -# Coder documentation style guide - -This is the canonical style guide for the Coder documentation. It is the -source of truth that the Vale rules in `docs/.style/styles/Coder/` enforce. - -Status: scaffold. Sections below are populated by follow-up PRs; this -page starts as a table of contents and grows as those PRs land. - -## How to use this guide - -This page is a scaffold while follow-up PRs land. Sections marked "To be -filled in" are placeholders. For anything not yet covered, see the -public summary at -[`docs/about/contributing/documentation.md`](../about/contributing/documentation.md). - -- **Contributors**: read the section that matches what you are writing. - Each rule notes the Vale rule ID, if any, so you can reproduce the - warning locally. -- **Reviewers**: cite the section in a review comment. Reviews are easier - when the guidance is in one place. -- **AI agents**: read this page in full before editing anything under - `docs/`. The Coder Agents and Claude Code guides - ([`AGENTS.md`](../../AGENTS.md), - [`.claude/docs/DOCS_STYLE_GUIDE.md`](../../.claude/docs/DOCS_STYLE_GUIDE.md)) - link here. - -## Voice and tone - -To be filled in by follow-up PRs. Planned coverage: - -- Active voice -- Second person -- Plural nouns and pronouns where number is uncertain -- Product voice (`stop` over `kill`, `turn off` over `disable` in - user-facing copy) -- Limiting "we" - -## Word choice - -To be filled in by follow-up PRs. Planned coverage: - -- Inclusive-language substitutions -- HashiCorp casing -- Dev Container terminology -- "Setup" vs "set up" and Quickstart casing -- "Next steps" vs "Learn more" -- Weasel words - -## Capitalization and punctuation - -To be filled in by follow-up PRs. Planned coverage: - -- Sentence case in titles and headings -- General capitalization policy -- Em-dash and en-dash ban (use comma, semicolon, or period) - -## Formatting - -To be filled in by follow-up PRs. Planned coverage: - -- Bold for UI elements -- Italics for parameter names and version variables -- Code font for user input, command-line utility names, filenames, - environment variables, HTTP verbs and status codes, placeholder - variables -- Code blocks with explicit language fences - -## Vale enforcement - -The repo-root `.vale.ini` configures Vale to read styles from -`docs/.style/styles/`. The starter configuration combines: - -- Google's developer-docs base style -- A curated subset of `alex` (inclusive-language) -- A curated subset of `write-good` (wordiness) -- Coder-specific custom rules in `docs/.style/styles/Coder/` - -The rationale for the cherry-picked base styles and the severity -policy lives in `.vale.ini`'s inline comments. Run `make lint/prose` -to reproduce the baseline locally. - -## Editor setup - -To be filled in by a follow-up PR. Will cover VS Code, Cursor, -JetBrains, and Neovim. - -## Relationship to `docs/about/contributing/documentation.md` - -A public-facing prose summary lives today at -[`docs/about/contributing/documentation.md`](../about/contributing/documentation.md). -A follow-up PR will redirect that page to this guide; until then, -follow the public summary for anything the scaffolded sections above do -not yet cover. New prose rules land here; the public page is frozen -pending the redirect. - -## Third-party references - -When this guide does not cover something, consult: - -| Type of guidance | Reference | -|---------------------|-----------------------------------------------------------------------------------------| -| Spelling | [Merriam-Webster](https://www.merriam-webster.com/) | -| Style, nontechnical | [The Chicago Manual of Style](https://www.chicagomanualofstyle.org/home.html) | -| Style, technical | [Microsoft Writing Style Guide](https://learn.microsoft.com/en-us/style-guide/welcome/) | diff --git a/docs/.style/style-guide/README.md b/docs/.style/style-guide/README.md new file mode 100644 index 00000000000..10ba7c1875d --- /dev/null +++ b/docs/.style/style-guide/README.md @@ -0,0 +1,109 @@ +# Coder documentation style guide + +This is the canonical prose style guide for the Coder documentation. +It tells you *how* to write the words that go in the docs. +For decisions about what belongs in the docs and what does not, refer to [`content-guidelines.md`](../content-guidelines.md). + +Each rule on the pages below is a policy decision the Coder docs team has made. +Where a Vale rule already enforces the policy, the rule name is listed in a parenthetical so you can reproduce the warning locally. +Where the rule is documentation-only, the parenthetical says so. +The doctrine for adding Vale rules lives in [`README.md`](../README.md). + +## How to use this guide + +- **Contributors**: read the section that matches what you are writing. + Each rule includes a brief rationale and **Do** / **Don't** examples. +- **Reviewers**: cite the section in a review comment. + Reviews are easier when the guidance lives in one place. +- **AI agents**: read every section before editing anything under `docs/`. + The Coder Agents and Claude Code guides ([`AGENTS.md`](../../../AGENTS.md), [`.claude/docs/DOCS_STYLE_GUIDE.md`](../../../.claude/docs/DOCS_STYLE_GUIDE.md)) link here. + +## Sections + +| Page | Covers | +|-----------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| [Audience and scope](./audience-and-scope.md) | One audience per page; one outcome per page; declare both up front; Coder personas | +| [Voice and tone](./voice-and-tone.md) | Second person; no first-person singular; "we" as the company, not the software; active voice; present tense | +| [Word choice](./word-choice.md) | Canonical brand and product names; "refer to" over "see"; "select" over "click"; weasel words; plain English for product actions; keep internal-only references out of published docs | +| [Accessibility and inclusion](./accessibility-and-inclusion.md) | WCAG target; inclusive pronouns and substitutions; descriptive link text; alt text; page descriptions; heading structure; reading level | +| [Capitalization and punctuation](./capitalization-and-punctuation.md) | Sentence-case headings; no gerund leads; no em-dashes; commas; US-style quotation | +| [Formatting](./formatting.md) | Bold for UI; italics for emphasis; code font for identifiers; language fences on code blocks; callouts; tabs; lists; tables; links; images; screenshots sparingly | +| [Numbers, units, and dates](./numbers-units-and-dates.md) | Digits everywhere; non-breaking space between number and unit; `Month Day, Year` dates; 12-hour time with AM/PM | +| [Editor setup](./editor-setup.md) | Vale editor integration for VS Code, Cursor, JetBrains, and Neovim (placeholder) | + +## Conventions for editing Coder docs + +These conventions apply to every Markdown file under `docs/`. +The style guide subpages dogfood them so contributors can see the rules in action. + +### One sentence per line + +Source lines in Coder documentation 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 rendered Markdown joins lines inside a paragraph back together, so the source line breaks do not appear in the rendered output. +Reviewers reading the diff do encounter them, and they make diffs land cleanly at the sentence level. + +`markdownlint`'s `MD013` (line length) is already disabled, so the convention is editorial. +Editors that auto-wrap on save should be configured to leave the source alone. + +#### Incremental adoption + +The Coder docs corpus predates this convention. +Much of the existing prose still wraps to a fixed column width or runs on a single long line, and some paragraphs on the other pages of this style guide still carry semantic line breaks (sembr) from earlier commits in this PR. +The convention is adopted incrementally. + +When a contributor edits any line inside a paragraph, the entire paragraph is reformatted to one sentence per line as part of the same edit. +The contributor does not reformat surrounding paragraphs they did not otherwise touch. + +For this rule, a bullet item, a numbered list entry, and a blockquote line are each their own paragraph. +Headings, fenced code blocks, and tables are out of scope: headings are single lines by convention, code blocks render their source verbatim, and table rows are governed by `markdown-table-formatter`. + +### The style guide does not use "see" for navigation + +The [Word choice page](./word-choice.md) bans "see" as a navigational verb across all docs. +The style guide itself follows the rule: "refer to" for formal cross-references, "check out" for informal pointers in tutorial-style passages, "visit" for external URLs. +Reserve "see" for the rare case where the prose describes what a reader observes in the product UI. + +## Vale enforcement + +The repo-root `.vale.ini` loads only the Coder rule package by default. +Third-party rules from Google, alex, and write-good are not enabled until a per-rule PR brings each back in. + +Each enabled rule lands via a dedicated PR that: + +1. Cleans the corpus to zero baseline findings. +2. Adds the rule line in `.vale.ini` at the rule author's chosen severity. +3. Adds the corresponding section to the appropriate subpage of this guide. + +Severity is a deliberate per-rule choice from the three-tier ladder: + +- `error` blocks merge in CI. + Use for hard policy where any violation is wrong. +- `warning` surfaces an annotation without failing CI. + Use for strong guidance with legitimate human-judgment exceptions. +- `suggestion` surfaces a `notice` annotation. + Use for soft guidance where the right fix is contextual. + +The full doctrine, including the false-positive policy, lives in [`README.md`](../README.md). +Run `make lint/prose` to reproduce the baseline locally. + +## Relationship to `docs/about/contributing/documentation.md` + +A public-facing prose summary lives today at [`docs/about/contributing/documentation.md`](../../about/contributing/documentation.md). +A follow-up PR will redirect that page to this guide. +Until then, follow the public summary for anything the subpages of this guide do not cover. +New prose rules land here. +The public page is frozen pending the redirect. + +## Third-party references + +When this guide does not cover something, consult: + +| Type of guidance | Reference | +|--------------------------|-----------------------------------------------------------------------------------------| +| Spelling | [Merriam-Webster](https://www.merriam-webster.com/) | +| Style, nontechnical | [The Chicago Manual of Style](https://www.chicagomanualofstyle.org/home.html) | +| Style, technical | [Microsoft Writing Style Guide](https://learn.microsoft.com/en-us/style-guide/welcome/) | +| Style, developer-focused | [Google developer documentation style guide](https://developers.google.com/style) | diff --git a/docs/.style/style-guide/accessibility-and-inclusion.md b/docs/.style/style-guide/accessibility-and-inclusion.md new file mode 100644 index 00000000000..ac5849ba8c8 --- /dev/null +++ b/docs/.style/style-guide/accessibility-and-inclusion.md @@ -0,0 +1,401 @@ +# Accessibility and inclusion + +The Coder documentation aims for [WCAG 2.1](https://www.w3.org/TR/WCAG21/) Level AA conformance as a minimum, with Level AAA as a stretch goal where it does not sacrifice clarity. +The rules on this page support that target. +They cover heading structure, inclusive language, link text, images, plain English for international readers, page descriptions, and reading level. + +> [!NOTE] Color contrast and other rendered-output a11y concerns belong to the docs site theme, not to prose conventions. +> The Coder docs team tracks color-contrast conformance separately. + +## Heading structure and placement + +Each page has exactly one H1. +The H1 is the page title and appears once at the top of the page. +Subsequent headings descend by one level at a time. +A page goes H1, then H2, then H3. +A page does not jump from H2 to H4. + +Each heading is followed by at least one paragraph (or other content block) before the next heading. +A bare H2 followed immediately by an H3 with no prose in between reads as a broken document outline, and SEO crawlers flag the pattern as a potential site error. +If a parent heading does not yet have introductory content, write a short paragraph that frames what the section covers before the subheadings. + +The rule is a [WCAG 2.1 Level A](https://www.w3.org/TR/WCAG21/#info-and-relationships) requirement: assistive technology relies on heading levels to convey document structure. +Skipping a level breaks the outline. + +**Do**: + +```markdown +# Configure your workspace + +This page walks through the configuration options exposed on a Coder workspace. +The sections below cover SSH access and environment variables. + +## Set up SSH access + +SSH access uses the agent that runs inside your workspace. +Two client setups are documented below. + +### Connect through JetBrains Toolbox + +Install the Coder plugin in JetBrains Toolbox, +then connect to your workspace by name. + +### Connect through VS Code Remote SSH + +The Coder VS Code extension wraps the standard Remote SSH client and configures it automatically. + +## Configure environment variables + +Environment variables persist across workspace restarts. +Define them in the template or in the workspace's parameters. +``` + +**Don't**: + +```markdown +# Configure your workspace + +# Configure your environment + +#### Connect through JetBrains Toolbox + +Install the Coder plugin in JetBrains Toolbox, +then connect to your workspace by name. +``` + +The second H1 creates two competing page titles. +The H1 to H4 jump skips H2 and H3. +Even if the levels were correct, the first H1 has no paragraph before the next heading, which also fails the rule. + +*Enforced by `markdownlint` rules `MD001` (heading-increment) and `MD025` (single-h1). +The "content between headings" rule is documentation-only.* + +## Inclusive pronouns + +Use the singular `they` when the subject's gender is unknown or irrelevant. +Avoid `he or she`, `(s)he`, and similar constructions. + +**Do**: + +> When a user opens a workspace, they connect to the agent over a Tailscale tunnel. + +**Don't**: + +> When a user opens a workspace, he or she connects to the agent over a Tailscale tunnel. + +*Enforced by `Google.Gender` and `Google.GenderBias`.* + +## Inclusive-language substitutions + +Use the industry-standard inclusive substitutions for terms that have transitioned across the broader developer-tooling ecosystem. + +| Do | Don't | +|-------------------------------------------------------|-----------------------------------------------| +| allowlist | whitelist | +| blocklist, denylist | blacklist | +| primary, main | master (for the primary branch or controller) | +| primary, hub, reference | master (general usage) | +| replica, secondary | slave | +| placeholder, sample, mock | dummy | +| smoke testing, confidence testing, acceptance testing | sanity check, sanity test | + +*Enforced by `Coder.InclusiveLanguage` (planned), with additional coverage from the curated `alex.*` lexicon.* + +## Descriptive link text + +Link text describes what the reader gets at the destination. +Generic phrases like "click here" and "this link" tell the reader nothing if they scan the link out of context. +Screen readers announce link text out of context too, which is the [WCAG 2.1 Level A](https://www.w3.org/TR/WCAG21/#link-purpose-in-context) requirement the rule supports. + +**Do**: + +> Refer to the [Coder CLI reference](../../reference/cli/index.md) for the full command list. + +**Don't**: + +> Refer to the Coder CLI reference [here](../../reference/cli/index.md). +> +> [Click here](../../reference/cli/index.md) for the full command list. + +*Enforced by `Coder.LinkText` (planned).* + +## Alt text for images + +Every image declares descriptive alt text. +The alt text describes what the image shows or what purpose it serves. +It is not a caption. +Captions go below the image in a `` tag. + +Aim for one or two sentences that convey the same information a sighted reader would extract from the image. +Lead with the subject, not "An image of" or "A screenshot showing". + +```markdown +![Template Insights dashboard with weekly active users and connection latency charts](../../images/admin/templates/template-insights.png) + +The Template Insights dashboard. Active users in the left panel; connection latency in the right panel. +``` + +For complex diagrams that cannot be summarized in alt text, provide a longer description in the body of the page and reference it from the alt text. + +*Enforced by `markdownlint` rule `MD045` for the alt-text-required requirement.* + +## Decorative images + +Mark images that carry no information beyond visual decoration with empty alt text. +Empty alt text tells the screen reader to skip the image rather than announce a meaningless filename. + +```markdown +![](../../images/decorative/divider.png) +``` + +Decorative images are rare in the Coder docs. +Most images shown to a reader are screenshots or diagrams that convey information, and those images need descriptive alt text. +When in doubt, write descriptive alt text. + +*Documentation-only. +No Vale rule.* + +## Plain English for international readers + +Keep prose accessible to readers whose first language is not English. +Two patterns add friction for non-native speakers without adding meaning, so the guide bans them: + +### Avoid idioms and figurative language + +Idioms (`under the weather`, `ballpark figure`, `get the ball rolling`, `at the eleventh hour`) and figurative language (`unleash`, `supercharge`, `dive in`, `out of the box`) rely on cultural context that does not translate. +They also rarely add precision. +Replace them with the literal meaning. + +**Do**: + +> The estimated startup time is between 30 and 60 seconds. +> +> Run `coder login` to begin. +> +> Coder ships with a default template. + +**Don't**: + +> The ballpark figure for startup time is 30 to 60 seconds. +> +> Run `coder login` to get the ball rolling. +> +> Coder ships with a default template out of the box. + +*Documentation-only. +Planned Vale rule `Coder.Idioms`.* + +### Latin abbreviations + +The following Latin abbreviations are fine in Coder docs. +Use them when they fit the sentence; the English equivalent is also fine. + +| Abbreviation | Meaning | Notes | +|--------------|------------------------------------------------|--------------------------------------------------------------------------------| +| `e.g.` | for example | Followed by a comma. Prefer parentheses around the clause, as described below. | +| `i.e.` | that is | Followed by a comma. Prefer parentheses around the clause, as described below. | +| `etc.` | and so on | Closes a list. The Oxford comma applies before it: `apples, oranges, etc.` | +| `vs.` | versus, against, as opposed to, in contrast to | No comma. Example: `coder server vs. coder agent`. | +| `et al.` | and others | Citation contexts only. Follow the citation style's punctuation rules. | + +**Prefer parentheses around `e.g.` and `i.e.` clauses.** The parentheses make the sentence structure obvious and avoid a cascade of commas around the abbreviation. + +**Do**: + +> Many compute platforms work (e.g., AWS, GCP, or a self-managed Kubernetes cluster). +> +> The agent exits when the workspace stops (i.e., when the build phase tears down). + +**Don't**: + +> Many compute platforms work, e.g., AWS, GCP, or a self-managed Kubernetes cluster. +> +> The agent exits when the workspace stops, i.e., when the build phase tears down. + +The **Don't** versions are grammatical, but the comma cascade makes the sentence structure harder to follow. + +**One period when `etc.` ends a sentence.** The period in `etc.` doubles as the sentence-ending period. + +**Do**: + +> The provisioner installs apples, oranges, etc. + +**Don't**: + +> The provisioner installs apples, oranges, etc.. + +When `etc.` ends a parenthetical at the end of a sentence, keep both periods. +The abbreviation's period closes `etc.`, the closing parenthesis follows, and the sentence-ending period falls outside the parenthesis. + +**Do**: + +> The provisioner handles produce (apples, oranges, etc.). + +The same rule applies if `e.g.` or `i.e.` ever sits at the end of a sentence, though that placement is unusual. + +**Citation form for `et al.`** In an author-date citation, place a comma between the author phrase and the year, and keep the abbreviation's period. + +**Do**: + +> The protocol is described by Smith et al., 2020. +> +> The protocol is described by Smith et al. (2020). + +**Less common Latin abbreviations are not allowed.** Latin abbreviations beyond the five in the table, such as `a priori`, `q.v.`, `viz.`, `n.b.`, `cf.`, and `ibid.`, are unfamiliar to many readers and easy to misuse. +Replace them with plain English. + +**Don't**: + +> The default configuration is acceptable a priori. +> +> Refer to the deployment guide, q.v. for benchmarks. + +
+Why these specific abbreviations are allowed + +Major plain-language guides such as the [Google developer documentation style guide](https://developers.google.com/style/abbreviations), the [Microsoft Writing Style Guide](https://learn.microsoft.com/en-us/style-guide/abbreviations/), the [18F Content Guide](https://content-guide.18f.gov/our-style/inclusive-language/), and the [Plain Language Action and Information Network (PLAIN) federal guidance](https://www.plainlanguage.gov/guidelines/words/use-simple-words-phrases/) recommend English equivalents for all Latin abbreviations. +The argument is that the abbreviations are unfamiliar to many readers and frequently misused (`i.e.` confused with `e.g.`). + +The Coder docs follow the spirit of that guidance for less common Latin but make an exception for `e.g.`, `i.e.`, `etc.`, `vs.`, and `et al.` These five are near-universal in industry technical writing; restricting them adds friction for writers without a clear payoff for readers familiar with the conventions of the genre. + +
+ +*Documentation-only. +No Vale rule.* + +## Page title and sidebar title + +A page's H1 and its sidebar title serve different jobs and may diverge. + +- The **H1** is the page's grammatical declaration of what the page does. + It works as the only line of text when the page is opened in isolation (Markdown source, RSS feed, mobile view that hides the sidebar, or a permalink shared in chat). + Refer to [Declare audience and scope up front](./audience-and-scope.md#declare-audience-and-scope-up-front) for how the H1 names the outcome. +- The **sidebar title** is a navigation label. + It fits the limited horizontal space of the sidebar and reads fast when the reader is scanning a tree of dozens of pages. + The Coder docs site reads the sidebar title from the `title` field in [`docs/manifest.json`](../../manifest.json). + +The two must each stand alone, but they do not need to be identical. +Breadcrumb depth gives one layer of context for free. +The sidebar title can drop redundancy that the parent breadcrumbs already imply. + +Worked example. +A page reachable through **Administration** > **Authentication** > **Google** has parent breadcrumbs that already say "Administration" and "Authentication". +The sidebar title can be `Google` alone, and the H1 can be `Configure Google authentication with Coder`. +Both labels stand alone in their own context. + +When the H1 and the sidebar title coincide (often the case for short-titled pages), that is fine. +When they diverge, the divergence is intentional and serves the reader. +The same pattern is common in mature docs sites. +AWS, Microsoft Learn, and GitHub Docs all pair task-focused H1s with shorter noun-focused sidebar titles. + +**Do**: + +| Sidebar title | H1 | +|---------------|------------------------------------------------| +| Google | Configure Google authentication with Coder | +| Helm chart | Deploy Coder on Kubernetes with the Helm chart | +| OIDC | Configure single sign-on with OIDC | + +**Don't**: + +| Sidebar title | H1 | +|--------------------------------------------|------------------------------------------------| +| Configure Google authentication with Coder | Configure Google authentication with Coder | +| Click here for Helm install | Deploy Coder on Kubernetes with the Helm chart | +| Page | Configure single sign-on with OIDC | + +The first **Don't** row uses the full H1 as the sidebar title. +The sidebar title is redundant with the parent breadcrumbs and crowds the navigation tree. +The second row has a sidebar title that does not stand alone. +The third row has a sidebar title that tells the reader nothing. + +*Documentation-only. +No Vale rule.* + +## Page descriptions + +Each page declares a description that appears in search engine results, in social-media previews, and in screen-reader page summaries. +The Coder docs site reads descriptions from [`docs/manifest.json`](../../manifest.json), not from YAML front matter inside the Markdown file. +The manifest maps each page to a `title` and a `description`: + +```json +{ + "title": "Configure your workspace", + "description": "Configure SSH access, environment variables, and autostart for a Coder workspace.", + "path": "./admin/workspaces/configure.md" +} +``` + +A good description: + +- States what the page covers in one sentence. +- Stays under roughly 160 characters so search engines do not truncate it. +- Avoids marketing language and superlatives. +- Reads as a complete sentence. + +**Do**: + +```json +"description": "Configure SSH access, environment variables, and autostart for a Coder workspace." +``` + +**Don't**: + +```json +"description": "Workspace configuration" +``` + +```json +"description": "The best, fastest, most reliable way to configure everything you need to know about Coder workspaces." +``` + +The short description tells the reader nothing. +The marketing description does not survive truncation and adds no information. + +If a page does not yet have a description in the manifest, add one in the same PR that touches the page. + +*Documentation-only. +No Vale rule.* + +## Reading level + +Aim for a Flesch-Kincaid grade level of 8 to 10 in body prose. +The target supports comprehension for non-native English readers, ESL audiences, and anyone skimming under time pressure. +The reading-level rule decomposes into prose rules covered elsewhere in this guide: + +- Short sentences. + Aim for 25 words or fewer. +- [Active voice by default](./voice-and-tone.md#active-voice-by-default). +- [Present tense by default](./voice-and-tone.md#present-tense-by-default). +- Common words. + Define jargon on first use. +- [Plain English for international readers](#plain-english-for-international-readers). +- [Plain language for product actions](./word-choice.md#stop-not-kill-turn-off-not-disable). +- [No weasel words](./word-choice.md#avoid-weasel-words). + +A reading-level rule is part of [WCAG 2.1 Level AAA](https://www.w3.org/TR/WCAG21/#reading-level) Success Criterion 3.1.5. +The criterion is satisfied either by writing at the lower-secondary reading level or by providing an alternative version. +Coder docs write at the target reading level directly. + +Editors that surface a grade-level score (Hemingway, Vale's `write-good.Reading`) are a useful spot check. +The grade level is not a hard ceiling. +A reference page that requires technical vocabulary will read higher than a tutorial, and that is correct. + +*Documentation-only. +No Vale rule wired.* + +## Color contrast + +The docs site theme controls color contrast, not the prose written on each page. +Tracked separately from this guide. +The target is WCAG 2.1 Level AA for normal text (contrast ratio 4.5:1) and Level AA for large text (3:1), with AAA (7:1 normal, 4.5:1 large) as the stretch goal. + +*Out of scope for this guide. +Tracked by the docs site theme.* + +## Related + +- [Style guide landing page](./README.md) +- [Voice and tone](./voice-and-tone.md) +- [Word choice](./word-choice.md) +- [Formatting](./formatting.md) diff --git a/docs/.style/style-guide/audience-and-scope.md b/docs/.style/style-guide/audience-and-scope.md new file mode 100644 index 00000000000..20970b96e10 --- /dev/null +++ b/docs/.style/style-guide/audience-and-scope.md @@ -0,0 +1,352 @@ +# Audience and scope + +Every page in the Coder documentation targets one audience working toward one outcome. +The audience determines vocabulary, depth, and the prior knowledge the page assumes. +The outcome determines what the page covers and where it stops. + +Pages that try to serve two audiences, or chain multiple unrelated outcomes, serve none of their readers well. +A reader who is one persona away from the page's target has to skip past content that does not apply to them, guess which sentences are for them, and trust the writer not to have buried a step they need inside a section labeled for someone else. + +The single canonical Coder example is **install Coder**. +An end user wants to connect their local editor to a Coder workspace and start coding. +A platform engineer wants to deploy the Coder control plane to their company's Kubernetes cluster. +Both groups search for "install Coder. +A page that tries to cover both forces the end user to read past Helm chart values, and forces the platform engineer to read past Visual Studio Code download links. +Two pages, one per audience and one per outcome, serve both groups better than one page that combines them. + +## Pick one audience per page + +Choose the audience before you choose the words. +The audience determines: + +- The product vocabulary the reader already knows (for example, whether `workspace` needs a definition). +- The infrastructure context the reader brings (for example, whether Kubernetes is assumed). +- The level of depth the reader expects (overview, how-to, reference, or in-depth tutorial). + +If a topic genuinely needs to serve two audiences, write two pages and cross-link them. +Resist the temptation to write one page with audience-tagged sections. +Section tags do not save readers from scanning content that does not apply to them. + +**Do**: + +```markdown +# Connect Visual Studio Code to your Coder workspace + +*Audience: a developer with an existing Coder workspace.* + +This page covers the Visual Studio Code IDE. +For Cursor, refer to [Cursor](./cursor.md). +For Windsurf, refer to [Windsurf](./windsurf.md). +``` + +**Don't**: + +```markdown +# Connect to your Coder workspace + +This page covers Visual Studio Code, Cursor, Windsurf, JetBrains, Vim, the web terminal, and SSH. +Operators provisioning the workspace template should refer to the section below on template configuration. +``` + +## Pick one outcome per page + +The outcome is the specific task, or the small set of related tasks, the page helps the reader accomplish. +A how-to page covers one task. +A tutorial covers one chained workflow. +A reference page covers one stable surface (one CLI command, one API endpoint, one schema). +An overview page introduces one concept. + +If the page has more than one outcome, split it. +"Configure SSO with Okta" is one outcome. +"Configure SSO" is not. +"Deploy Coder on AWS" is one outcome. +"Deploy Coder" is not. + +A page that helps the reader accomplish two unrelated outcomes hides each outcome from the readers who need the other. + +**Do**: + +```markdown +# Configure single sign-on with Okta + +This page walks through configuring OIDC single sign-on against an Okta tenant. +For Azure Active Directory, refer to [Configure SSO with Azure AD](./sso-azure-ad.md). +For Google Workspace, refer to [Configure SSO with Google Workspace](./sso-google.md). +``` + +**Don't**: + +```markdown +# Authentication + +This page covers OIDC providers (Okta, Azure AD, Google Workspace, generic OIDC), +SAML providers, GitHub OAuth, password authentication, and the API token model. +``` + +## Hub pages and category landing pages + +Some pages exist to orient the reader and route them to the child page that owns the actual content. +A hub page may have a broad title and a short body when its job is to direct the reader to a child page, not to teach. + +Hub pages are not an exemption from the audience and outcome rules. +The audience is the reader looking for the right child page. +The outcome is making the routing decision in three or four lines. + +A hub page is appropriate when: + +- The topic has several distinct sub-topics. +- Each sub-topic deserves its own page for scope reasons. +- A reader entering the section needs to choose between them. + +**Do**: + +```markdown +# Authentication + +This page is the entry point for configuring authentication in Coder. +Pick the provider that matches your identity source: + +- [OpenID Connect (OIDC)](./oidc.md), for Okta, Auth0, Azure AD, Google Workspace, and other OIDC providers. +- [SAML](./saml.md), for SAML 2.0 identity providers. +- [GitHub OAuth](./github-oauth.md), for GitHub-hosted teams. +- [Password authentication](./password.md), for self-hosted local accounts. +``` + +**Don't**: + +```markdown +# Authentication + +This page covers OIDC, SAML, GitHub OAuth, password authentication, and the API token model. + +## OIDC + +[300 lines of provider-specific configuration] + +## SAML + +[300 lines of provider-specific configuration] +``` + +The Don't example forces every reader to scan a wall of content for the section that applies to them. +The Do example routes them to the right page in four lines. + +A hub page does not need every link to be a direct child page in the file tree. +Cross-references to sibling sections of the docs are valid when that is where the reader's next step lives. + +## Declare audience and scope up front + +The first paragraph of the page names the audience and the outcome. +The reader should know within the first two or three sentences whether the page is for them and whether it covers their task. + +Conventions: + +- The H1 names the outcome. +- The first paragraph names the audience and confirms the outcome. +- The first paragraph also links to sibling pages for adjacent audiences or outcomes when those exist. + +Do not put a metadata line such as `*Audience: a developer.*` above the first paragraph. +The audience appears in the prose itself. +Do not use the [persona names](#personas-the-coder-docs-serve) inside the page body either. +Persona names are vocabulary for writers planning the page, not for readers reading it. +Name the audience by the role the reader recognizes from their own work (`developer`, `template author`, `Coder deployment administrator`, `organization owner`). + +**Do**: + +```markdown +# Connect Visual Studio Code to your Coder workspace + +This guide is for a developer with an existing Coder workspace. +It covers the Visual Studio Code IDE. +For Cursor, refer to [Cursor](./cursor.md). +For Windsurf, refer to [Windsurf](./windsurf.md). +``` + +**Don't**: + +```markdown +# Kubernetes + +Coder runs on Kubernetes. +This page covers many topics related to running Coder on Kubernetes. +``` + +The Don't title does not name an outcome. +The body does not name an audience. +If the page is a hub that routes the reader, use the pattern in [Hub pages and category landing pages](#hub-pages-and-category-landing-pages). +If the page teaches a single outcome, rename the title and rewrite the opening paragraph. + +### Gate privileged pages with a prerequisite callout + +Some pages walk through steps that only one role should run. +If a reader from the wrong role follows the steps, they may misconfigure the deployment, escalate their own permissions, or break something for everyone else. + +For pages of that kind, add an `IMPORTANT` callout at the top of the page that names the required role and tells the wrong-role reader who to ask. + +**Do**: + +```markdown +# Configure single sign-on with Okta + +This guide is for a Coder deployment administrator +who has access to both the Coder control plane and the Okta tenant. + +> [!IMPORTANT] +> You must be a Coder deployment administrator to complete this guide. +> If you are not a deployment administrator, +> ask your administrator to complete the steps for you. +``` + +The prerequisite callout uses the role the reader recognizes (`Coder deployment administrator`), not the writer-facing persona name (`Perry the Platform Engineer`). + +## Give the audience only what it needs + +Choosing the audience is also choosing what to leave out. +A page written for a known audience gives that reader what they need to reach the outcome, and nothing that belongs to a different audience. + +Knowing the audience means knowing what that audience can already do. +When the page assumes a reader who runs their own Coder deployment, that reader is their own administrator. +Do not hedge a step with "ask your administrator" or "if you have permission". +Those caveats are written for a reader this page does not target, and they make the real reader doubt whether the step is meant for them. + +Before you add a caveat, a permission note, or an "if you don't have access" aside, check it against the audience and the full context of the page: + +- Does the reader this page targets actually hit this limitation? +- Has the page already established that this reader has the access? +- Does the caveat help this reader, or only a reader who belongs on a different page? + +If the caveat serves a different audience, cut it, or move it to the page that audience reads. + +**Do** (a local-first Quickstart, where the reader started the server two pages earlier): + +> Configure a GitHub provider on your deployment, then create the workspace again. + +**Don't**: + +> Configure a GitHub provider on your deployment. +> If you are not a deployment administrator, ask your administrator to do this for you. + +The **Don't** aside is correct on an enterprise how-to page, where the reader may not own the deployment. +On a Quickstart that walked the same reader through starting the server, the reader already has the access, so the aside only adds doubt. + +A page may assume a persona, as long as it knows which persona it assumes and matches its depth and its caveats to what that persona can already do. +This is the complement of [gating privileged pages](#gate-privileged-pages-with-a-prerequisite-callout): add a prerequisite callout when the reader might be the wrong role, and cut wrong-role caveats when the audience is, by definition, the right role. + +## Personas the Coder docs serve + +When deciding which audience a page targets, match the reader to one of the canonical personas the Coder docs serve. +Each persona summary captures who the reader is, what they need from the docs, and the Coder surface they typically work with. + +If a page does not cleanly target one of these personas, revisit the scope. +A page without a clear persona is a page that serves no one well. + +The persona names are vocabulary for writers planning a page. +They do not appear in published prose. +Inside a page, name the audience by the role the reader recognizes from their own work (`developer`, `template author`, `Coder deployment administrator`). + +### Primary personas + +#### Perry the Platform Engineer + +Perry builds self-service platforms for development teams at a mid-to-large enterprise. +They own the templates, governance, and integrations that turn the Coder control plane Ada deploys into the default workflow developers actually use. +They need template authoring docs, RBAC and organization design, integration patterns, prebuilds, cost reporting, and policy-as-code. + +*Coder surface:* template authoring (Terraform, modules, prebuilds), RBAC, organizations and groups, policy and governance, integrations (CI/CD, observability, secrets, Git), audit logs. + +#### Dave the Developer + +Dave is a software engineer at a company that has adopted Coder. +They were not involved in the procurement decision and are expected to use the workspace the company provisioned for them. +They need day-to-day workspace usage docs: connecting from their preferred IDE, running CLI commands inside the workspace, port forwarding, SSH, and recovering when something breaks. + +*Coder surface:* workspaces, `coder` CLI, IDE integrations (VS Code, Cursor, JetBrains, Windsurf, Zed, Vim, Emacs), web terminal, dotfiles, SSH and port forwarding. + +#### Elliot the End User + +Elliot uses a Coder workspace day-to-day but is not a software engineer. +They may be a data scientist, product manager, customer success engineer, operations analyst, or another team member whose primary work happens inside a workspace the organization provisioned for them. +They need workspace-usage docs in plain language: connecting to the workspace, running the tools their team has standardized on, and recovering when something breaks. +They do not need template authoring or infrastructure context. + +*Coder surface:* workspaces, web terminal, IDE and notebook integrations (VS Code, Jupyter, RStudio), dotfiles, port forwarding, SSH, file uploads and downloads. + +> [!NOTE] Elliot is a stopgap umbrella persona for non-developer end users. +> The Coder docs team plans to revisit the persona model with product and design once the broader audience is mapped out. + +#### Ada the Infrastructure Admin + +Ada runs the underlying infrastructure that Coder deploys onto: Kubernetes clusters, cloud accounts, networking, storage, identity, and security policy. +They need deployment, operation, and recovery docs: install paths, upgrade and rollback, IAM and SSO, monitoring and alerting, capacity planning, and incident playbooks. +Their success metric is uptime, so they trust proven, well-documented configurations over bleeding-edge defaults. + +*Coder surface:* control plane install (Helm, Docker, VM, airgapped), database, networking and DERP, IAM and SSO/OIDC/SAML, telemetry and audit logs, backup and disaster recovery. + +#### Steven the Sponsor + +Steven is the CTO. +They approve the Coder purchase and stay close enough to the architecture to ask sharp questions, but they no longer write code. +They need overview pages that explain what Coder is, how it fits the existing stack, what it costs, and what its security and compliance posture looks like. + +*Coder surface:* architecture overviews, why-Coder framing, pricing and licensing, security and compliance summaries, release notes, success-metric dashboards. + +### Secondary personas + +#### Melissa the Machine Learner + +Melissa is an ML engineer who lives between Jupyter notebooks, Python, ML frameworks, and large datasets. +They need docs for GPU-enabled workspaces, persistent storage for datasets and model artifacts, ML-friendly templates, and integrations with experiment tracking and model registries. +They are comfortable in the CLI but expect the dev environment to be reproducible without per-experiment setup. + +*Coder surface:* GPU-enabled workspaces and templates, devcontainers, persistent storage, large-resource workspace configurations. + +#### Tommy the Tester + +Tommy is a QA engineer. +They need docs for reproducible test environments, CI integration patterns, and workspace configurations that let them run regression suites in isolation. +They value clear logs, traceable errors, and clean rollback paths over flashy features. + +*Coder surface:* workspaces for test environments, CI integrations, reproducible build patterns, workspace lifecycle (start, stop, rebuild). + +#### Caitlin the Citizen Developer + +Caitlin is non-technical (customer success) but uses agentic AI tools to make small product changes without writing code. +They need docs that explain Coder Tasks and the agent-driven flows in plain language, with no assumed dev-environment knowledge and no manual setup steps. +They avoid anything that requires opening a terminal or editing a config file. + +*Coder surface:* Coder Tasks, AI Bridge, prompt-driven workflows, web-based interfaces. + +#### Felipe the FinOps + +Felipe owns financial operations and tracks where the budget goes. +They need docs for usage and cost reporting, license counts, telemetry exports for finance dashboards, and per-team or per-template attribution. +They value precise, traceable numbers over feature descriptions. + +*Coder surface:* usage reports, audit logs, license management, billing and seat counts, telemetry exports. + +#### Sergio the Security Officer + +Sergio is the IT security officer at an organization with strict compliance requirements. +They need docs for the security architecture, identity and access control, secrets management, audit and compliance evidence (SOC 2, FedRAMP-style controls), data residency, and the supply chain story. +They are skeptical of new tools by default and want documented, auditable behavior. + +*Coder surface:* SSO and OIDC/SAML, RBAC, secrets management, audit logs, security architecture pages, compliance and trust-center content, allowlists and network policies. + +#### Tara the Team Leader + +Tara is an engineering manager or senior tech lead assigned the Group Admin role in Coder RBAC. +They need docs for team-scope administration: group memberships, group-owned secrets, group-scoped templates, and the audit log entries that explain who changed what. +They are not the platform owner. +They run their team inside the guardrails Perry or Ada set up. + +*Coder surface:* groups, group memberships, group-owned secrets, group-scoped templates, group audit logs. + +*Documentation-only. +No Vale rule.* + +## Related + +- [Voice and tone](./voice-and-tone.md) +- [Word choice](./word-choice.md) +- [Coder documentation content guidelines](../content-guidelines.md) +- [Style guide landing page](./README.md) diff --git a/docs/.style/style-guide/capitalization-and-punctuation.md b/docs/.style/style-guide/capitalization-and-punctuation.md new file mode 100644 index 00000000000..928638d444a --- /dev/null +++ b/docs/.style/style-guide/capitalization-and-punctuation.md @@ -0,0 +1,262 @@ +# Capitalization and punctuation + +Coder documentation uses sentence-case headings, the Oxford comma, US-style quotation, and no em-dashes or en-dashes in prose. +The rules on this page set those defaults. + +For heading structure (H1, H2, H3 placement and order), refer to [Accessibility and inclusion](./accessibility-and-inclusion.md#heading-structure-and-placement). + +## Sentence-case headings + +Capitalize the first word of a heading or page title, plus any proper nouns. +Everything else is lowercase. +This rule covers H1 through H6 and matches the way the heading reads aloud. + +**Do**: + +```markdown +# Configure your workspace +## Set up SSH access +### Connect through JetBrains Toolbox +``` + +**Don't**: + +```markdown +# Configure Your Workspace +## Set Up SSH Access +### Connect Through JetBrains Toolbox +``` + +*Enforced by `Google.Headings` (scope adjusted to skip CLI flag fragments and acronyms).* + +## No gerund-leading headings + +Do not start a heading with a present participle or gerund (an `-ing` word acting as a verb form). +The imperative form reads better for task headings. +The noun form reads better for concept headings. +Reserve gerund-leading headings for the rare case where neither alternative reads cleanly. + +**Do**: + +```markdown +## Install Coder +## Installation +## Configure your workspace +## Configuration reference +``` + +**Don't**: + +```markdown +## Installing Coder +## Configuring your workspace +``` + +### Exceptions + +Not every `-ing` word is a gerund-leading violation. +The rule targets verb forms (`installing`, `configuring`, `deploying`), not the following: + +- Nouns that happen to end in `-ing` and have no verb counterpart in the heading: `String formatting`, `Heading structure`. +- Compound nouns where the `-ing` word names a category or feature: `Pricing`, `Billing`, `Logging`, `Monitoring`, `Tracing`, `Networking`. +- Adjectives derived from verbs that modify the head noun: `Running workspaces`, `Pending invitations`. + +When the `-ing` word is the actual subject the section describes (a feature, a noun, or an attribute), the heading is fine. +When the `-ing` word is the verb form of a task the section walks through, rewrite as an imperative or as the noun form. + +*Enforced by `Coder.GerundHeading`, with the exceptions above scoped in the rule.* + +## No trailing punctuation in headings + +Headings are labels, not sentences. +Drop terminal periods and exclamation points. +Use trailing question marks sparingly, and only when the heading is an actual question that the section answers. + +The rule has scoped exceptions: + +- **Periods (`.`) and exclamation points (`!`) inside backticks** are allowed when the heading names a literal identifier that contains the character (a config file ending in `.yml`, a CLI flag like `--force!`, a programming macro like `panic!`). + The backticks tell the reader the punctuation is part of the identifier, not a sentence ender. +- **Question marks (`?`) inside backticks** are also allowed for the same reason (a query operator, a regex modifier, a UI element literally named `?`). + +**Do**: + +```markdown +## What is a workspace +## Quick reference +## What does the `panic!` macro do? +## Configure the `.vale.ini` file +``` + +**Don't**: + +```markdown +## What is a workspace? +## Quick reference! +## Workspaces are great! +## Configure your workspace. +``` + +The first **Don't** uses a trailing question mark for a label that is not actually a question. +Reword as a noun phrase ("What a workspace is") or drop the question mark. +The second and third are decorative. +The fourth treats the heading as a sentence. + +*Periods and exclamation points enforced by `Google.HeadingPunctuation` at `error` severity. +Question marks enforced by `Google.HeadingPunctuation` at `suggestion` severity. +Both ignore characters inside backticks.* + +## No em-dashes or en-dashes + +Em-dashes (—, U+2014), en-dashes (–, U+2013), and the ASCII `--` fallback are banned in prose. +Em-dashes typically set off a parenthetical aside or a break in thought. +Replace them with commas (for a tight aside), parentheses (for a clearly secondary aside), or a period and a new sentence (for a thought that stands on its own). + +**Do**: + +> The provisioner, which Coder builds on top of Terraform, creates the workspace. +> +> The provisioner (which Coder builds on top of Terraform) creates the workspace. +> +> The provisioner creates the workspace. +> Coder builds the provisioner on top of Terraform. + +**Don't**: + +> The provisioner—which Coder builds on top of Terraform—creates the workspace. +> +> The provisioner -- which Coder builds on top of Terraform -- creates the workspace. + +*Enforced by `scripts/check_emdash.sh` (existing CI script) and `Coder.EmDash` (planned).* + +## Commas + +### Comma after an introductory element + +Place a comma after an introductory word, phrase, or clause that comes before the main clause. +The comma marks where the introduction ends and the main clause begins. + +**Do**: + +> In this guide, you add Ruby as a parameter option. +> +> After you authorize Coder, the workspace starts. +> +> To pull the template, run `coder templates pull`. + +**Don't**: + +> In this guide you add Ruby as a parameter option. +> +> After you authorize Coder the workspace starts. + +*Documentation-only. +No Vale rule.* + +### No comma in a short compound predicate + +When `and`, `or`, or `but` joins two verbs that share one subject, do not put a comma before the conjunction. +The comma belongs there only when the conjunction joins two independent clauses, each with its own subject. + +**Do**: + +> Log in to Coder and select **Templates**. +> +> The agent opens a tunnel and forwards traffic over it. + +**Don't**: + +> Log in to Coder, and select **Templates**. +> +> The agent opens a tunnel, and forwards traffic over it. + +When each side of the conjunction is a full clause with its own subject, the comma returns: + +> Log in to Coder, and the dashboard opens. + +*Documentation-only. +No Vale rule.* + +### Oxford comma + +Use a comma before the conjunction in a list of three or more items. + +**Do**: + +> The provisioner builds, configures, and starts the workspace. + +**Don't**: + +> The provisioner builds, configures and starts the workspace. + +*Enforced by `Google.OxfordComma`.* + +## US-style quotation + +Place commas and periods inside closing quotation marks. +Semicolons and colons stay outside. +This is the United States convention and matches the dominant style of the surrounding tech-docs ecosystem. + +**Do**: + +> The error message reads, "workspace not found." + +**Don't**: + +> The error message reads, "workspace not found". + +*Enforced by `Google.Quotes`.* + +## Semicolons sparingly + +Prefer two sentences. +A semicolon joins two complete thoughts when they are tightly related and a period would lose the connection, but in technical prose two sentences almost always read more clearly. + +**Do**: + +> The provisioner uses Terraform. +> It reads the template files and creates the workspace. + +**Don't**: + +> The provisioner uses Terraform; it reads the template files and creates the workspace. + +*Documentation-only. +No Vale rule.* + +## Exclamation points rare in prose + +Exclamation points in body prose read as marketing copy or shouted emphasis. +Reserve them for code blocks, direct quotes from error messages, and rare moments where genuine emphasis serves the reader. + +**Do**: + +> Coder is ready to use. + +**Don't**: + +> Coder is ready to use! + +*Enforced by `Google.Exclamation`.* + +## Numeric ranges + +Spell out the joiner in prose. +Use `5 to 10` or `between 5 and 10`, not `5-10`. +In code blocks, terse reference material, and tables where space matters, the hyphenated form is acceptable. + +**Do**: + +> The agent retries 5 to 10 times before giving up. + +**Don't**: + +> The agent retries 5-10 times before giving up. + +*Enforced by `Google.Ranges`.* + +## Related + +- [Style guide landing page](./README.md) +- [Accessibility and inclusion](./accessibility-and-inclusion.md) +- [Formatting](./formatting.md) +- [Numbers, units, and dates](./numbers-units-and-dates.md) diff --git a/docs/.style/style-guide/editor-setup.md b/docs/.style/style-guide/editor-setup.md new file mode 100644 index 00000000000..959308e765b --- /dev/null +++ b/docs/.style/style-guide/editor-setup.md @@ -0,0 +1,11 @@ +# Editor setup + +A future revision of this guide will cover Vale editor integration for VS Code, Cursor, JetBrains, and Neovim, so contributors get inline feedback before commit instead of CI failure after push. + +This page is a placeholder. +The contents land in a follow-up PR. + +## Related + +- [Style guide landing page](./README.md) +- [Vale doctrine and tooling](../README.md) diff --git a/docs/.style/style-guide/formatting.md b/docs/.style/style-guide/formatting.md new file mode 100644 index 00000000000..e966aa99d18 --- /dev/null +++ b/docs/.style/style-guide/formatting.md @@ -0,0 +1,440 @@ +# Formatting + +Coder documentation uses bold for UI elements, italics for emphasis, and code font for identifiers. +Code blocks declare a language. +The rules on this page set those defaults and the conventions for callouts, tabs, lists, tables, links, and images. + +For descriptive link text and image alt text, refer to [Accessibility and inclusion](./accessibility-and-inclusion.md). +The accessibility-driven rules live on that page so heading structure, language, link text, and alt text stay together. + +## One sentence per line + +Write each sentence on its own Markdown source line. +Do not split a sentence across multiple lines, and do not wrap to a fixed column width. + +The payoff is cleaner diffs and easier authoring. +A sentence-level edit changes one line, not a paragraph reflow, so reviewers see exactly which sentence moved. +The rule is straightforward to apply for both humans and LLMs: end a sentence, start a new line. + +What counts as a single line: + +- One declarative, interrogative, or imperative sentence ending in a period, question mark, or exclamation point. +- The full text of a single bullet item, numbered list entry, or blockquote line. + +What does not get its own line: + +- Mid-sentence clauses or phrases. +- Source inside fenced code blocks, where the language's own conventions apply. +- Table rows, which are governed by `markdown-table-formatter`. + +**Do**: + +> The Coder agent connects to the workspace, opens a Tailscale tunnel, and forwards SSH and IDE traffic over the tunnel. + +**Don't** (mid-sentence clause breaks): + +> The Coder agent connects to the workspace, opens a Tailscale tunnel, and forwards SSH and IDE traffic over the tunnel. + +**Don't** (fixed column wrap): + +> The Coder agent connects to the workspace, opens a Tailscale tunnel, and forwards SSH and IDE traffic over the tunnel. + +Both **Don't** versions add noise to the source and produce diff churn on small edits. + +`markdownlint`'s `MD013` (line length) is already disabled, so the convention is editorial. +Editors that auto-wrap on save should be configured to leave the source alone. + +*Documentation-only. +No Vale rule.* + +## Text formatting + +The rules in this section cover inline formatting that lives inside a paragraph. + +### Bold for UI elements + +Use bold for the literal text of UI elements the reader interacts with: buttons, menu items, page titles, field labels, tab names. +Bold tells the reader "this is the thing you select or read". + +When the reader navigates across multiple UI elements, join each element with a greater-than sign (`>`) surrounded by spaces. +The separator makes the navigation path scannable and matches the convention in Microsoft and Google developer documentation. + +**Do**: + +> Select **Templates** > **Settings** > **Schedule**. +> +> Navigate to **Workspaces** > **New workspace**. + +**Don't**: + +> Navigate to "Templates" > "Settings" and select the Schedule tab. +> +> Navigate to *Templates* > *Settings* and select the *Schedule* tab. +> +> Click **Templates**, then click **Settings**, then click **Schedule**. + +*Documentation-only. +No Vale rule.* + +### Italics for emphasis only + +Reserve italics for genuine emphasis where bold would be too loud. +Do not use italics for UI elements, identifiers, or product names. + +**Do**: + +> Restarting the workspace deletes ephemeral state. +> Save your work *before* you select **Restart**. + +**Don't**: + +> Navigate to *Templates* > *Settings*. + +*Documentation-only. +No Vale rule.* + +### Code font + +Use backticks (inline code font) for the following: + +- User input. +- Command names and flag names. +- Filenames, file paths, and directory names. +- Environment variables. +- HTTP verbs and status codes. +- Configuration keys. +- Code identifiers (function names, struct names, package names). +- Placeholder variables. + +**Do**: + +> Run `coder login --token ` to authenticate. +> Set `CODER_URL` in your environment first. +> +> The server returns `404 Not Found` when the workspace does not exist. + +**Don't**: + +> Run "coder login --token \" to authenticate. +> Set CODER_URL in your environment first. +> +> The server returns 404 when the workspace does not exist. + +*Documentation-only. +No Vale rule.* + +## Block elements + +The rules in this section cover block-level structures that stand on their own line or own region. + +### Code blocks with language fences + +Every fenced code block declares a language. +Use the most specific language tag available: + +- `sh` for a shell command or a shell script. + Use `sh` when the block is input the reader types or a script they save, and the block does not also show output. +- `console` for an interactive session that shows the typed command and its output together. + Prefix each typed line with `$`. +- `powershell` for Windows command-line blocks. + PowerShell is the default Windows shell in the Coder docs. +- `tf` for Terraform and HCL. +- `yaml` for YAML. +- `go` for Go. +- `json` for JSON. +- `text` for command output shown on its own, and for any block with no syntax to highlight. + +`bash` and `shell` are aliases of `sh`. +Use `sh` so the corpus stays consistent. + +A command with no output shown is `sh`, not `console`. +To show a command together with its output, either use one `console` block with `$` before the typed line, or split the command into an `sh` block and the output into a `text` block. + +The auto-generated Coder CLI reference under `docs/reference/cli/` labels its command-usage blocks `console`. +That output is generated. +Do not copy the pattern into hand-written pages. + +The docs site highlights code with [Speed-Highlight](https://github.com/speed-highlight/core), which detects the language from the code content, not from the fence label. +The fence label still drives highlighting on GitHub and in most editors, and `markdownlint` rule `MD040` requires one, so always declare the most specific language. +For content with no sensible language tag, fall back to `text`. + +**Do**: + +````markdown +```sh +coder templates push -d ~/coder-quickstart -y quickstart +``` + +```console +$ coder templates list NAME LAST UPDATED quickstart 2 minutes ago +``` +```` + +**Don't**: + +````markdown +``` +coder login --token +``` + +```console +coder templates push -d ~/coder-quickstart -y quickstart +``` +```` + +The first **Don't** omits the language. +The second labels a bare command `console` but shows no output, so `sh` is correct. + +*Enforced by `markdownlint` rule `MD040` for the missing-language case.* + +### Callouts + +Use the GitHub callout syntax for asides. +Use them sparingly. +Prose should carry the message. + +| Callout | Use for | +|------------------|----------------------------------------------------------------------------------------------------------------------| +| `> [!NOTE]` | Supplementary context the reader benefits from but does not need to act on before proceeding | +| `> [!TIP]` | An optional optimization, shortcut, or related feature | +| `> [!IMPORTANT]` | A required step or prerequisite the reader will miss if they skim | +| `> [!WARNING]` | An action with a serious side effect (data loss, downtime, security exposure) that the reader must read before doing | +| `> [!CAUTION]` | A severe or irreversible consequence; reserve for cases where `WARNING` is not strong enough | + +A follow-up PR will demonstrate each callout rendered against an existing docs page so reviewers can calibrate when each one fits. + +*Documentation-only. +No Vale rule.* + +### Tabs for parallel content + +Use tabs when the reader picks one path that applies to their situation: installation methods on different operating systems, platform-specific commands, or API client SDKs in different languages. +Do not use tabs to hide information the reader needs regardless of choice. + +The docs site renders a `
` wrapper with H3 children as a tabbed interface. +The H3 heading text becomes the tab label, and everything from that H3 to the next H3 (or to the closing `
`) becomes the tab panel. + +**Do**: + +````markdown +
+ +### macOS + +```sh +brew install coder/coder/coder +``` + +### Linux + +```sh +curl -L https://coder.com/install.sh | sh +``` + +### Windows + +```powershell +winget install Coder.Coder +``` + +
+```` + +Leave a blank line after the opening `
` and before the closing `
` so the markdown processor parses the inner content as markdown rather than HTML. + +*Documentation-only. +No Vale rule.* + +### Lists + +If a sentence enumerates more than five items, rewrite as a bulleted list. +A prose list of six or more items reads as a wall of commas. +A bulleted list is easier to scan and to maintain. + +Unordered lists are for items that have no required order. +Ordered lists are for sequential steps the reader follows in order. +Steps in an ordered list start with an imperative verb. + +Punctuation on list items follows the structure of each item: + +- **Complete sentences**: end with a period. +- **Phrases that complete the lead-in clause from the preceding paragraph**: end with a period when the combined paragraph plus item reads as a sentence. +- **Single-word or short-phrase labels**: no terminal punctuation. + +Do not mix the styles inside one list. +If one item is a complete sentence, rewrite the rest so every item is a complete sentence. + +**Do**: + +```markdown +1. Run `coder login` to authenticate. +2. Create the workspace template. +3. Build the workspace from the template. +``` + +```markdown +The provisioner supports: + +- AWS +- Azure +- Google Cloud +``` + +```markdown +The agent reconnect logic uses the following timeouts: + +- Initial reconnect: 1 second. +- Backoff factor: 2. +- Maximum delay: 30 seconds. +``` + +**Don't**: + +```markdown +1. The user runs `coder login` to authenticate +2. Creating the workspace template comes next. +3. Then the workspace gets built from the template +``` + +```markdown +The provisioner supports: + +- AWS. +- Azure +- Google Cloud. +``` + +The first **Don't** mixes punctuation styles and uses non-imperative leads. +The second mixes punctuation inside one list and uses periods on single-word labels. + +For a "Learn more" or "See also" list of links, treat each item as a label: no terminal period, and no leading "And" or "Or". +When such a list needs a lead-in, end the lead-in with a colon on a clause that stands on its own, rather than dangling the colon off a sentence the bullets then finish. + +**Do**: + +```markdown +You have two options: + +- Install the tool with `apt-get` in the template's startup script. +- Bake the tool into the workspace image. +``` + +```markdown +## Learn more + +- [Extending templates](./extending-templates.md) +- [Terraform modules](https://developer.hashicorp.com/terraform/language/modules) +``` + +**Don't**: + +```markdown +Install it where it persists across rebuilds: + +- Add it to the template's startup script with `apt-get`. +- Or bake it into the workspace image. +``` + +The **Don't** dangles the colon off a sentence and starts a bullet with "Or". + +*Documentation-only. +No Vale rule.* + +### Tables + +Use tables to compare options, list parameters, or show permissions. +Keep tables simple. +Avoid nested formatting and avoid tables that would read better as prose. + +Keep tables narrow enough that they fit the readable text column without horizontal scrolling. +If a column needs more than a short phrase, rewrite the cell into the page body or break the table into two narrower tables. +A table that crushes column widths so words split across lines reads worse than the equivalent prose. + +If a table needs many columns to capture the data, reconsider whether a table is the right structure. +A definition list or a sequence of subsections may serve the reader better. + +*Documentation-only. +No Vale rule.* + +### Links + +Use Markdown link syntax (`[text](url)`). +Prefer relative paths within the docs (`../reference/cli/index.md`) over absolute URLs (`https://coder.com/docs/reference/cli`), so the link survives a future move of the docs site. + +Links to non-docs locations in the Coder codebase (source files, CI workflows, tests) also use relative paths. +The docs site renderer resolves those paths to the canonical GitHub URLs automatically. +A relative link to [`scripts/develop.sh`](../../../scripts/develop.sh) reads correctly on GitHub when browsing the repo and on the docs site when reading the published page. + +Anchor links to a specific section use the GitHub-flavored slug: lowercase the heading, replace spaces with hyphens, and drop punctuation (`./word-choice.md#refer-to-check-out-visit-not-see`). + +External URLs use the full `https://` form. +Do not strip the protocol. + +For the link-text rule that screen readers and reading-out-of-context demand, refer to [Descriptive link text](./accessibility-and-inclusion.md#descriptive-link-text). + +*Documentation-only. +No Vale rule for the syntax conventions.* + +### Images + +Place image assets under the matching subdirectory of `docs/images/`. +Use lowercase filenames with hyphens between words (`template-insights-dashboard.png`). +Reference the asset with a relative path from the Markdown source. + +Captions go below the image in a `` tag. + +```markdown +![Template Insights dashboard with weekly active users and connection latency charts](../../images/admin/templates/template-insights.png) + +The Template Insights dashboard. Active users in the left panel; connection latency in the right panel. +``` + +For alt text and decorative-image conventions, refer to [Alt text for images](./accessibility-and-inclusion.md#alt-text-for-images) and [Decorative images](./accessibility-and-inclusion.md#decorative-images). + +*Documentation-only for asset path conventions. +Alt-text requirement enforced by `markdownlint` rule `MD045`.* + +### Screenshots sparingly + +Use screenshots only when a sighted reader would be confused without the visual aid. +A worked example, a code block, or a precise written instruction is almost always better than a screenshot. + +> If a picture is worth a thousand words, then a good example is worth at least twice that amount. +> +> Adapted from Lorna Jane Mitchell's [Short tech writing style guide for developers](https://lornajane.net/posts/2024/short-tech-writing-style-guide-for-developers). + +Screenshots carry an ongoing maintenance burden. +The product UI changes, strings get renamed, themes get retuned, and a screenshot that was accurate at merge time silently rots. +Readers who hit a stale screenshot lose confidence in the page, and a reader using a screen reader cannot use the screenshot at all. +The writer who adds a screenshot owns the cost of replacing it every time the captured surface changes. + +When a screenshot is the right answer: + +- Capture the minimum surface area. + Crop to the smallest region that resolves the confusion the page is addressing. +- Provide alt text that conveys the purpose of the screenshot, per [Alt text for images](./accessibility-and-inclusion.md#alt-text-for-images). +- Pair the screenshot with the written instruction. + The written instruction is the source of truth. + The screenshot is a check on the reader's understanding, not a replacement for the words. + +**Do**: + +> Open the workspace settings page. +> Set **Autostart** to **Weekdays at 9 AM** and select **Save**. + +**Don't**: + +> ![Workspace settings page with Autostart set to Weekdays at 9 AM](../../images/workspaces/autostart.png) +> +> Configure autostart as shown above. + +The authoritative screenshot policy, including the obfuscation, PHI, and PII rules, lives in [`content-guidelines.md`](../content-guidelines.md). + +*Documentation-only. +Enforcement is editorial.* + +## Related + +- [Style guide landing page](./README.md) +- [Accessibility and inclusion](./accessibility-and-inclusion.md) +- [Capitalization and punctuation](./capitalization-and-punctuation.md) diff --git a/docs/.style/style-guide/numbers-units-and-dates.md b/docs/.style/style-guide/numbers-units-and-dates.md new file mode 100644 index 00000000000..294d7b86c7d --- /dev/null +++ b/docs/.style/style-guide/numbers-units-and-dates.md @@ -0,0 +1,144 @@ +# Numbers, units, and dates + +Coder documentation uses digits for all numbers in prose, a non-breaking space between a number and its unit, and the `Month Day, Year` date format. +The rules on this page set those defaults. + +## Digits everywhere + +Use digits for all numbers in prose, including small whole numbers. +The traditional Chicago-style rule of "spell out one through nine" optimizes for print journalism. +Digits are more accessible for the international and non-native-English audience that reads Coder docs, scan faster in technical prose, and stay legible through machine translation. + +If a sentence would start with a digit, restructure the sentence so a word comes first. +Do not spell out the number to avoid the leading digit. +That reintroduces the rule the digits-everywhere policy is meant to remove. + +**Do**: + +> The agent retries 3 times before giving up. +> +> Workspaces auto-stop after 8 hours of inactivity. +> +> The workspace has 5 connected users. + +**Don't**: + +> The agent retries three times before giving up. +> +> Workspaces auto-stop after eight hours of inactivity. +> +> 5 users connected to the workspace. + +The first and second **Don't** examples spell out small numbers. +The third example starts a sentence with a digit. +Restructure to put a word first ("The workspace has 5 connected users."). + +*Enforced by `Coder.DigitsEverywhere` (planned, ships at `warning` severity because the rule is preference, not hard policy).* + +## Non-breaking space between number and unit + +Insert a non-breaking space between a number and its unit so the pair never breaks across a line. +The Markdown source uses ` ` (HTML entity) or the Unicode character `U+00A0` (the literal non-breaking space). +The visible result is the same as a regular space, but the line breaker treats the number and unit as one token. + +**Do**: + +In the Markdown source (what you type): + +```markdown +The default timeout is 30 seconds. +Connection latency under 150 ms shows green. +``` + +In the rendered output (what the reader reads): + +> The default timeout is 30 seconds. +> Connection latency under 150 ms shows green. + +The rendered output looks identical to text written with a regular space. +The difference shows up only at the end of a line: the browser will never split `30` and `seconds` across two lines. +To see the rule in action, shrink the browser window until the sentence wraps. +The number and the unit move to the next line together rather than separating. + +**Don't**: + +In the Markdown source: + +```markdown +The default timeout is 30 seconds. +Connection latency under 150ms shows green. +``` + +The first line allows the browser to split `30` from `seconds`. +The second line omits the space entirely, which also reads worse. + +In code blocks, configuration values, and CLI output, the original format is preserved (`30s`, `150ms`). +The non-breaking-space rule applies to prose only. + +*Enforced by `Google.Units` (planned).* + +## Date format + +Write dates as `Month Day, Year` with a full month name and a comma between day and year. +The format is unambiguous across locales, which the all-numeric forms (`07/31/2026` versus `31/07/2026`) are not. + +**Do**: + +> Coder released version 2.20 on July 31, 2026. + +**Don't**: + +> Coder released version 2.20 on 07/31/2026. +> +> Coder released version 2.20 on 31 July 2026. +> +> Coder released version 2.20 on 2026-07-31. + +In code blocks, configuration values, log lines, and API responses, keep whatever format the source uses. +ISO 8601 (`2026-07-31`) is correct in those contexts. + +*Enforced by `Google.DateFormat` (planned).* + +## Time format + +Write times in 12-hour format with a space and uppercase AM or PM. + +**Do**: + +> The maintenance window starts at 9 AM and ends at 5 PM. + +**Don't**: + +> The maintenance window starts at 9am and ends at 5pm. +> +> The maintenance window starts at 09:00 and ends at 17:00. + +In code blocks and timestamps from logs or APIs, keep the source format. +The 12-hour rule is for prose only. + +*Enforced by `Google.AMPM` (planned).* + +## Ordinals + +Spell out ordinals `first` through `ninth`. +Use digits with a suffix for `10th` and up. This is the one place the digits-everywhere rule yields, because ordinals spelled out read more naturally in prose at low counts. + +**Do**: + +> The first time you run `coder login`, the CLI prompts you for an access URL. +> +> The 10th workspace in the list is the oldest. + +**Don't**: + +> The 1st time you run `coder login`, the CLI prompts you for an access URL. +> +> The tenth workspace in the list is the oldest. + +*Enforced by `Google.Ordinal` (planned).* + +## Related + +- [Style guide landing page](./README.md) +- [Capitalization and punctuation](./capitalization-and-punctuation.md) +- [Formatting](./formatting.md) diff --git a/docs/.style/style-guide/voice-and-tone.md b/docs/.style/style-guide/voice-and-tone.md new file mode 100644 index 00000000000..0fd43d16e04 --- /dev/null +++ b/docs/.style/style-guide/voice-and-tone.md @@ -0,0 +1,172 @@ +# Voice and tone + +Coder documentation addresses the reader directly, uses active voice, and describes the product in the present tense. +The rules on this page set those defaults. + +For pronoun conventions that center inclusive language, refer to [Accessibility and inclusion](./accessibility-and-inclusion.md). + +## Address the reader directly + +Use the second person ("you") in prose that gives the reader an instruction or describes what the reader sees, types, or gets back. +Second person is direct, scales across audiences, and avoids the ambiguity of "the user" (which user?) or generic constructions. + +**Do**: + +> You can connect to a workspace over SSH after you have installed the Coder CLI. + +**Don't**: + +> Users can connect to workspaces over SSH after the user has installed the Coder CLI. + +*Documentation-only. +No Vale rule.* + +## Avoid first-person singular + +First-person singular pronouns (`I`, `my`, `me`, `mine`, `I'm`, `I've`) imply a single author speaking to a single reader, which is the wrong register for product documentation. +Rewrite in the second person or in a neutral voice. + +**Do**: + +> You can configure the workspace timeout in the template settings. + +**Don't**: + +> I usually set the workspace timeout in the template settings. + +*Enforced by `Coder.FirstPersonSingular`.* + +## Reserve first-person plural for Coder Technologies + +`We`, `us`, and `our` refer to **Coder Technologies, Inc.**, the company that makes the Coder platform. +For formal references to the company, use the full name ("Coder Technologies, Inc."). +For informal references in body prose, use `we`, `us`, or `our`. + +Do not use first-person plural for: + +- The product itself. + The product is `Coder`, not "we". + Rewrite to put the product, a release, or a feature as the subject. +- A combined "you and the docs" or "you and the author". + That construction obscures who is taking the action. + +**Do**: + +> For more information about enterprise licensing, [contact us](https://coder.com/contact/sales). +> +> Coder Technologies, Inc. publishes a new agent binary in each release. +> +> Each release includes a new agent binary. +> You can install the agent with the workspace template. + +**Don't**: + +> We ship a new agent binary in each release. +> +> Coder ships new agent binaries: we release them on the first of each month. +> +> We can install the agent by running this command on our workspace. + +The first **Don't** uses "we" to mean the product rather than the company. +Rewrite with the product, release, or feature as the subject ("Each release includes ..."). +The second **Don't** uses "we" to refer to the product's release behavior. +The third **Don't** uses "we" to mean "the docs and the reader together", which obscures who runs the command. + +*Enforced by `Coder.FirstPersonPlural`.* + +## Active voice by default + +Active voice puts the actor first and reads faster. +Passive voice is acceptable when the actor is genuinely unknown or irrelevant (`The token is rotated every 24 hours.`), but the default is active. + +**Do**: + +> Coder rotates the agent token every 24 hours. + +**Don't**: + +> The agent token is rotated every 24 hours by Coder. + +*Documentation-only. +No Vale rule. +Imprecise rules like `Google.Passive` and `write-good.Passive` fire on every passive construction including the legitimate ones, so they stay out of the package per the rule-authoring doctrine.* + +## Present tense by default + +Describe how the product works in the present tense. +Future tense ("will") implies an event that has not happened yet at read time. +Reserve future tense for: + +- Genuine future events, like scheduled rollouts or deprecations with a known date. +- Conditional or predictive statements where "will" carries the meaning "is guaranteed to". + "If you stop the workspace, the agent will disconnect within 30 seconds" describes a guaranteed consequence and reads more naturally with `will` than with the present tense. + +**Do**: + +> The provisioner reads the template files and creates the workspace. +> +> If you delete the template, Coder will refuse to create new workspaces from it. + +**Don't**: + +> The provisioner will read the template files and will create the workspace. +> +> When you run the install script, it will download the latest release. + +The second **Don't** uses future tense to describe normal behavior of the install script. +Use plain present tense for behavior the product already exhibits. + +*Documentation-only. +No Vale rule.* + +## Trailing prepositions are a judgment call + +A sentence that ends with a preposition (`with`, `to`, `from`, `for`, `on`, `of`, `at`, `by`, `into`, `over`, `under`, `about`) can leave its object implicit, which adds a small comprehension cost. +Avoiding the trailing preposition, though, can produce a more awkward sentence. +There is no one-size-fits-all rule. +Read both versions and keep the one that reads more naturally. + +Lean toward rewriting when the trailing preposition is redundant, or when the reordered version is still easy to read: + +**Do**: + +> The CLI prompts you for the directory in which to store the template. +> +> Where is the config file? + +**Don't**: + +> The CLI prompts you for the directory you want to store the template in. +> +> Where is the config file at? + +The second **Don't** keeps a redundant `at`. +"Where is the config file?" says the same thing. + +Keep the trailing preposition when avoiding it contorts the sentence: + +**Do**: + +> This is some nonsense that I will not put up with. +> +> Open the repository you want to clone from. + +**Don't**: + +> This is some nonsense up with which I will not put. +> +> Open the repository from which you want to clone. + +The first **Don't** is the classic over-correction: the rewrite is harder to read than the preposition it avoids. + +When both versions read equally well, the writer chooses. +Treat avoiding a trailing preposition as a default to reach for, not a rule to enforce. + +*Documentation-only. +No Vale rule.* + +## Related + +- [Style guide landing page](./README.md) +- [Word choice](./word-choice.md) +- [Accessibility and inclusion](./accessibility-and-inclusion.md) diff --git a/docs/.style/style-guide/word-choice.md b/docs/.style/style-guide/word-choice.md new file mode 100644 index 00000000000..08e3b6ea4a0 --- /dev/null +++ b/docs/.style/style-guide/word-choice.md @@ -0,0 +1,386 @@ +# Word choice + +Coder documentation uses canonical brand and product names, plain language for product actions, and "refer to" instead of "see" for navigational pointers. +The rules on this page set those defaults. + +For inclusive-language substitutions like `allowlist` or `primary`, refer to [Accessibility and inclusion](./accessibility-and-inclusion.md). + +## Coder product and feature names + +`Coder`, the company and the product, is always capitalized. +Feature names are capitalized as proper nouns when the prose names the feature. +The underlying generic concept stays lowercase. + +When the prose refers to the Coder command-line interface as a tool, wrap it in backticks: `coder`. +The bare lowercase `coder` (no backticks) is wrong. +It reads as a misspelling of the product name. + +| Do | Don't | +|---------------------------------|------------------------------------------------| +| Coder | coder (referring to the product, no backticks) | +| `coder` (the CLI, in backticks) | coder (the CLI, no backticks) | +| AI Bridge | AI bridge, AIBridge | +| Workspace Proxy | workspace proxy (referring to the feature) | +| workspace | Workspace (referring to the generic concept) | +| template | Template (referring to the generic concept) | +| agent | Agent (referring to the generic concept) | +| provisioner | Provisioner (referring to the generic concept) | + +**Do**: + +> Coder runs `coder login` to authenticate against the Coder server. +> +> Open the AI Bridge integration page to configure model providers. + +**Don't**: + +> coder runs coder login to authenticate against the coder server. +> +> Open the ai bridge integration page to configure model providers. + +*Enforced by `Coder.ProductTerms` (planned).* + +## Brand names + +Use the canonical casing for third-party brand and product names. +The Coder docs team keeps a substitution list. + +When the prose refers to a third-party command-line tool, wrap the tool name in backticks the same way as for the Coder CLI. +The product name (`Terraform`) stays capitalized in prose. +The CLI tool (`terraform`) lives in backticks. + +| Do | Don't | +|-------------------------------------|---------------------------------------| +| HashiCorp | Hashicorp, HASHICORP | +| GitHub | Github, GITHUB | +| OpenTofu | Opentofu, OpenTOFU | +| Kubernetes | kubernetes (in prose), K8s (in prose) | +| Terraform | terraform (in prose, no backticks) | +| `terraform` (the CLI, in backticks) | terraform (the CLI, no backticks) | +| JetBrains | Jetbrains, jetbrains | +| VS Code | VSCode, VSC, VS code | + +Lowercase forms remain correct in code blocks, URLs, package names, and Terraform provider sources, where the canonical form is lowercase by convention. + +*Enforced by `Coder.BrandNames`.* + +## Dev container terminology + +The open standard at [containers.dev](https://containers.dev/) uses two forms in its own documentation: + +- **`Development Container Specification`** (or **`Dev Container Spec`** for short) when naming the open specification, the Features ecosystem, or the Templates ecosystem. +- **`dev container`** (lowercase, two words) for the category and for any instance. + +The Coder docs follow the same conventions. + +`envbuilder` is the implementation tool Coder uses to build dev containers. +It is not itself the concept, so it stays in backticks as a tool name. + +> [!NOTE] The Coder feature that integrates the open standard with Coder workspaces is named `Dev Containers` in product context. +> The capitalization there comes from the [Coder product and feature names](#coder-product-and-feature-names) rule for Coder features, not from the underlying concept. + +| Do | Don't | +|-------------------------------------|------------------------------------------------------| +| Development Container Specification | DevContainer Specification | +| Dev Container Spec | dev container spec (as the proper-noun shorthand) | +| dev container | Dev Container, DevContainer, devcontainer (in prose) | +| `devcontainer.json` | `dev-container.json`, `DevContainer.json` | +| `envbuilder` | EnvBuilder, Envbuilder, env builder | + +**Do**: + +> Coder builds dev containers that conform to the Development Container Specification. +> The template defines the dev container in a `devcontainer.json` file. +> The provisioner builds the dev container with `envbuilder` and starts the agent inside it. + +**Don't**: + +> Coder supports DevContainers as a workspace runtime. +> (Wrong casing. +> The spec writes the abbreviated form as two words.) +> +> Coder supports Dev Containers as a workspace runtime. +> (Capital-D `Dev Container` is reserved for the proper-noun shorthand `Dev Container Spec`. +> The category is lowercase.) + +*Enforced by `Coder.DevContainer` (planned).* + +## Phrasal verbs and their noun forms + +English uses two spellings for many product actions: two words when the term is a verb (`set up`, `log in`), and one word (or hyphenated) when the term is a noun (`setup`, `login`). +Treat them consistently across the docs. + +| Verb (two words) | Noun (one word or hyphenated) | +|------------------|-------------------------------| +| 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 | + +`Quickstart` is one word, always, even though it derives from "quick start". + +**Do**: + +> Follow the Quickstart to set up your first workspace. +> +> The setup takes about 10 minutes. +> +> Log in to Coder, then check that the login appears in the audit log. +> +> Back up the database before the upgrade. +> The backup file lives in `/var/lib/coder/backups`. + +**Don't**: + +> Follow the Quick Start to setup your first workspace. +> +> The set-up takes about 10 minutes. +> +> Login to Coder, then check that the log in appears in the audit log. +> +> Backup the database before the upgrade. + +*Enforced by `Coder.PhrasalVerbs` (planned).* + +## Refer to, check out, visit, not see + +When the prose points the reader at another page, section, or external resource, choose the verb that matches the register: + +- **Refer to** is the formal default for cross-references inside the docs. + Use it when the destination is a reference page, a specification, or any resource the reader should consult before continuing this doc. +- **Check out** is informal. + Use it in tutorials and step-by-step passages where the conversational register suits the content. + Do not use it in reference material. +- **Visit** is best when the destination is an external URL or another site, especially when the reader leaves the docs. + +Do not use **see** as a navigational verb. +Reserve **see** for the rare case where the prose describes what a reader observes in the product UI ("You see a list of templates on the Templates page"). +The plain-language alternatives carry register information that "see" does not, and reserving "see" for its observational meaning improves clarity for every reader. + +The same reservation covers "see" used to mean "understand" or "find out". +In a list of outcomes, "learn why the build fails" or "find out why the build fails" names what the reader gains. +"See why the build fails" borrows the observational sense of "see" for a comprehension outcome, so prefer "learn" or "find out". + +**Do**: + +> For the full command list, refer to the [Coder CLI reference](../../reference/cli/index.md). +> +> Check out the [Quickstart](../../tutorials/index.md) before you configure the production deployment. +> +> Visit the [Terraform Registry](https://registry.terraform.io/) for the latest provider versions. +> +> Add a Ruby option, then learn why the option alone does not install the toolchain. + +**Don't**: + +> For the full command list, see the [Coder CLI reference](../../reference/cli/index.md). +> +> See the [Quickstart](../../tutorials/index.md) before you configure the production deployment. +> +> See the [Terraform Registry](https://registry.terraform.io/) for the latest provider versions. +> +> Add a Ruby option, then see why the option alone does not install the toolchain. + +*Enforced by `Coder.SeeAlternatives` (planned).* + +## Learn more, not Next steps + +End-of-page navigation that points the reader at related material uses the heading **Learn more**, not **Next steps**. +Two rationales apply: + +- **Sequencing**: "Next steps" implies the reader must follow a specific sequence. + "Learn more" frames the section as optional related reading, which matches the Diátaxis distinction between a tutorial (sequenced) and a how-to or reference (independent). +- **Inclusive language**: "steps" reads as a physical-mobility metaphor. + Readers who cannot walk through steps still consume technical documentation. + Neutral alternatives like "Learn more" do not encode that assumption. + +**Do**: + +```markdown +## Learn more + +- [Configure SSH access](./ssh.md) +- [Set workspace autostart](./autostart.md) +``` + +**Don't**: + +```markdown +## Next steps + +- [Configure SSH access](./ssh.md) +- [Set workspace autostart](./autostart.md) +``` + +*Enforced by `Coder.LearnMore` (planned).* + +## Tutorial, not walkthrough + +`Tutorial` is the standard term in technical documentation and matches the Diátaxis category. +`Walkthrough` is colloquial, and the metaphor assumes the reader can walk. +Neutral alternatives like "tutorial" do not encode that assumption. + +**Do**: + +> This tutorial shows you how to deploy Coder on AWS. + +**Don't**: + +> This walkthrough shows you how to deploy Coder on AWS. + +*Enforced by `Coder.Tutorial` (planned).* + +## Select, not click + +Use "select" for actions on UI elements, regardless of input device. +"Click" assumes a mouse. +Touch devices tap, keyboard users press Enter, and assistive-technology users activate. +"Select" covers every case and matches the Microsoft style guide convention. + +Reserve "click" for code or configuration that literally fires on a click event, like a `onClick` handler or a DOM `click` event. + +**Do**: + +> Select **Save** to apply the changes. +> +> Select **Templates** > **Settings** > **Schedule**. + +**Don't**: + +> Click **Save** to apply the changes. +> +> Click on the **Templates** tab, then click **Settings**. + +*Enforced by `Coder.SelectClick` (planned).* + +## Don't assume simplicity or difficulty + +Words that minimize the difficulty of an action ("simply", "just", "easy", "easily", "obviously", "of course", "clearly") assume the reader's experience matches the author's. +If something is "obvious" to the author and not to the reader, the reader may feel the document is confusing or condescending. +Cut the simplicity-assuming word or restructure the sentence. + +The reverse pattern, exaggerating difficulty ("complex", "intricate", "non-trivial"), is also banned. +Both patterns predict the reader's reaction instead of describing the work. + +**Do**: + +> Run `coder login` to authenticate. + +**Don't**: + +> Simply run `coder login` to authenticate. +> It's easy! +> +> The non-trivial process of authenticating with Coder requires running `coder login`. + +*Enforced by `Coder.AssumeDifficulty` (planned).* + +## Avoid weasel words + +Vague attributions ("many believe", "some say", "experts agree", "studies show", "it is widely accepted that", "most people") let the prose claim something without naming a source. +Either name the source or remove the claim. + +Vague qualifiers ("often", "usually", "sometimes", "in most cases") tell the reader the statement is sometimes false but do not say when. +Replace with the specific condition, or remove the qualifier and accept the statement as a default. + +**Do**: + +> The Coder agent reconnects within 30 seconds of a network drop. +> +> The [Coder benchmarks](../../about/why-coder.md) show a 40% reduction in onboarding time for new developers. +> +> The provisioner runs `terraform plan` before `terraform apply`. + +**Don't**: + +> The Coder agent usually reconnects within a reasonable time. +> +> Many developers believe Coder reduces onboarding time. +> +> Experts agree that running `terraform plan` first is best practice. + +*Enforced by `Coder.WeaselWords` (planned).* + +## Stop, not kill; turn off, not disable + +In product-facing prose, prefer "stop" over "kill" and "turn off" over "disable". +The plain-language forms read better for a non-technical audience and do not carry violent or ableist connotations. + +The rule has scoped exceptions for unavoidable industry-specific terms. +When the prose names a specific technical command or a real state label, the original term is the only correct one. +Wrap the term in backticks to signal that the prose is naming a tool or a state, not using the violent verb. + +The exceptions are: + +- The Linux `kill` command (process control) and the `SIGKILL` signal. + When the prose tells the reader to terminate a process from a shell, the literal command is `kill `. + In prose, write "stop the process" or "end the process" instead. + Use `kill` in backticks only when the prose names the command itself. +- The `disabled` state of a feature flag in configuration. + Configuration values keep their literal name (`disabled: true`), and prose describing the flag also uses the state name in backticks. +- The `killed` status of a process in a log file or in CLI output. + The log line preserves the original wording. + +The Coder docs team is aware that the most natural verb for software (`run`) carries similar connotations. +A dedicated rule for `run` is out of scope for this revision. + +**Do**: + +> To stop a workspace, select **Stop** in the workspace dashboard. +> +> You can turn off auto-update in the template settings. +> +> If the provisioner hangs, end the process from the shell. +> The literal command is `kill ` or `pkill provisionerd`. +> +> The agent reports a `killed` status when the supervisor terminated the process. + +**Don't**: + +> To kill a workspace, select **Kill** in the workspace dashboard. +> +> You can disable auto-update in the template settings. +> +> If the provisioner hangs, kill the process from the shell. +> (Plain-text `kill` used where backticks are required, and the verb reads as violent.) + +*Enforced by `Coder.PlainLanguage` (planned), with the industry-term exception scoped in the rule.* + +## Keep internal-only references out of published docs + +The published documentation, including the contribution guides, is public. +Every reader and every contributor, whether a community contributor or a Coder employee, must be able to open every resource linked from the docs. +A link that only employees can open excludes community contributors, so it does not belong on a published page. + +Keep these out of published pages: + +- Issue-tracker identifiers and URLs (for example, an `ABC-123` identifier or a `linear.app` link). +- Private or internal-only repositories and their URLs. +- Internal-only chat threads, design docs, dashboards, runbooks, and wikis. +- Any link gated behind employee-only access. + +Track the work in the surfaces built for it. +A pull request description, a commit message, or a code-review comment is the right place to cite an internal issue ID or a private link, because every contributor on that change can read it there. +The published page stays the same for everyone. + +**Do**: + +> The provisioner retries the build 3 times before it fails. + +**Don't**: + +> The provisioner retries the build 3 times before it fails. +> For the backstory, refer to [ABC-123](https://linear.app/acme/issue/ABC-123). + +*Documentation-only. +Planned Vale rule `Coder.InternalReferences`.* + +## Related + +- [Style guide landing page](./README.md) +- [Voice and tone](./voice-and-tone.md) +- [Accessibility and inclusion](./accessibility-and-inclusion.md) diff --git a/docs/.style/styles/Coder/README.md b/docs/.style/styles/Coder/README.md index 2a70166eeb7..4023b22f53b 100644 --- a/docs/.style/styles/Coder/README.md +++ b/docs/.style/styles/Coder/README.md @@ -22,9 +22,7 @@ incrementally. Planned starter rules: 1. Write a YAML file under this directory. Name it after the rule's intent, for example `InclusiveLanguage.yml` or `ProductVoice.yml`. -2. Each rule's `message:` should link to the matching section in - `docs/.style/style-guide.md`, ideally with a deep-link anchor, so a - contributor reading a Vale warning can jump straight to the guidance. +2. Each rule's `message:` should link to the matching section in the appropriate subpage of `docs/.style/style-guide/`, ideally with a deep-link anchor, so a contributor reading a Vale warning can jump straight to the guidance. 3. Land at `level: warning` first. Promote to `level: error` only after both conditions hold: - The rule is objectively correct (typo, brand-name casing, banned diff --git a/docs/about/contributing/documentation.md b/docs/about/contributing/documentation.md index cab9bf1362d..7f511d9b58d 100644 --- a/docs/about/contributing/documentation.md +++ b/docs/about/contributing/documentation.md @@ -32,13 +32,10 @@ following third-party references: ## Tools -This repository runs [Vale](https://vale.sh/) on `docs/` as part of CI to -enforce prose style. The configuration is the repo-root `.vale.ini`, and -the curated rule set is documented in -[`docs/.style/style-guide.md`](../../.style/style-guide.md). Run the same -checks locally with `make lint/prose`. Vale runs in advisory mode in -this iteration: warnings surface as inline PR annotations, but they don't -block the build. +This repository runs [Vale](https://vale.sh/) on `docs/` as part of CI to enforce prose style. +The configuration is the repo-root `.vale.ini`, and the curated rule set is documented in [`docs/.style/style-guide/`](../../.style/style-guide/README.md). +Run the same checks locally with `make lint/prose`. +Vale runs in advisory mode in this iteration: warnings surface as inline PR annotations, but they don't block the build. The following external tools can also help when drafting. Take their suggestions with a grain of salt because they aren't tuned for Coder's