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:
Nick Vigilante
2026-06-12 18:38:49 -04:00
committed by GitHub
parent fb24110933
commit ba64724f8a
5 changed files with 605 additions and 58 deletions
+45 -38
View File
@@ -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
![Placeholder: Template Insights page showing weekly active users chart](../../images/admin/templates/template-insights.png)
```
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:**
+96 -19
View File
@@ -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
+3 -1
View File
@@ -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/`.
+58
View File
@@ -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.
+403
View File
@@ -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.