This guide defines Pulumi-specific style rules for our documentation.
It's the repo-specific layer. For brand-level conventions, defer to the Pulumi brand guidelines (see Brand guidelines below); for anything neither covers, fall back to the Google Developer Documentation Style Guide.
This style guide applies to all Hugo content files in this repository.
The following exceptions are specifically excluded from this style guide:
- Non-content files (scripts, configuration, etc.) should follow general best practices for that file type.
- Meta Markdown files (e.g.,
README.md,AGENTS.md) may use different conventions as appropriate.
Brand-level conventions — voice and tone, writing style, typography, logo and visual usage, and color — live in the Pulumi brand guidelines. Precedence, highest first:
- This style guide — repo-specific conventions for this repository's Hugo content.
- Pulumi brand guidelines — brand-wide voice, writing style, and visual rules.
- Google Developer Documentation Style Guide — anything neither covers.
When this guide and the brand guidelines diverge, this guide wins here — but flag the divergence rather than inventing a third convention.
Approved logos and other brand assets come from the self-describing brand asset API (https://brand.pulumi.com/api) — no setup, just fetch the URL. Working in an interactive agent or editor? Installing the Pulumi Brand MCP server puts the full guidelines, logos, palette, and a contrast checker inline.
Pulumi strives to use language that is clear, inclusive, and respectful.
- Avoid ableist terms.
- Instead of crazy, use wild.
- Instead of dummy, use placeholder.
- Avoid unnecessarily gendered language (e.g., use folks, everyone).
- Avoid violent or aggressive terms (e.g., avoid kill).
- Avoid pop-culture references that may not be globally understood.
- Instead of "click," use "select" (or "choose").
- Instead of "go to," use "navigate."
- Avoid directional terms (e.g., "see above"); link directly.
- Avoid words like "easy" or "simple." These judge difficulty and may alienate readers.
- Exactly one H1 (
#) per page, set in front mattertitle. - H1: Title Case.
- H2 and deeper: Sentence case.
- Only increment one heading level at a time (no skipping levels).
- Use capitalization only for proper nouns. For example, use "stack" not "Stack."
- Do not end headings with punctuation, with one exception: headings in a "Frequently asked questions" section may end with
?so the site's FAQPage JSON-LD auto-collector (layouts/partials/schema/collectors/faq-entity.html) detects them as questions. - Headings should be surrounded by blank lines.
Title vs. headings. The brand guide's sentence-case rule governs headings, and it treats the H1 as the page title, not a heading. Title Case for the H1 — rendered from front-matter
title, consistent with the Title Case used for navigation menu items — is therefore in keeping with the Pulumi brand writing-style guidelines, not an exception to them. Sentence case applies to H2 and deeper. Don't "fix" existing H1s to sentence case.
Navigation menu items: Use Title Case for frontmatter menu fields (menu.name, menu.title). Navigation items are UI labels, not prose headings, and follow Title Case conventions consistent with industry standards.
- Internal and external links: use normal Markdown syntax.
[Link text](/path/to/file)[Link text](https://example.com)
- Link text must be descriptive. Avoid vague text like here or click here.
- When changing the URL of an existing page, add a redirect with a Hugo alias.
- Always use root-relative paths (beginning with
/) for all internal links and image references — never page-relative paths like./image.png,../other-page, or bare relative paths likesome-page. Page-relative paths are ambiguous because Hugo content files are sometimes named.mdfiles rather than_index.mdfiles in a folder, making the meaning of./differ between the file's location on disk and the URL the page is served from. Root-relative paths are unambiguous, portable, and don't silently break when files move.- Correct:
[stacks](/docs/iac/concepts/stacks/), - Incorrect:
[stacks](./stacks/),,[stacks](../stacks/)
- Correct:
Links that navigate users to a different UI/experience (different from the main docs site) should include the ↗ (U+2197 North East Arrow) symbol to indicate this transition when linking from navigation menus or landing page cards.
When to use ↗:
- Links to generated API documentation (
/docs/reference/pkg/*) - Links to external sites (e.g., pkg.go.dev)
- Links to Tutorials (different UI)
- Any link that takes users away from the main docs experience
Placement:
- In menu configurations (
config/_default/menus.yml): append to thenamefield with a space- Example:
name: SDK docs ↗
- Example:
- In landing page cards: append to the
headingfield with a space- Example:
heading: Python ↗
- Example:
The symbol is not needed in regular in-text links within documentation pages.
Rationale: The ↗ symbol is the web-standard indicator for external links and helps users understand they're navigating to a different UI, preventing surprise when the page appearance changes.
Every section has an _index.md that the sidebar automatically injects as the first item of the section's submenu. The label it receives — "Overview" or "Introduction" — depends on the page's role.
Use "Overview" for section indexes whose primary purpose is routing readers to child pages, with little or no prose of their own. Add docs_home: true to the frontmatter to mark the page as an overview and enable the section home template.
Required frontmatter:
docs_home: truenotitle: true— suppresses the duplicate H1 (the template renders it fromh1:)norightnav: true— hides the right-hand table of contents (unused on overview pages)h1:— displayed in the page bannerdescription:— short paragraph rendered in the banner (HTML string)sections:— list of section blocks usingtype: cards-logo-label-link,type: button-cards, ortype: flat
See content/docs/iac/_index.md for the canonical example. Never use raw HTML to build navigation tiles or grid layouts.
Use "Introduction" for section indexes that contain substantive prose introducing a topic. No special frontmatter is required; any _index.md without docs_home: true receives this label automatically.
If the page also links to related child pages, use standard markdown (lists, tables) — not raw HTML grids or inline Tailwind classes.
- Use root-relative paths for all image references (see Links above).
- Provide descriptive alt text for all images. Describe the image's content or function in a few words, and omit lead-ins like "image of" or "screenshot of" — screen readers already announce those.
- Name image files descriptively (helps accessibility and SEO); avoid generic names like
screenshot-1.png. - For partial screenshots where the image may be hard to distinguish from the page background, add a 1px gray #999999 border.
Brand assets. Use approved logos from the brand asset API (https://brand.pulumi.com/api); don't recolor, distort, or otherwise alter the logo, and never AI-generate Pulumi brand imagery or the Pulumipus mascot.
Use the {{ notes }} shortcode sparingly. Supported levels:
info— general informationtip— helpful hintswarning— important cautions
Example:
{{% notes type="tip" %}}
This is a useful suggestion.
{{% /notes %}}Hugo supports two shortcode notations:
-
{{% shortcode %}}(percent signs) - Use for shortcodes that process Markdown content. Hugo processes these before Markdown rendering- Examples:
notes,choosable,details
- Examples:
-
{{< shortcode >}}(angle brackets) - Use for shortcodes that output pre-formatted content. Hugo processes these after Markdown rendering- Examples:
cleanup,example
- Examples:
Rule of thumb: If the shortcode uses markdownify internally (check layouts/shortcodes/), use percent signs. Otherwise, use angle brackets.
Both syntaxes work for plain text content, but use percent signs for shortcodes with nested Markdown like lists or headings.
- Separate paragraphs with a blank line.
- Do not use line breaks within paragraphs. Let text wrap naturally.
- Keep paragraphs short (ideally ≤3 sentences).
- Use the Oxford (serial) comma: "build, deploy, and manage," not "build, deploy and manage."
- Use present tense for how the product behaves: "Neo pauses when the limit is reached," not "Neo will pause." Reserve the future tense for events that genuinely happen later.
- Contractions are fine — preferred, even — in docs. They read more naturally.
- Put commas and periods outside closing quotation marks unless they belong to the quoted text — e.g., write
"us-west-2", with the comma outside. - Em-dashes are fine when you write them yourself, but revise away the em-dashes, three-item series, and filler phrasings that LLMs tend to emit — they read as unedited machine output.
For dates, times, numbers, and anything else this guide doesn't specify, defer to the brand writing-style guide. On point of view — the most-missed rule — it uses the second person (you), not the first-person plural (we): in docs, "we aren't doing anything — the reader is." Reserve we for blog and community content.
- Use ordered lists for steps.
- All items should begin with
1.(Markdown will auto-number).
Example:
1. First step
1. Second step
1. Third stepUse fenced code blocks (triple backticks) for all code and console output.
Supported languages for syntax highlighting:
- Language-specific:
typescript,python,go,java,csharp,yaml, etc. - Shell commands:
bash,sh - Console output:
output
Do not use indentation (4 spaces) to denote console output. While technically valid Markdown, indented blocks are difficult for both humans and AI assistants to parse and maintain.
Wrong:
output line 1
output line 2Correct:
```output
output line 1
output line 2
```- Use
bashorshfor commands the user should type - Use
outputfor the resulting console output
Example:
pulumi upUpdating (dev)
...
Rationale: Fenced code blocks are explicit, easy to identify, and support syntax highlighting. Indented blocks can be confused with nested lists or quotes, especially when editing.
Use the hl_lines parameter on fenced code blocks to highlight specific lines with a purple background. This draws attention to the most important lines in a code sample, such as newly added or changed lines.
Single lines and ranges:
```typescript {hl_lines=[3]}
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as vpc from "@pulumi/vpc"; // this line is highlighted
``````python {hl_lines=["3-5"]}
import pulumi
import pulumi_aws as aws
# lines 3 through 5
# are all
# highlighted
```Combined with line numbers:
```typescript {.line-numbers hl_lines=[5,"14-19"]}
// code here
```Use line highlighting when a code block is long but only a few lines are new or noteworthy. Do not highlight every line — if the entire block matters equally, no highlighting is needed.
- Use blockquotes only for direct quotations.
Example:
This is something a person said.
We support two formats:
- GoAT (ASCII diagrams) — good for simple flows.
- Mermaid — supports flowcharts, sequence diagrams, class diagrams, etc.
See Hugo diagrams docs and Mermaid docs.
- Always capitalize Pulumi product names correctly.
- Pulumi IaC (Infrastructure as Code)
- Pulumi ESC (Environments, Secrets, and Configuration)
- Pulumi IDP (Internal Developer Platform)
- Pulumi Insights
- Pulumi Cloud (also Pulumi console / Pulumi Cloud console — but not "Pulumi UI")
- Pulumi Deployments
- Pulumi Neo
- Pulumi Policies
- Expand product acronyms at first mention. Use just the product name after.
- For non-Pulumi acronyms: spell out on first use, then use the acronym.
- Example: Virtual Private Cloud (VPC), then VPC.
- Widely known acronyms (API, HTTP, REST) don’t need expansion.
- Pulumi Policies is the product name, so it's a singular proper noun (like "United States" or "Brooks Brothers").
- Always refer to it in the singular form (e.g., "Pulumi Policies enforces compliance").
- Never refer to it in the plural (e.g., avoid "Pulumi Policies enforce compliance").
- Use "public preview" for pre-GA features, not "public beta." This aligns with Pulumi's release terminology.
- Don't overcapitalize generic concepts, even Pulumi-specific ones. Only proper nouns are capitalized: "stack" (not "Stack"), "environment" (not "Environment"), "token" (not "Token"), "infrastructure as code" (not "Infrastructure as Code") when used as a common noun mid-sentence. This mirrors the Headings rule above and applies to body prose too. It doesn't apply where the capitalized word is itself a proper noun in context — for example, the Pulumi Kubernetes Operator's
Stackcustom resource (a Kubernetes CRD Kind) or apulumicdk.Stackclass identifier.
The Pulumi glossary defines common terms and concepts used throughout the documentation.
- When introducing a new concept or Pulumi-specific term in documentation, consider adding it to the glossary.
- The glossary helps users (both human and AI agents) quickly understand Pulumi terminology.
- To add or update glossary terms, edit
data/glossary.toml. - Link to specific glossary terms using anchor links:
/docs/iac/concepts/glossary/#term-name
The following terms have precise meanings in Pulumi documentation. Use them consistently and prefer them over informal or ambiguous alternatives:
| Term | Definition |
|---|---|
| Native language package | A component published to a language-specific registry (npm, PyPI, NuGet, Maven, etc.) without a Pulumi plugin. Consumable only in the language in which it was authored. |
| Pulumi package | A component or provider packaged with a Pulumi plugin so Pulumi can generate SDKs for any supported language. Consumable in all Pulumi languages. |
Use "Pulumi package" (not "cross-language package") when referring to components or providers distributed with a Pulumi plugin. Use "native language package" (not "single-language package" or "language-native package") when referring to components distributed as standard language packages without a Pulumi plugin.
- CLI commands: wrap in backticks (e.g.,
pulumi up). - UI elements: use bold (e.g., “Go to the Account page”).
- Navigation: use arrows (e.g., Settings → API Keys).
Many pages end with a block of links to other pages. Use one of exactly two headings, chosen by the reader's intent — do not invent variants ("Related resources," "See also," "Additional resources," "What's next," "Further reading," and the like):
- Next steps — the reader should continue in a sequence: the next tutorial, the next step in a getting-started flow, or a recommended follow-on task. Use when there is a natural forward order.
- Learn more — links to related or reference material with no implied order: concept pages, other pages on the same topic, or external references. Use for lateral cross-references.
Rules:
- Use
##(H2), sentence case: Next steps and Learn more, never "Next Steps" or "Learn More." - Place the section at the end of the page.
- Choose by intent, not by page type. A concept page may have Next steps; a tutorial may have Learn more.
- If a page has both sequential and lateral links, use two sections named Next steps and Learn more — don't coin a third heading.
Exempt: the generated SEE ALSO blocks on CLI command pages (content/docs/iac/cli/commands/) and the auto-rendered "Related templates" aside on template pages, which are produced by tooling.
Dedicated FAQ pages have one canonical home: the FAQ hub at /docs/support/faq/, under the Support & Troubleshooting nav section. This placement is intentional. Readers reach for an FAQ when they're in help-seeking mode, and Support & Troubleshooting is the site-wide help destination; keeping the pages together also avoids re-scattering Q&A across product sections. (The per-product FAQs that once lived at /docs/esc/faq/, /docs/insights/policy/faq/, /docs/iac/faq/, and similar paths were deliberately consolidated here — the aliases on the consolidated pages preserve those URLs.)
Rules:
- Dedicated FAQ pages live only under
content/docs/support/faq/, one page per product area (infrastructure.md,secrets-config.md,policies.md, ...), each listed as a card on the hub's_index.mdand placed in thesupportmenu withparent: support-faq. Do not create anfaq.mdinside a product section. - Product sections link in. Surface a product's FAQ from its landing page or a Learn more block (for example, "For common questions, see the FAQ"), not by adding FAQ pages to the product's own nav.
- FAQ is not troubleshooting. "How do I fix this error?" content belongs with the rest of the day-2 material under IaC Operations (Troubleshooting, Debugging) — or, for a Pulumi Cloud feature, on a
troubleshooting.mdpage inside that feature's own section (the SAML and SCIM sections each have one) — not in an FAQ. FAQ pages answer conceptual and product questions ("Does Pulumi support rollbacks?", "How does Pulumi store state?"). - Keep answers canonical. If an answer needs more than a few paragraphs, the full explanation belongs in the topical docs and the FAQ entry gives the short answer plus a link. Don't let an FAQ become the only place something is documented.
- In-page FAQ sections are different. A "Frequently asked questions" H2 near the end of a what-is page, blog post, or product page is a page-level pattern, not part of the FAQ hub, and stays with its page. See Headings for the question-mark exception that lets the FAQPage JSON-LD collector pick those questions up.
- End with a Next steps or Learn more section as appropriate — see Cross-reference sections.
See BLOGGING.md for guidance on writing Pulumi blog posts.
The rules in this guide are enforced — where mechanically possible — by Vale via .vale.ini at the repo root. Custom rules live under styles/Pulumi/ and layer on top of the Google Developer Style Guide and write-good packages. Run locally with make lint-prose. Vale findings also surface in the pinned PR review in two tiers: a small set of near-zero-false-positive correctness rules (wrong or deprecated product names, banned terms, misspellings, grammatical agreement — the blocker: list in .claude/commands/docs-review/scripts/vale-deterministic-fixes.yaml) renders under 🚨 Outstanding and must be resolved or refuted before merging; everything else renders under