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.*
20 KiB
Coder Docs Content Guidelines
Note
This is the canonical guidance for what belongs in the Coder documentation under
docs/(published to 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:
- Walk the quick decision checklist to triage the content.
- If the checklist routes the content away from the docs, find the correct home in the routing table.
- If the content does belong in the docs, follow the guiding principles, the what belongs catalog, and the structural rules.
- If you're still unsure, file a question in the DOCS project in Linear or
tag
@vigilanteon 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 for the correct destination.
- Does it describe how the product works or how to use it, from the end user's perspective? Likely docs.
- Is it announcing, celebrating, or explaining the motivation behind a feature? Blog, not docs.
- Is it a record of what changed in a release (including performance improvements and bug fixes)? Changelog, not docs.
- Is it about what to do when the product fails or misbehaves? Support KB (Pylon), not docs.
- Is it about contributing to the Coder codebase or writing style? GitHub (or public Notion), not docs.
- Is it already documented by a third-party vendor (Terraform, AWS, Azure, GCP, etc.)? Link to their docs, don't duplicate.
- 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. 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
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:
- 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.
- Features that are not yet confirmed to exist do not get documented. No speculative docs for unmerged or uncommitted work.
- 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
--experimentsflag oncoder serverand theCODER_EXPERIMENTSenvironment 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.
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
Betalabel. - 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 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:
- No PHI or PII.
- No internal secrets leaked without properly obfuscating the text.
- Capture the minimally necessary surface area. The more area a screenshot includes, the more likely it becomes out of date.
- 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).
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. -
Never hand-edit auto-generated content. Files under
docs/reference/cli/are generated from Go code; changes go in the CLI definitions (typically undercli/), 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:
- The H1 title takes a
(Premium)suffix. Example:# Template Insights (Premium). - The page's
docs/manifest.jsonentry gets"state": ["premium"].
- The H1 title takes a
-
Moving or renaming a page requires link updates and a redirect. If a page changes its position in the directory structure:
- Update every link that relies on its existing location.
- Add a redirect in the
coder/coder.comrepo (redirects.json).
Do not create a
docs/_redirectsfile. That format isn't processed by 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 bymake lint/emdash.
What does not belong in the docs
Use this catalog alongside the 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.
-
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.
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 (Urgent, cycle
4). Audits the existing
## Troubleshootingsections and dedicated troubleshooting pages underdocs/, 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 govern. - doc-check redirect suggestions. When doc-check detects a moved or
renamed page, it should suggest the exact
redirects.jsonentry forcoder/coder.comin a code block, so applying it is at most a copy-paste job.