Files
coder/docs/admin/templates/index.md
T
Nick Vigilante f7632451f4 feat(docs): add Coder.BrandNames Vale rule, enforce HashiCorp casing (#25501)
Lands the first concrete rule under the `Coder` style:
`Coder.BrandNames`, a bundled `substitution` rule that enforces
canonical brand casing in prose. HashiCorp is the first entry;
[DOCS-188](https://linear.app/codercom/issue/DOCS-188) extends it with
GitHub, OpenTofu, Kubernetes, Terraform, JetBrains, and VS Code.

## What changes

Four commits, ordered so each is independently valid:

1. **`docs: fix HashiCorp casing in prose and sidebar`**
([06d769dad1](https://github.com/coder/coder/pull/25501/commits/06d769dad179cf85c535b058df3b6bafdc1f9565)).
5 Markdown files plus 2 `docs/manifest.json` entries. Drives the corpus
violation count to zero.
2. **`feat(docs/.style/styles/Coder): add Coder.BrandNames Vale rule`**
([e00fc780a7](https://github.com/coder/coder/pull/25501/commits/e00fc780a7a20dcf82105d997af5cfcddd4b1855)).
New `BrandNames.yml` with the HashiCorp swap at `level: error`, plus a
new `### Brand names` subsection in `docs/.style/style-guide.md`.
3. **`docs(.style/styles/Coder/README.md): scrub planned-rules notes
obsoleted by Coder.BrandNames`**
([af8833b9f5](https://github.com/coder/coder/pull/25501/commits/af8833b9f58dd617732ae533bbf53eb4fc2e816a)).
Removes the README's "intentionally empty for now" lead-in and the
obsolete HashiCorp casing bullet from the planned-coverage list.
4. **`docs: apply semantic line breaks and fix Vale findings on
PR-touched files`**
([e9f11df188](https://github.com/coder/coder/pull/25501/commits/e9f11df1886fdf0d5efc5e8a2cab95fecbd898f9)).
Pre-review pass on every Markdown file this PR modifies. Full sembr and
Vale-warning cleanup on the style-guide infrastructure
(`style-guide.md`, `Coder/README.md`); sembr applied to the HashiCorp
swap paragraph only on the five product docs, per scoping discussion
with @nickvigilante.

## Severity rationale

`error` from day one. HashiCorp's brand owner publishes a canonical
casing; any other casing in prose is wrong, not a judgment call. Matches
the `error = low FPs x high gravity` framework. False-positive rate is
effectively zero because Vale's `substitution` rule skips inline code,
fenced code blocks, and URLs by default, so `hashicorp/kubernetes`
(Terraform provider source) and `developer.hashicorp.com` stay
untouched.

## Verification

- `make lint/markdown`: 0 errors across 487 files.
- `make lint/prose`: 1 error, 1 warning, 1 suggestion in 468 files. All
three findings are the intentional `Coder.DemoError`,
`Coder.DemoWarning`, and `Coder.DemoSuggestion` annotations on
`docs/.style/style-guide/demo/demo.md` (added on main as part of the
[DOCS-425](https://linear.app/codercom/issue/DOCS-425) inline-annotation
demo), not real findings. `Coder.BrandNames` fires zero times against
the cleaned-up corpus.
- `make pre-commit-light`: passed (7s).
- Self-test: ran the rule against an unmodified `docs/` and confirmed it
flags the 7 prose instances the cleanup commit fixes, then re-ran
against the post-cleanup state and confirmed zero alerts.

## Known future conflict

When [#26632](https://github.com/coder/coder/pull/26632)
([DOCS-434](https://linear.app/codercom/issue/DOCS-434)) merges, the
monolithic `docs/.style/style-guide.md` is split into the
`docs/.style/style-guide/` multi-page structure. The `### Brand names`
subsection added in commit 2 will need to land in
`docs/.style/style-guide/word-choice.md` (which already references the
rule), and the `link:` in `docs/.style/styles/Coder/BrandNames.yml` will
need to update from `style-guide.md#brand-names` to
`style-guide/word-choice.md#brand-names`. Resolution path documented in
an inline comment on this PR.

<details>
<summary>Implementation plan and decision log</summary>

### Why bundle into Coder.BrandNames rather than one file per brand

Vale's convention (mirrored by `Google.WordList` with ~70 swaps in a
single file) is to bundle `substitution` rules when they share severity,
message template, and link. All brand-name rules share that shape:
`error`, `Use '%s' instead of '%s'`, link to the style guide section.
Bundling reduces "add a brand" to a one-line YAML diff and keeps
`CODEOWNERS` and blame coherent. Per-rule performance is irrelevant at
this scale; Vale's per-rule overhead is sub-millisecond and dwarfed by
Markdown parsing.

### Why the cleanup lands first

Commits are ordered cleanup-then-rule so each commit is a known-good
state:

- After commit 1: corpus is HashiCorp-clean, but no rule exists yet.
- After commit 2: rule exists and lints a clean corpus.

Reversing the order would land the rule at commit 1 (firing 7 errors on
uncleaned content) and resolve them at commit 2. Under `--no-exit` the
CI job still passes, but the inline annotations on commit 1 would be
misleading.

### Why HashiCorp first instead of all brands at once

Proof-of-concept value. HashiCorp is the smallest cleanup (7 prose lines
plus 2 sidebar lines = 9 lines), zero FPs, zero ambiguity. Once the loop
(rule plus cleanup plus style-guide section) is proven,
[DOCS-188](https://linear.app/codercom/issue/DOCS-188) appends the other
brands as additional commits to the same bundle.

### Brand-token sensitivity

The `swap:` table only matches:

- `Hashicorp` (capital H, lowercase rest), the actual wrong form in the
corpus.
- `HASHICORP` (all caps), defensive; doesn't appear in current corpus
but cheap to include.

`hashicorp` (all lowercase) is **not** in the swap table. The lowercase
form appears 49 times in URLs (`developer.hashicorp.com`,
`registry.terraform.io/providers/hashicorp/...`,
`github.com/hashicorp/...`) and 6 times as Terraform provider sources
(`source = "hashicorp/kubernetes"`), all of which are correct lowercase
by convention. Vale's substitution rule scope ensures URLs and code
blocks are skipped, but skipping the rule entirely for `hashicorp`
(lowercase) is the explicit decision; if a prose typo of lowercase
"hashicorp" ever shows up, we'd catch it through `Vale.Spelling`
([DOCS-187](https://linear.app/codercom/issue/DOCS-187)) instead.

### Self-reference in the style guide

The `### Brand names` section's example table needed `Hashicorp` and
`HashiCorp` as literal demonstration tokens. Wrapping them in backticks
(`` `Hashicorp` ``, `` `HashiCorp` ``) keeps Vale from flagging the
wrong-case example as a real violation. This is correct typography too:
demonstration tokens get code formatting.

### Manifest.json

Vale doesn't lint JSON, so the two `docs/manifest.json` entries are
fixed by direct edit rather than tool enforcement. The sidebar `path`
(`./admin/integrations/vault.md`) is unchanged; the title change does
not affect the page URL on coder.com. No redirect needed in
`coder/coder.com:redirects.json`.

### Pre-mortem

- **Generated docs noise**: `Coder.BrandNames` does not fire on
auto-generated `docs/reference/` content because no codersdk identifier
matches the swap pattern. Zero risk.
- **Future-additions friction**: adding GitHub to the swap table is one
YAML line and a cleanup commit. The bundling shape pays off here.
- **Disable footgun**: if a contributor needs to write the wrong casing
on purpose (quoting an external bug report verbatim, for example), they
can wrap the literal in backticks (already correct typography) or use
the per-line Vale skip comment.

</details>

Closes [DOCS-34](https://linear.app/codercom/issue/DOCS-34).

---

*Filed via [Coder Agents](https://coder.com/docs/ai-coder/agents) on
Nick's behalf.*
2026-07-08 11:43:29 -04:00

3.1 KiB

Template

Templates are written in Terraform and define the underlying infrastructure that all Coder workspaces run on.

The template builder is the recommended way to create templates. It guides you through selecting base infrastructure, adding modules, and configuring your template without writing Terraform.

Learn the concepts

While templates are written in standard Terraform, it's important to learn the Coder-specific concepts behind templates. The best way to learn the concepts is by creating a basic template from scratch. If you are unfamiliar with Terraform, see HashiCorp's Tutorials for common cloud providers.

Create a template

The fastest way to get started is with the template builder, which composes a working template from a base infrastructure template and optional registry modules. Starter templates for popular platforms (AWS, Kubernetes, Docker, and others) are available as base templates in the builder, or through the CLI.

Extending templates

It's often necessary to extend the template to make it generally useful to end users. Common modifications are:

Learn more about the various ways you can extend your templates.

Best Practices

We recommend starting with a universal template that can be used for basic tasks. As your Coder deployment grows, you can create more templates to meet the needs of different teams.