mirror of
https://github.com/coder/coder.git
synced 2026-09-21 12:44:32 +08:00
docs: add canonical content guidelines, close doc-check SKILL gaps (DOCS-332) (#26352)
Closes DOCS-332. ## Summary Add `docs/.style/content-guidelines.md` as the canonical source of truth for what belongs in Coder's docs and what doesn't. Slim `.claude/skills/doc-check/SKILL.md` and reconcile `.claude/docs/DOCS_STYLE_GUIDE.md` so they defer to that canonical file. One-line pointer added from root `AGENTS.md`. ## Problem DOCS-332 cataloged five gaps in the doc-check skill and its sibling AI-facing docs: 1. Two style guides overlapping and contradicting each other on bold and italic conventions. 2. The SKILL had a single "do not comment" class (auto-generated CLI docs); everything else was inferred. Source of sticky-comment noise. 3. Premium signaling split across two files (`(Premium)` H1 suffix in SKILL, `"state": ["premium"]` manifest entry in DOCS_STYLE_GUIDE). 4. The no-emdash rule lived in root `AGENTS.md` and DOCS_STYLE_GUIDE but not in the SKILL. 5. The redirects-live-in-`coder/coder.com:redirects.json` rule lived only in DOCS_STYLE_GUIDE. In parallel, a cross-repo content guidance discussion (June 2026) produced a canonical "what belongs in the docs" document in Notion that disagreed with the existing GitHub guidance in three places: screenshots, "proactive documentation," and in-docs troubleshooting. ## Fix **New canonical file**: `docs/.style/content-guidelines.md`. Translates the canonical content guidance into the repo: - Diátaxis framing. - "Documentation lands with the change" rule with three corollaries (docs in same PR; no docs for unconfirmed features; multi-PR launch exception, present tense, never as a promise). - 7-step quick decision checklist. - "What belongs / what doesn't / routing table" structure. - Screenshot policy: only when the topic would be confusing without it; PHI/PII, secrets, minimal surface area, alt text required. - Premium signaling requires both H1 suffix and `"state": ["premium"]` in `docs/manifest.json`. - Redirects must be added to `coder/coder.com:redirects.json`, never `docs/_redirects`. - Verify-against-code rule with exact RBAC names and full API paths. - Terraform exception for minimal teaching examples. **Slim `.claude/skills/doc-check/SKILL.md`**: defers scope and routing to `docs/.style/content-guidelines.md`. Adds an explicit "What not to comment on" list (Gap 2) covering internal refactors, test-only changes, CI/tooling, dep bumps, and pure code reorganizations. Closes Gaps 3, 4, and 5 in the same pass. **Reconcile `.claude/docs/DOCS_STYLE_GUIDE.md`**: removes the image-driven documentation pattern, the placeholder-screenshot workflow, the "proactive documentation" pattern, and the in-docs troubleshooting H3 pattern. Each is replaced with a short pointer to the canonical guidelines. Prose, formatting, and structural conventions remain; this file continues to cover those. **`AGENTS.md`**: one-line pointer added to the navigation section and the read-when-relevant list. ## What's explicitly out of scope - **Gap 1** (bold and italic reconciliation): deferred to DOCS-186, which will redirect the human-facing `docs/about/contributing/documentation.md` to `docs/.style/style-guide.md` once DOCS-180 lands. - **Prose-rule migration** to `docs/.style/style-guide.md`: handled by DOCS-180. - **doc-check workflow comment-format changes**: deferred (Phase 2 work). - **redirect-suggestion behavior in doc-check**: tracked as DOCS-359. - **Historical predictive-content sweep across `docs/`**: tracked as DOCS-358. ## Known CI notes - This PR will trigger `docs-preview`, which posts a comment with a deep link to the first added Markdown file. The link will 404 because `docs/.style/**` files are not added to `docs/manifest.json` and shouldn't be (the directory is contributor-facing, not published). DOCS-180 negates `docs/.style/**` in the `docs-preview` workflow; once that lands the papercut goes away. Safe to ignore the comment on this PR. - `deploy-docs` will run on merge but is manifest-driven: since `docs/.style/**` files are not in `docs/manifest.json`, the surgical Algolia indexer will skip them and no full Vercel rebuild fires. - `doc-check` will run on this PR; the diff has no user-facing product change, so it should report no documentation impact. ## Review This change is documentation-only and does not modify product code or CI checks in any meaningful way. Per standing instructions this requires a human review; the `/coder-agents-review` bot is **not** triggered. <details> <summary>Implementation plan and decision log</summary> ### Decisions made during scoping 1. **Option B (consolidate)** for DOCS-332: a single canonical content-guidance file instead of distributing fixes back into the existing sibling files. 2. **File location**: `docs/.style/content-guidelines.md`. The rules apply to both humans and AI, so an AI-prefixed naming scheme would mislead. `docs/.style/` is contributor-facing and not published to coder.com per the DOCS-180 convention. 3. **Independent merge**: this PR does not block on DOCS-180. The README in `docs/.style/` is a minimal stub that should merge cleanly with the DOCS-180 README. 4. **Canonical-source model**: GitHub becomes canonical for docs content guidance. The cross-repo source page will be rewritten to point at this file as a follow-up. ### Conflicts resolved | Topic | Old GitHub guidance | New canonical | |----------------|---------------------------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------| | Screenshots | Image-driven sections; placeholders welcome | Use only when topic confusing without; 4 rules (no PHI or PII, no secrets, minimal surface area, alt text) | | Timelessness | "Proactive Documentation" pattern (write ahead, reference PR number) | "Documentation lands with the change" plus 3 corollaries; predictive language banned | | Troubleshooting| In-docs H3 pattern | Routes to Support KB (Pilon); embedded widget under investigation | ### Pre-mortem - **`docs-preview` dead link**: known papercut documented in the CI notes above. - **`deploy-docs` over-fire**: addressed by manifest-driven exclusion; the surgical indexer skips non-manifest paths. - **Merge conflict with DOCS-180 `docs/.style/README.md`**: expected to be small and mechanical. Both PRs introduce the same directory and a "What lives here" table; the merge is "combine the rows". - **Merge conflict with DOCS-186**: none expected. DOCS-186 changes `docs/about/contributing/documentation.md`, which this PR does not touch. ### Follow-up tickets filed - **DOCS-358**: Sweep `docs/` for predictive or proactive content that violates the "docs land with the change" rule. - **DOCS-359**: doc-check suggests `redirects.json` entries on doc renames and moves. </details> --- *Generated via Coder Agents.*
This commit is contained in:
@@ -1,6 +1,15 @@
|
||||
# Documentation Style Guide
|
||||
|
||||
This guide documents documentation patterns observed in the Coder repository, based on analysis of existing admin guides, tutorials, and reference documentation. This is specifically for documentation files in the `docs/` directory - see [CONTRIBUTING.md](../../docs/about/contributing/CONTRIBUTING.md) for general contribution guidelines.
|
||||
This guide documents prose, structure, and formatting patterns for documentation files in the `docs/` directory. It complements, and does not replace, the canonical content rules.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> **What belongs in the docs (and what doesn't)** is governed by
|
||||
> [`docs/.style/content-guidelines.md`](../../docs/.style/content-guidelines.md).
|
||||
> Read that first. When this style guide conflicts with the content
|
||||
> guidelines, the content guidelines govern. This file covers prose,
|
||||
> formatting, and structural conventions only.
|
||||
|
||||
See [CONTRIBUTING.md](../../docs/about/contributing/CONTRIBUTING.md) for general contribution guidelines.
|
||||
|
||||
## Research Before Writing
|
||||
|
||||
@@ -79,32 +88,23 @@ Use bold labels for capabilities, provides high-level understanding before detai
|
||||
- Caption: Use `<small>` tag below images
|
||||
- Alt text: Describe what's shown, not just repeat heading
|
||||
|
||||
### Image-Driven Documentation
|
||||
### Screenshot policy
|
||||
|
||||
When you have multiple screenshots showing different aspects of a feature:
|
||||
Screenshots are governed by the canonical content guidelines. See
|
||||
[Screenshots, used wisely](../../docs/.style/content-guidelines.md#what-belongs-in-the-docs)
|
||||
in `docs/.style/content-guidelines.md`. The short version:
|
||||
|
||||
1. **Structure sections around images** - Each major screenshot gets its own section
|
||||
2. **Describe what's visible** - Reference specific UI elements, data values shown in the screenshot
|
||||
3. **Flow naturally** - Let screenshots guide the reader through the feature
|
||||
- Include a screenshot only when the topic would be confusing without
|
||||
the visual aid.
|
||||
- No PHI or PII.
|
||||
- No internal secrets leaked without obfuscation.
|
||||
- Capture the minimally necessary surface area.
|
||||
- Alt text is always required and must explain the screenshot's
|
||||
purpose for accessibility.
|
||||
|
||||
**Example**: Template Insights documentation has 3 screenshots that define the 3 main content sections.
|
||||
|
||||
### Screenshot Guidelines
|
||||
|
||||
**When screenshots are not yet available**: If you're documenting a feature before screenshots exist, you can use image placeholders with descriptive alt text and ask the user to provide screenshots:
|
||||
|
||||
```markdown
|
||||

|
||||
```
|
||||
|
||||
Then ask: "Could you provide a screenshot of the Template Insights page? I've added a placeholder at [location]."
|
||||
|
||||
**When documenting with screenshots**:
|
||||
|
||||
- Illustrate features being discussed in preceding text
|
||||
- Show actual UI/data, not abstract concepts
|
||||
- Reference specific values shown when explaining features
|
||||
- Organize documentation around key screenshots
|
||||
Do not structure sections around screenshots, and do not insert
|
||||
placeholders for missing screenshots. Those older patterns are
|
||||
superseded by the canonical content guidelines.
|
||||
|
||||
## Content Organization
|
||||
|
||||
@@ -237,29 +237,36 @@ Document exact values from code:
|
||||
|
||||
**CRITICAL**: All documentation pages must be added to `docs/manifest.json` to appear in navigation. Read the manifest file to understand the structure and find the appropriate section for your documentation. Place new pages in logical sections matching the existing hierarchy.
|
||||
|
||||
## Proactive Documentation
|
||||
## Documentation lands with the change
|
||||
|
||||
When documenting features that depend on upcoming PRs:
|
||||
|
||||
1. **Reference the PR explicitly** - Mention PR number and what it adds
|
||||
2. **Document the feature anyway** - Write as if feature exists
|
||||
3. **Link to auto-generated docs** - Point to CLI reference sections that will be created
|
||||
4. **Update PR description** - Note documentation is included proactively
|
||||
|
||||
**Example**: Template Insights docs include `--disable-template-insights` flag from PR #20940 before it merged, with link to `../../reference/cli/server.md#--disable-template-insights` that will exist when the PR lands.
|
||||
This rule lives in the canonical content guidelines. See
|
||||
[Documentation lands with the change](../../docs/.style/content-guidelines.md#documentation-lands-with-the-change)
|
||||
in `docs/.style/content-guidelines.md` for the rule, the definition of
|
||||
"user-facing," the three corollaries, and the experiments-versus-feature-stages
|
||||
distinction.
|
||||
|
||||
## Special Sections
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- **H3 subheadings** for each issue
|
||||
- Format: Issue description followed by solution steps
|
||||
|
||||
### Prerequisites
|
||||
|
||||
- Bullet or numbered list
|
||||
- Include version requirements, dependencies, permissions
|
||||
|
||||
## Sections that don't belong
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
Troubleshooting and failure-mode content routes to the Support
|
||||
knowledge base (Pylon), not the docs. Support is the primary owner;
|
||||
Docs is secondary owner where needed. See the
|
||||
[routing table](../../docs/.style/content-guidelines.md#routing-table)
|
||||
in the canonical content guidelines.
|
||||
|
||||
Don't add a Troubleshooting section to a docs page. If a page would
|
||||
benefit from troubleshooting context, surface it via the embedded
|
||||
Pylon KB widget when that work lands; until then, link out to the
|
||||
relevant Pylon article from the page body.
|
||||
|
||||
## Formatting and Linting
|
||||
|
||||
**Always run these commands before submitting documentation:**
|
||||
|
||||
@@ -5,49 +5,126 @@ description: Checks if code changes require documentation updates
|
||||
|
||||
# Documentation Check Skill
|
||||
|
||||
Review code changes and determine if documentation updates or new documentation
|
||||
is needed.
|
||||
Review code changes and determine if documentation updates or new
|
||||
documentation is needed.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> The **canonical** rules for what belongs in the Coder docs (and what
|
||||
> doesn't) live in
|
||||
> [`docs/.style/content-guidelines.md`](../../../docs/.style/content-guidelines.md).
|
||||
> Read that first. When this skill conflicts with the content
|
||||
> guidelines, the content guidelines govern.
|
||||
|
||||
## Workflow
|
||||
|
||||
1. **Get the code changes** - Use the method provided in the prompt, or if none
|
||||
specified:
|
||||
1. **Get the code changes.** Use the method provided in the prompt, or if
|
||||
none specified:
|
||||
- For a PR: `gh pr diff <PR_NUMBER> --repo coder/coder`
|
||||
- For local changes: `git diff main` or `git diff --staged`
|
||||
- For a branch: `git diff main...<branch>`
|
||||
|
||||
2. **Understand the scope** - Consider what changed:
|
||||
2. **Triage the diff.** Walk the
|
||||
[quick decision checklist](../../../docs/.style/content-guidelines.md#quick-decision-checklist)
|
||||
in the content guidelines. Most non-user-facing diffs route out of
|
||||
the docs entirely; see [What not to comment on](#what-not-to-comment-on).
|
||||
|
||||
3. **Understand the scope.** Consider what changed:
|
||||
- Is this user-facing or internal?
|
||||
- Does it change behavior, APIs, CLI flags, or configuration?
|
||||
- Even for "internal" or "chore" changes, always verify the actual diff
|
||||
- Even for "internal" or "chore" changes, always verify the actual
|
||||
diff.
|
||||
|
||||
3. **Search the docs** for related content in `docs/`
|
||||
4. **Search the docs.** Find related content in `docs/`.
|
||||
|
||||
4. **Decide what's needed**:
|
||||
5. **Decide what's needed.** Consider:
|
||||
- Do existing docs need updates to match the code?
|
||||
- Is new documentation needed for undocumented features?
|
||||
- Or is everything already covered?
|
||||
|
||||
5. **Report findings** - Use the method provided in the prompt, or if none
|
||||
specified, summarize findings directly
|
||||
6. **Report findings.** Use the method provided in the prompt, or if none
|
||||
specified, summarize findings directly.
|
||||
|
||||
## What to Check
|
||||
|
||||
- **Accuracy**: Does documentation match current code behavior?
|
||||
- **Completeness**: Are new features/options documented?
|
||||
- **Completeness**: Are new features or options documented?
|
||||
- **Examples**: Do code examples still work?
|
||||
- **CLI/API changes**: Are new flags, endpoints, or options documented?
|
||||
- **Configuration**: Are new environment variables or settings documented?
|
||||
- **Breaking changes**: Are migration steps documented if needed?
|
||||
- **Premium features**: Should docs indicate `(Premium)` in the title?
|
||||
- **Premium features**: See [Premium feature signaling](#premium-feature-signaling)
|
||||
below.
|
||||
- **Renames or moves**: See [Renames and moves require redirects](#renames-and-moves-require-redirects)
|
||||
below.
|
||||
|
||||
## What not to comment on
|
||||
|
||||
Do not produce sticky-comment suggestions for these classes of change.
|
||||
They have no user-visible documentation surface.
|
||||
|
||||
- **Auto-generated CLI docs** under `docs/reference/cli/`. These are
|
||||
generated from Go code under `cli/`; suggest edits to the CLI
|
||||
definitions instead.
|
||||
- **Internal-only refactors** with no user-visible behavior change.
|
||||
- **Test-only changes** (new tests, refactored tests, fixtures).
|
||||
- **CI, release, or tooling commits** that don't change user-facing
|
||||
surfaces. This includes workflow YAML, Makefile internals, formatter
|
||||
configs, and lint configs.
|
||||
- **Dependency bumps** without behavior changes.
|
||||
- **Pure code reorganizations** (moves, renames, package restructuring
|
||||
with no API or behavior change).
|
||||
- **Features guarded by an unsafe experiment flag.** Features behind an
|
||||
unsafe experiment are not designed for users yet and may be reverted.
|
||||
See
|
||||
[Experiments versus feature stages](../../../docs/.style/content-guidelines.md#experiments-versus-feature-stages)
|
||||
in the content guidelines for the experiment-vs-stage distinction. A
|
||||
safe experiment or an Early Access feature does need at least a
|
||||
single-page doc, so don't apply this rule to those.
|
||||
|
||||
If a diff is a mix of one of the above with a user-facing change, comment
|
||||
only on the user-facing portion.
|
||||
|
||||
## Key Documentation Info
|
||||
|
||||
- **`docs/manifest.json`** - Navigation structure; new pages MUST be added here
|
||||
- **`docs/reference/cli/*.md`** - Auto-generated from Go code, don't edit directly
|
||||
- **Premium features** - H1 title should include `(Premium)` suffix
|
||||
- **`docs/manifest.json`** is the navigation structure; new pages MUST be
|
||||
added here.
|
||||
- **`docs/reference/cli/*.md`** is auto-generated from Go code. Don't
|
||||
edit directly.
|
||||
- **`docs/.style/content-guidelines.md`** is the canonical source for
|
||||
what belongs in the docs.
|
||||
|
||||
## Coder-Specific Patterns
|
||||
### Premium feature signaling
|
||||
|
||||
A page documenting a Premium feature requires **both** of the following.
|
||||
Missing either one is a defect:
|
||||
|
||||
1. The H1 title takes a `(Premium)` suffix. Example:
|
||||
`# Template Insights (Premium)`.
|
||||
2. The page's `docs/manifest.json` entry includes `"state": ["premium"]`.
|
||||
|
||||
### No emdash, endash, or ` -- ` as punctuation
|
||||
|
||||
This applies in docs prose, code blocks, comments, and string literals.
|
||||
Use commas, semicolons, or periods, or restructure the sentence. For
|
||||
numeric ranges, use a plain hyphen (e.g., `0-100`). The rule is enforced
|
||||
by `make lint/emdash`, but the doc-check skill should also flag
|
||||
violations it generates or suggests.
|
||||
|
||||
### Renames and moves require redirects
|
||||
|
||||
Redirects for [coder.com/docs](https://coder.com/docs) are configured in
|
||||
a separate repo, not in this one. When a doc page is renamed or moved:
|
||||
|
||||
1. Update every link that relies on the old location.
|
||||
2. Add an entry to
|
||||
[`coder/coder.com:redirects.json`](https://github.com/coder/coder.com/blob/master/redirects.json)
|
||||
that maps the old path to the new one. Open that PR alongside the
|
||||
`coder/coder` rename PR.
|
||||
|
||||
Do not create a `docs/_redirects` file in this repo; that format isn't
|
||||
processed by coder.com.
|
||||
|
||||
## Coder-specific patterns
|
||||
|
||||
### Callouts
|
||||
|
||||
@@ -66,9 +143,9 @@ Use GitHub-Flavored Markdown alerts:
|
||||
|
||||
### CLI Documentation
|
||||
|
||||
CLI docs in `docs/reference/cli/` are auto-generated. Don't suggest editing them
|
||||
directly. Instead, changes should be made in the Go code that defines the CLI
|
||||
commands (typically in `cli/` directory).
|
||||
CLI docs in `docs/reference/cli/` are auto-generated. Don't suggest
|
||||
editing them directly. Changes should be made in the Go code that
|
||||
defines the CLI commands (typically the `cli/` directory).
|
||||
|
||||
### Code Examples
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ Rule #1: If you want exception to ANY rule, YOU MUST STOP and get explicit permi
|
||||
- Observability and isolation: Use [Observability Guide for Agents](.claude/docs/OBSERVABILITY.md) for logs, tracing, and metrics, and [Development Isolation Guide for Agents](.claude/docs/DEV_ISOLATION.md) for ports, state, readiness, and cleanup.
|
||||
- Failures: Use [Agent Failure Catalog](.claude/docs/AGENT_FAILURES.md) for repeatable failure formats and seeded diagnostics.
|
||||
- Language and area docs: Use [Modern Go](.claude/docs/GO.md), [Testing Patterns and Best Practices](.claude/docs/TESTING.md), [Database Development Patterns](.claude/docs/DATABASE.md), [OAuth2 Development Guide](.claude/docs/OAUTH2.md), [Coder Architecture](.claude/docs/ARCHITECTURE.md), [Troubleshooting Guide](.claude/docs/TROUBLESHOOTING.md), [Documentation Style Guide](.claude/docs/DOCS_STYLE_GUIDE.md), and [Pull Request Description Style Guide](.claude/docs/PR_STYLE_GUIDE.md) when that area is in scope.
|
||||
- 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/`.
|
||||
|
||||
@@ -212,7 +213,8 @@ manually before starting work:
|
||||
- `.claude/docs/PR_STYLE_GUIDE.md` - PR description format (when writing PRs)
|
||||
- `.claude/docs/OAUTH2.md` - OAuth2 and RFC compliance (when touching auth)
|
||||
- `.claude/docs/TROUBLESHOOTING.md` - common failures and fixes (when stuck)
|
||||
- `.claude/docs/DOCS_STYLE_GUIDE.md` - docs conventions (when writing `docs/`)
|
||||
- `.claude/docs/DOCS_STYLE_GUIDE.md` - docs prose and formatting (when writing `docs/`)
|
||||
- `docs/.style/content-guidelines.md` - canonical content scope and routing rules (when writing `docs/`; governs on conflicts with the style guide)
|
||||
|
||||
**For frontend work**, also read `site/AGENTS.md` before making any changes
|
||||
in `site/`.
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
# `docs/.style/`
|
||||
|
||||
Contributor-facing style and content guidance for the Coder documentation.
|
||||
Nothing under this directory is published to
|
||||
[coder.com/docs](https://coder.com/docs).
|
||||
|
||||
## What lives here
|
||||
|
||||
| Path | Purpose |
|
||||
|-------------------------|---------------------------------------------------------------------|
|
||||
| `content-guidelines.md` | Canonical content rules: what belongs in `docs/`, what doesn't, why |
|
||||
|
||||
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.
|
||||
|
||||
## 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.
|
||||
|
||||
## How exclusion from coder.com works
|
||||
|
||||
[coder.com/docs](https://coder.com/docs) routes and search are
|
||||
manifest-driven:
|
||||
|
||||
- Route discovery lives in
|
||||
[`coder/coder.com:src/utils/docs/docs.ts`](https://github.com/coder/coder.com/blob/master/src/utils/docs/docs.ts)
|
||||
(`getDocsStaticPaths`). It iterates `routes` from `docs/manifest.json`
|
||||
and emits one Next.js static path per entry. Files not in the manifest
|
||||
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.
|
||||
|
||||
Net result: not adding anything from `docs/.style/` to `docs/manifest.json`
|
||||
gives us no route, no Algolia record, and no sidebar entry.
|
||||
|
||||
## What still runs against this directory
|
||||
|
||||
- `make lint/markdown` (markdownlint-cli2) processes every Markdown file
|
||||
here. The repo-root `package.json` invokes
|
||||
`markdownlint-cli2 --fix $(find docs -name '*.md')`.
|
||||
- `make fmt/markdown` (markdown-table-formatter) reflows tables here for
|
||||
the same reason.
|
||||
|
||||
## 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.
|
||||
@@ -0,0 +1,403 @@
|
||||
# Coder Docs Content Guidelines
|
||||
|
||||
> [!NOTE]
|
||||
> This is the **canonical** guidance for what belongs in the Coder
|
||||
> documentation under `docs/` (published to
|
||||
> [coder.com/docs](https://coder.com/docs)) and what doesn't. It applies to
|
||||
> both human contributors and any LLM-assisted workflow that touches the
|
||||
> docs. When this file conflicts with another style or contributing
|
||||
> document in the repository, this file governs.
|
||||
|
||||
## How to use this guide
|
||||
|
||||
When you have a candidate change for the docs, apply these rules in order:
|
||||
|
||||
1. Walk the [quick decision checklist](#quick-decision-checklist) to triage
|
||||
the content.
|
||||
2. If the checklist routes the content away from the docs, find the
|
||||
correct home in the [routing table](#routing-table).
|
||||
3. If the content does belong in the docs, follow the
|
||||
[guiding principles](#guiding-principles), the
|
||||
[what belongs](#what-belongs-in-the-docs) catalog, and the
|
||||
[structural rules](#structural-rules).
|
||||
4. If you're still unsure, file a question in the DOCS project in Linear or
|
||||
tag `@vigilante` on a draft PR. Don't guess.
|
||||
|
||||
## Quick decision checklist
|
||||
|
||||
Triage a piece of content fast. If any answer routes you away from the
|
||||
docs, see the [routing table](#routing-table) for the correct destination.
|
||||
|
||||
1. Does it describe how the product works or how to use it, from the end
|
||||
user's perspective? **Likely docs.**
|
||||
2. Is it announcing, celebrating, or explaining the motivation behind a
|
||||
feature? **Blog**, not docs.
|
||||
3. Is it a record of what changed in a release (including performance
|
||||
improvements and bug fixes)? **Changelog**, not docs.
|
||||
4. Is it about what to do when the product fails or misbehaves?
|
||||
**Support KB (Pylon)**, not docs.
|
||||
5. Is it about contributing to the Coder codebase or writing style?
|
||||
**GitHub** (or public Notion), not docs.
|
||||
6. Is it already documented by a third-party vendor (Terraform, AWS,
|
||||
Azure, GCP, etc.)? **Link to their docs**, don't duplicate.
|
||||
7. Is it relevant only to a past or hypothetical future version? **Doesn't
|
||||
belong**; keep docs scoped to the version they describe.
|
||||
|
||||
## Guiding principles
|
||||
|
||||
### Follow the Diátaxis framework
|
||||
|
||||
The docs follow the [Diátaxis framework](https://diataxis.fr/). Every page
|
||||
should be identifiable as one of:
|
||||
|
||||
- a tutorial,
|
||||
- a how-to guide,
|
||||
- a reference, or
|
||||
- an explanation,
|
||||
|
||||
and should not mix those modes within a single page.
|
||||
|
||||
*Why:* Diátaxis gives both writers and readers a predictable structure,
|
||||
and gives the team a vocabulary for detecting when a page has drifted out
|
||||
of its lane.
|
||||
|
||||
### Describe the current version, for the end user
|
||||
|
||||
Every page should be accurate for the specific product version it applies
|
||||
to, and oriented around what the user sees, types, and gets back.
|
||||
|
||||
*Why:* Most users care about direct inputs and outputs ("if I enable
|
||||
setting X, I see Y"), not how Coder is implemented internally.
|
||||
Version-scoped content is also what makes drift detectable and testable.
|
||||
|
||||
### Programmatic content is a testable CI surface
|
||||
|
||||
Tutorials and how-to guides that include CLI commands (or chained
|
||||
commands) must state the expected output, so correctness can be verified
|
||||
automatically.
|
||||
|
||||
*Why:* If we can run it, we can detect drift. Untestable claims rot
|
||||
silently.
|
||||
|
||||
### Verify against the code; document exact values
|
||||
|
||||
Docs claims should be checked against the actual implementation, not
|
||||
approximations:
|
||||
|
||||
- Exact RBAC action names. Example: `template:view_insights`, not "view
|
||||
insights".
|
||||
- Real thresholds and defaults. Example: `green < 150ms, yellow 150-300ms,
|
||||
red ≥300ms`, not "around 150 ms".
|
||||
- Full API paths. Example: `/api/v2/insights/templates`, not
|
||||
`/insights/templates`.
|
||||
|
||||
*Why:* Precise values are what make accuracy checkable; "roughly 5
|
||||
minutes" can't drift-fail, but `300s default` can.
|
||||
|
||||
### Documentation lands with the change
|
||||
|
||||
A PR that introduces or changes a user-facing feature should include the
|
||||
documentation for it, in the same PR, or land at the same time.
|
||||
|
||||
A feature is **user-facing** once it's visible by default: it appears in
|
||||
`--help` output for a CLI command, in the UI under a section, in a public
|
||||
API listing, or in a public configuration surface. A backend or API
|
||||
change that's technically possible but not exposed to users by default,
|
||||
including anything guarded by an unsafe experiment flag, doesn't qualify
|
||||
until it's visible. See
|
||||
[Experiments versus feature stages](#experiments-versus-feature-stages)
|
||||
below for the experiment-vs-stage distinction.
|
||||
|
||||
*Why:* Docs written at PR time are written while the behavior is freshest
|
||||
and are verifiable against the diff. Tying the docs bar to default
|
||||
visibility keeps backend-only plumbing PRs out of the docs queue.
|
||||
|
||||
Three corollaries:
|
||||
|
||||
1. **Features that introduce or change behavior get documented in the PR
|
||||
that introduces or changes them.** Don't merge a behavior change
|
||||
without the matching doc update.
|
||||
2. **Features that are not yet confirmed to exist do not get documented.**
|
||||
No speculative docs for unmerged or uncommitted work.
|
||||
3. **Multi-PR launch exception.** For a body of work that spans several
|
||||
PRs and is spec'd to launch together by a particular date, docs may be
|
||||
written ahead of those merges, in the present tense, describing the
|
||||
feature as it will exist at launch. They must never read as a promise
|
||||
of what's coming. No "will support", "in a future release", "coming
|
||||
soon", or roadmap framing.
|
||||
|
||||
### Experiments versus feature stages
|
||||
|
||||
Coder has two related but distinct concepts. Don't conflate them:
|
||||
|
||||
- **Experiments** are the feature flagging system: the `--experiments`
|
||||
flag on `coder server` and the `CODER_EXPERIMENTS` environment
|
||||
variable. An experiment is either *safe* (ready for users to try) or
|
||||
*unsafe* (active development, not designed for users at all).
|
||||
- **Feature stages** describe how production-ready a feature is: Early
|
||||
Access, Beta, or General Availability. See
|
||||
[Feature stages](../../install/releases/feature-stages.md).
|
||||
|
||||
Practical impact for docs:
|
||||
|
||||
- **Unsafe experiments** don't need docs. The feature is in active
|
||||
development, hidden behind a flag the user wouldn't enable on a real
|
||||
deployment, and may be reverted at any time.
|
||||
- **Safe experiments and Early Access features** need at least a single
|
||||
docs page covering how to enable the feature, what it does, and known
|
||||
limitations.
|
||||
- **Beta features** get full docs (how to use, configure, and operate),
|
||||
with the `Beta` label.
|
||||
- **GA features** get full docs across reference, tutorials, and guides
|
||||
as appropriate.
|
||||
|
||||
*Why:* Holding unsafe-experiment PRs to the docs bar is noise. Holding
|
||||
Early Access or Beta PRs to a lower bar is drift.
|
||||
|
||||
## What belongs in the docs
|
||||
|
||||
Use this catalog with the [quick decision checklist](#quick-decision-checklist)
|
||||
above. Each entry includes the reason it belongs in the docs.
|
||||
|
||||
- **Tutorials that touch programmatic aspects of the product.** "If I run
|
||||
this group of CLI commands, what's supposed to happen?" and "How do I do
|
||||
X in the product?", each written so it can become a testable, verifiable
|
||||
CI surface.
|
||||
|
||||
*Why:* A true tutorial serves the user's study and informs action; it
|
||||
teaches the right way to use a command in an approachable, no-risk way
|
||||
that a bare reference page can't.
|
||||
|
||||
- **Explanations of features with a direct, noticeable impact on how users
|
||||
interact with the product.**
|
||||
|
||||
*Why:* If a feature changes what the user sees or does, the docs must
|
||||
explain how it's supposed to work.
|
||||
|
||||
*Exception:* Performance improvements belong in the changelog or blog,
|
||||
since they don't change how the user interacts with the product.
|
||||
|
||||
- **Supported integrations, providers, and APIs.** Examples: the Slack
|
||||
integration, GitHub Actions, Bedrock vs. Claude as model providers.
|
||||
|
||||
*Why:* Users need an authoritative answer to "does Coder work with X?",
|
||||
and this is a high-drift area worth actively monitoring.
|
||||
|
||||
- **New features that add genuine net-new value.** New UI sections, and
|
||||
new CLI commands or flags (e.g., key expiration policy for Coder
|
||||
secrets), including expected command flags and output.
|
||||
|
||||
*Why:* Net-new surface area is undocumented by definition; documenting
|
||||
expected flags and output also feeds the testable-CI-surface goal.
|
||||
|
||||
- **Configuration surfaces.** New environment variables, server flags, and
|
||||
settings must be documented when they ship.
|
||||
|
||||
*Why:* Configuration is product surface area just like the UI and CLI.
|
||||
If a setting changes behavior, users need an authoritative description
|
||||
of it.
|
||||
|
||||
- **Coder's own API endpoints.** New or changed endpoints must be
|
||||
documented with full, correct paths. Example: `/api/v2/insights/templates`,
|
||||
never `/insights/templates`.
|
||||
|
||||
*Why:* The API is a first-class user surface, and imprecise paths are a
|
||||
drift vector. This is distinct from the third-party integrations rule
|
||||
above, which is about compatibility with external services.
|
||||
|
||||
- **Breaking changes and migration steps.** When a change breaks existing
|
||||
behavior, the docs must cover the migration path for the current
|
||||
version's upgrade.
|
||||
|
||||
*Why:* Migration steps for getting onto the current version are
|
||||
current-version content. They describe what a user on this version must
|
||||
do, so they don't violate the version-scoping principle. Once a
|
||||
migration path is no longer relevant to the supported upgrade path, it
|
||||
ages out like any other stale content.
|
||||
|
||||
- **Tutorials and guides that go beyond an API reference.** Walkthroughs
|
||||
using the CLI (or chained commands) with expected outputs.
|
||||
|
||||
*Why:* Reference docs tell users what exists; guides teach them how to
|
||||
accomplish something with it.
|
||||
|
||||
- **Minimal teaching examples of Terraform, with ample links to
|
||||
HashiCorp's docs.**
|
||||
|
||||
*Why:* This is a deliberate exception to the "don't duplicate
|
||||
third-party docs" rule. Solutions-team experience shows many customers
|
||||
don't know how to write the Terraform needed to build workspaces that
|
||||
satisfy their business requirements. A light sprinkling of Terraform
|
||||
unblocks them; the links keep HashiCorp's docs as the source of truth.
|
||||
|
||||
- **Screenshots, used wisely, never reflexively.** Include a screenshot
|
||||
only when the topic would be confusing without the visual aid. The
|
||||
policy is not "no screenshots"; it is "use screenshots wisely." Every
|
||||
screenshot must follow all of these rules:
|
||||
|
||||
1. No PHI or PII.
|
||||
2. No internal secrets leaked without properly obfuscating the text.
|
||||
3. Capture the minimally necessary surface area. The more area a
|
||||
screenshot includes, the more likely it becomes out of date.
|
||||
4. Alt text is always required, and must properly explain the purpose
|
||||
of the screenshot for accessibility.
|
||||
|
||||
*Why:* Screenshots must be kept up to date and risk going stale if not
|
||||
actively monitored, and users who rely on screen readers or other
|
||||
assistive technology cannot get the same value from screenshots that
|
||||
sighted users can. Each screenshot must earn its place, stay small, and
|
||||
carry alt text that conveys its purpose.
|
||||
|
||||
*Note:* This policy supersedes the older "image-driven documentation"
|
||||
guidance (structuring sections around screenshots, inserting
|
||||
placeholders for missing screenshots). It may be loosened if automated
|
||||
screenshot generation becomes real (see
|
||||
[Open items](#open-items)).
|
||||
|
||||
## Structural rules
|
||||
|
||||
These govern *how* content enters the docs, for both humans and the
|
||||
doc-check agent.
|
||||
|
||||
- **Every new page must be added to `docs/manifest.json`.** Pages not in
|
||||
the manifest don't appear in navigation and effectively don't exist on
|
||||
[coder.com/docs](https://coder.com/docs).
|
||||
- **Never hand-edit auto-generated content.** Files under
|
||||
`docs/reference/cli/` are generated from Go code; changes go in the CLI
|
||||
definitions (typically under `cli/`), then regenerate. Generated
|
||||
sections are marked with `<!-- Code generated ... DO NOT EDIT -->`.
|
||||
- **Premium features are marked explicitly.** Both of the following are
|
||||
required for a Premium page:
|
||||
1. The H1 title takes a `(Premium)` suffix. Example: `# Template
|
||||
Insights (Premium)`.
|
||||
2. The page's `docs/manifest.json` entry gets `"state": ["premium"]`.
|
||||
- **Moving or renaming a page requires link updates and a redirect.** If
|
||||
a page changes its position in the directory structure:
|
||||
1. Update every link that relies on its existing location.
|
||||
2. Add a redirect in the
|
||||
[`coder/coder.com`](https://github.com/coder/coder.com/blob/master/redirects.json)
|
||||
repo (`redirects.json`).
|
||||
|
||||
Do not create a `docs/_redirects` file. That format isn't processed by
|
||||
[coder.com](https://coder.com).
|
||||
- **No emdash, endash, or ` -- ` as punctuation.** This applies in docs
|
||||
prose, code blocks, comments, and string literals. Use commas,
|
||||
semicolons, or periods, or restructure the sentence. For numeric
|
||||
ranges, use a plain hyphen (e.g., `0-100`). The rule is enforced by
|
||||
`make lint/emdash`.
|
||||
|
||||
## What does not belong in the docs
|
||||
|
||||
Use this catalog alongside the [routing table](#routing-table). Each entry
|
||||
includes the destination and the reason.
|
||||
|
||||
- **Contributing guides.** Route to GitHub directly, or possibly a public
|
||||
Notion site.
|
||||
|
||||
*Why:* The number of people contributing to the Coder codebase is a
|
||||
small fraction of the number of people using the product; this content
|
||||
isn't relevant to end users.
|
||||
|
||||
- **Style guides (including the docs style guide).** Route to GitHub,
|
||||
alongside the code.
|
||||
|
||||
*Why:* Style rules share the same logic and audience as contribution
|
||||
guidelines, and keeping docs style with the product reduces friction
|
||||
for the CI workflows that will eventually enforce it.
|
||||
|
||||
- **Support and troubleshooting content.** Route to the support
|
||||
knowledge base (Pylon). Troubleshooting documentation is primarily
|
||||
owned by Support, with Docs as secondary owner where needed.
|
||||
|
||||
*Why:* The docs explain how the product works and how to use it; the
|
||||
KB covers what to do when things go wrong. Support should own the
|
||||
content they produce.
|
||||
|
||||
*Connection point:* Docs pages should surface relevant Pylon KB
|
||||
articles via an embedded widget, scoped to the section or page. This
|
||||
keeps docs and support content separate while still giving users quick
|
||||
answers to troubleshooting questions in context. (Implementation under
|
||||
investigation.)
|
||||
|
||||
- **Bugs where the desired behavior isn't already documented.** Route to
|
||||
changelog.
|
||||
|
||||
*Why:* The docs shouldn't highlight product deficiencies.
|
||||
|
||||
*Exception:* When the behavior is bad, Coder itself agrees it's bad,
|
||||
and the docs don't yet cover what's *supposed* to happen, document the
|
||||
expected behavior and/or best practices for configuring around the
|
||||
problem.
|
||||
|
||||
- **Timeless, predictive, or stale content.** Only content relevant to
|
||||
the specific version a doc applies to belongs in that doc.
|
||||
|
||||
*Why:* Don't predict the future; don't carry forward material that no
|
||||
longer applies. Version-scoped content is what keeps the docs
|
||||
trustworthy and drift-detectable. See the multi-PR launch exception in
|
||||
[Documentation lands with the change](#documentation-lands-with-the-change).
|
||||
|
||||
- **Feature announcements and launch rationale.** Route to blog.
|
||||
|
||||
*Why:* Announcing a feature, or explaining in a casual voice *why* it
|
||||
was launched, is marketing and storytelling. Explaining how the feature
|
||||
is *supposed to work* is docs.
|
||||
|
||||
- **Deep internals of how the code works.** Focus on how the product
|
||||
changes for the end user instead.
|
||||
|
||||
*Why:* Most users don't care how Coder's code is written; they care
|
||||
about inputs and outputs.
|
||||
|
||||
- **Duplicated third-party documentation** (Terraform, Amazon, Microsoft,
|
||||
Google, other vendors). Link to their docs instead.
|
||||
|
||||
*Why:* Vendor docs are the source of truth; ours would immediately
|
||||
start drifting from them.
|
||||
|
||||
*Exception:* Minimal Terraform teaching examples, as described in
|
||||
[What belongs in the docs](#what-belongs-in-the-docs).
|
||||
|
||||
## Routing table
|
||||
|
||||
When content doesn't belong in the docs, here's where it goes.
|
||||
|
||||
| Content type | Destination | Why |
|
||||
|------------------------------------------|----------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||
| Feature announcements | Blog | Docs are version-scoped and factual; announcements are storytelling |
|
||||
| Launch rationale ("why we built this") | Blog | Casual, narrative voice belongs on the blog |
|
||||
| Performance improvements | Changelog or blog | No change to how the user interacts with the product |
|
||||
| Release-by-release changes | Changelog | The changelog is the record of what changed and when |
|
||||
| Known bugs or undesired behavior | Changelog | Docs shouldn't highlight deficiencies (see exception above) |
|
||||
| Troubleshooting ("when things go wrong") | Support KB (Pylon) | Support is primary owner of failure-mode content (Docs secondary where needed); docs own intended behavior and link to the KB via an embedded widget |
|
||||
| Contributing guides | GitHub (or public Notion) | Audience is contributors, not end users |
|
||||
| Style guides (code and docs) | GitHub, with the codebase | Same audience as contributing guides; enables CI enforcement |
|
||||
| Third-party tool or cloud instructions | Vendor docs (linked) | Vendor docs are the source of truth; ours would drift |
|
||||
| Code internals or implementation detail | Engineering docs (GitHub), if anywhere | End users care about inputs and outputs, not implementation |
|
||||
|
||||
## Open items
|
||||
|
||||
These items have been agreed in principle but the mechanics are still
|
||||
under investigation. Update this section as they land.
|
||||
|
||||
- **In-docs troubleshooting migration.** Tracked in
|
||||
[DOCS-363](https://linear.app/codercom/issue/DOCS-363) (Urgent, cycle
|
||||
4). Audits the existing `## Troubleshooting` sections and dedicated
|
||||
troubleshooting pages under `docs/`, rewrites them for KB voice, and
|
||||
uploads them via the Pylon API. Until that work lands, link out to the
|
||||
relevant Pylon article from the page body; if no Pylon article exists
|
||||
yet, leave the existing inline troubleshooting in place rather than
|
||||
removing it.
|
||||
- **Pylon KB widget implementation.** The direction is decided (embedded
|
||||
widget surfacing relevant KB articles per page or section); the
|
||||
mechanics are still under investigation.
|
||||
- **Automated screenshot generation.** Today, doc-check only analyzes and
|
||||
comments; it creates nothing. The repo has Playwright e2e infrastructure
|
||||
under `site/e2e/`, so an agent workspace generating screenshots is
|
||||
plausible but unproven. If it becomes real, revisit loosening the
|
||||
screenshots policy. Until then, the screenshot rules in
|
||||
[What belongs in the docs](#what-belongs-in-the-docs) govern.
|
||||
- **doc-check redirect suggestions.** When doc-check detects a moved or
|
||||
renamed page, it should suggest the exact `redirects.json` entry for
|
||||
`coder/coder.com` in a code block, so applying it is at most a
|
||||
copy-paste job.
|
||||
Reference in New Issue
Block a user