mirror of
https://github.com/coder/coder.git
synced 2026-09-24 15:04:27 +08:00
docs: scaffold docs/.style for the prose style guide (#25466)
Adds a private contributor-tooling directory at `docs/.style/` that will host the canonical prose style guide and the custom Vale rules used to enforce it. The directory's contents do not deploy to `coder.com/docs`. This PR is the scaffold only. The Vale configuration, the rule set, and the per-rule style-guide sections all land in follow-up PRs. ## What changes - New `docs/.style/` directory with: - `README.md` explaining the convention - `style-guide.md` as a table-of-contents scaffold - `styles/Coder/README.md` placeholder so Git tracks the empty Vale rules dir - `.github/workflows/deploy-docs.yaml`: skip the workflow on `.style`-only pushes, and exclude `.style` paths from the surgical-reindex git diff on mixed commits. Defense-in-depth on top of the manifest-driven coder.com routing. - `.github/.linkspector.yml`: add `docs/.style` to `excludedDirs` - `AGENTS.md` and `.claude/docs/DOCS_STYLE_GUIDE.md`: cross-link to the new style guide for agents ## Verification - `make pre-commit-light` clean (`fmt/markdown`, `lint/markdown`, `lint/typos`, `lint/emdash`, `lint/actions/actionlint`, `lint/shellcheck`). - `markdown-table-formatter --check` and `markdownlint-cli2` both process the new files (existing globs are `find docs -name '*.md'`). - `actionlint` clean on the modified workflow. - coder.com exclusion works because route discovery and Algolia indexing are manifest-driven; this directory is not in `docs/manifest.json`. The workflow changes are defense in depth. <details> <summary>Implementation plan and decision log</summary> ### Decisions - **Location**: `docs/.style/` (leading dot, mirrors `.github/`, `.vscode/`, `.claude/`). Vale's `StylesPath` will be `docs/.style/styles/`; `.vale.ini` lands at repo root in a follow-up. - **Existing public page `docs/about/contributing/documentation.md`**: untouched in this PR. Nick's separate information-architecture rework will redirect it to GitHub at the right time. - **Placeholder for empty `styles/Coder/`**: real `README.md`, not `.gitkeep`. Discoverable on GitHub, lints with the existing tooling, lists the planned starter rules. - **CONTRIBUTING.md**: not touched. It's a 2-line redirect to `coder.com/docs/CONTRIBUTING`; bloating it would defeat the redirect. - **`.claude/docs/DOCS_STYLE_GUIDE.md`**: kept as the structure/research companion. A blockquote at the top points at the new canonical prose guide. ### coder.com exclusion mechanism (verified by inspection) Direct inspection of `coder/coder.com`: - Route discovery in [`src/utils/docs/docs.ts`](https://github.com/coder/coder.com/blob/master/src/utils/docs/docs.ts) iterates `routes` from `docs/manifest.json`. Files not in the manifest never become routes. - The Algolia surgical indexer at [`src/utils/algoliaDocs/surgical.ts`](https://github.com/coder/coder.com/blob/master/src/utils/algoliaDocs/surgical.ts) explicitly skips paths not in the manifest, incrementing `pathsSkipped`. Net result: not adding anything from `docs/.style/` to `manifest.json` is the only thing that has to be true for the exclusion to work. The `deploy-docs.yaml` tweaks are defense in depth. ### deploy-docs.yaml changes (pre-mortem) 1. Trigger path negation `!docs/.style/**` skips the workflow on `.style`-only pushes. GitHub Actions only suppresses when every changed file matches a negation, so mixed commits still trigger. 2. The git-diff pathspec `:(exclude)docs/.style/**` drops `.style` paths from the surgical-reindex payload on mixed commits. Risks considered: - **Test contract**: `.github/workflows/test-deploy-docs-diff.sh` only exercises the downstream awk parser, not the git-diff invocation. The exclusion happens at git-diff time; the parser sees the same `<status>\0<path>\0` format. No test change needed. - **First push to a brand-new branch**: the workflow falls back to whole-branch reindex when `BEFORE_SHA` is all zeros. Whole-branch reindex re-extracts records from the manifest, which still excludes `.style` files because they are not in the manifest. - **Workflow-dispatch**: takes the whole-branch path; same reasoning. Safe. ### Why a real README in `styles/Coder/` instead of `.gitkeep` It explains intent, lists the upcoming rules, and lints with the existing tooling. The cost is one extra Markdown file; the upside is that a contributor browsing GitHub sees the plan without clicking around. </details> --- *Filed via [Coder Agents](https://coder.com/docs/ai-coder/agents) on Nick's behalf.* Linear: DOCS-180
This commit is contained in:
+33
-8
@@ -9,22 +9,24 @@ Nothing under this directory is published to
|
||||
| Path | Purpose |
|
||||
|-------------------------|---------------------------------------------------------------------|
|
||||
| `content-guidelines.md` | Canonical content rules: what belongs in `docs/`, what doesn't, why |
|
||||
| `style-guide.md` | Canonical prose style guide for `docs/` |
|
||||
| `styles/Coder/` | Custom Vale rules specific to Coder (product voice, terms) |
|
||||
|
||||
See [`content-guidelines.md`](content-guidelines.md) for the canonical
|
||||
rules on what content belongs in `docs/` and what should be routed
|
||||
elsewhere (blog, changelog, Support KB, etc.).
|
||||
|
||||
> [!NOTE]
|
||||
> This directory is the home for the docs scaffold being built out under
|
||||
> DOCS-180. The prose style guide and the Vale rules that enforce it land
|
||||
> in that work and will appear in this table when they merge.
|
||||
See [`style-guide.md`](style-guide.md) for the prose style guide. The
|
||||
`styles/Coder/` directory holds the custom Vale rules that enforce parts
|
||||
of the guide; Vale's `StylesPath` in the repo-root `.vale.ini` (added in
|
||||
a follow-up PR) points at `docs/.style/styles/`.
|
||||
|
||||
## Why a hidden directory
|
||||
|
||||
The leading dot mirrors the `.github/`, `.vscode/`, and `.claude/`
|
||||
convention already used in this repo for tooling-internal directories.
|
||||
The structural Markdown linters still pick it up; coder.com's docs site
|
||||
does not.
|
||||
Vale and the structural Markdown linters still pick it up; coder.com's
|
||||
docs site does not.
|
||||
|
||||
## How exclusion from coder.com works
|
||||
|
||||
@@ -38,10 +40,14 @@ manifest-driven:
|
||||
do not become routes.
|
||||
- The Algolia surgical indexer at
|
||||
[`coder/coder.com:src/utils/algoliaDocs/surgical.ts`](https://github.com/coder/coder.com/blob/master/src/utils/algoliaDocs/surgical.ts)
|
||||
explicitly skips paths that are not in the manifest.
|
||||
explicitly skips paths that are not in the manifest, incrementing
|
||||
`pathsSkipped`.
|
||||
|
||||
Net result: not adding anything from `docs/.style/` to `docs/manifest.json`
|
||||
gives us no route, no Algolia record, and no sidebar entry.
|
||||
gives us no route, no Algolia record, and no sidebar entry. Two
|
||||
defense-in-depth changes in `.github/workflows/deploy-docs.yaml` keep the
|
||||
deploy workflow from running on `.style`-only commits and exclude the
|
||||
directory from the surgical-reindex payload on mixed commits.
|
||||
|
||||
## What still runs against this directory
|
||||
|
||||
@@ -50,9 +56,28 @@ gives us no route, no Algolia record, and no sidebar entry.
|
||||
`markdownlint-cli2 --fix $(find docs -name '*.md')`.
|
||||
- `make fmt/markdown` (markdown-table-formatter) reflows tables here for
|
||||
the same reason.
|
||||
- Vale, once `.vale.ini` lands in a follow-up PR, lints the entire
|
||||
`docs/**/*.md` set including `docs/.style/style-guide.md`.
|
||||
|
||||
## What does not run against this directory
|
||||
|
||||
- `linkspector`: excluded via `excludedDirs` in `.github/.linkspector.yml`.
|
||||
External-link checking is overkill for contributor tooling.
|
||||
- The `deploy-docs` workflow: its `paths:` filter negates `docs/.style/**`,
|
||||
and the surgical-reindex git-diff invocation excludes the same path. See
|
||||
`.github/workflows/deploy-docs.yaml`.
|
||||
- The `docs-preview` workflow: its `paths:` filter negates `docs/.style/**`,
|
||||
so `.style`-only PRs produce no preview comment. The selection logic also
|
||||
skips `.style` files when picking the preview target on mixed PRs. See
|
||||
`.github/workflows/docs-preview.yaml`.
|
||||
|
||||
## Editing the content guidelines
|
||||
|
||||
Open a PR against `docs/.style/content-guidelines.md`. The rules in that
|
||||
file apply to humans and AI-assisted workflows alike; when it conflicts
|
||||
with another style or contributing doc in the repo, it governs.
|
||||
|
||||
## Editing the style guide
|
||||
|
||||
Open a PR against `docs/.style/style-guide.md`. Follow-up PRs add each
|
||||
rule and the matching style-guide section together.
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
# 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 the follow-up PR that lands `.vale.ini`.
|
||||
|
||||
## 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/) |
|
||||
@@ -0,0 +1,40 @@
|
||||
# Coder custom Vale rules
|
||||
|
||||
Custom Vale rules specific to Coder live here. Each rule is a YAML file
|
||||
that Vale loads through the `BasedOnStyles = Coder` setting in the
|
||||
repo-root `.vale.ini`.
|
||||
|
||||
This directory is intentionally empty for now. Follow-up PRs add rules
|
||||
incrementally. Planned starter rules:
|
||||
|
||||
- Dev Container terminology
|
||||
- HashiCorp casing
|
||||
- Limit "we"
|
||||
- Setup vs set up, Quickstart casing
|
||||
- Next steps vs Learn more
|
||||
- Vale substitution rule scaffold
|
||||
- Weasel words
|
||||
- Em-dash and en-dash mirror in Vale
|
||||
- Inclusive-language substitutions
|
||||
- Product-voice rules
|
||||
|
||||
## Authoring a new rule
|
||||
|
||||
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.
|
||||
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
|
||||
substitution).
|
||||
- The existing-content violation count for the rule reaches zero.
|
||||
4. A follow-up PR will add a parity CI check that verifies every rule
|
||||
here has a matching section in `style-guide.md`. Add the section in
|
||||
the same PR as the rule.
|
||||
|
||||
## Reference
|
||||
|
||||
- Vale docs: <https://vale.sh/docs/>
|
||||
- Vale rule types: <https://vale.sh/docs/topics/styles/>
|
||||
Reference in New Issue
Block a user