Skip to main content

Vale style guide

Vale is a command-line prose linter that enforces writing style rules automatically. This portfolio uses Vale with two rule layers: the Microsoft Writing Style Guide as the base, and a custom NimbusWiz ruleset that enforces the controlled vocabulary and voice decisions defined in the Taxonomy.

Configuration: .vale.ini

StylesPath = styles
MinAlertLevel = suggestion

Packages = Microsoft

[*.md]
BasedOnStyles = Microsoft, NimbusWiz

[*.mdx]
BasedOnStyles = Microsoft, NimbusWiz

[docs/technical-documentation/api-reference/*.md]
BasedOnStyles = Microsoft, NimbusWiz
TokenIgnores = (\x60[^\x60]+\x60)

# AI experiments: first-person voice and passive voice are deliberate case-study register
[docs/ai-experiments/*.md]
Microsoft.FirstPerson = NO
Microsoft.Passive = NO

# Persona pages: first-person internal perspective; passive voice is narrative
[docs/information-architecture/personas/*.md]
Microsoft.FirstPerson = NO
Microsoft.Passive = NO

# Journey maps: pedagogical 'we' is appropriate; passive voice is narrative
[docs/information-architecture/journey-maps/*.md]
Microsoft.We = NO
Microsoft.Passive = NO

# IA discussion pages: same rationale as journey maps
[docs/information-architecture/*.md]
Microsoft.We = NO

# Technical documentation: DevOps audience; API terms, system passives, URLs are correct style
[docs/technical-documentation/**]
Microsoft.HeadingAcronyms = NO
Microsoft.GeneralURL = NO
Microsoft.Passive = NO
Microsoft.Vocab = NO
Microsoft.SentenceLength = NO

# Knowledge base (FAQ format): first-person headings and question marks are intentional
[docs/technical-documentation/knowledge-base/*.md]
Microsoft.FirstPerson = NO
Microsoft.HeadingPunctuation = NO

[CHANGELOG.md]
BasedOnStyles = Vale

MinAlertLevel = suggestion means Vale surfaces everything: suggestions, warnings, and errors, not just hard failures.

Per-directory overrides suppress Microsoft rules where they conflict with deliberate stylistic choices.

For portfolio narrative pages (case studies, personas, journey maps, IA discussion), Microsoft.FirstPerson, Microsoft.We, and Microsoft.Passive are suppressed where first-person voice, pedagogical "we", or passive voice is intentional.

For technical documentation, several Microsoft rules are tuned out at the directory level: Microsoft.HeadingAcronyms would flag legitimate API terms, Microsoft.GeneralURL flags valid URLs in code samples, Microsoft.Passive flags system-state descriptions ("the deployment is queued") that read more naturally in passive voice, Microsoft.Vocab blocks legitimate product terms not in its dictionary, and Microsoft.SentenceLength is over-tight for procedural copy that needs full context per step.

For the knowledge base, Microsoft.FirstPerson and Microsoft.HeadingPunctuation are suppressed because FAQ format uses first-person question headings ending in ? ("Where do I find my API key?"), which the rule otherwise flags.

Microsoft Writing Style Guide base

The Microsoft package provides rules for:

  • Passive voice detection
  • Contractions (Microsoft style allows them, and this enforces consistent use)
  • Comma usage and punctuation
  • Heading and list formatting
  • Redundant phrases (in order to, due to the fact that)
  • Bias-free language

The package installs automatically via vale sync when the pipeline runs.

NimbusWiz custom rules

Custom rule files live in styles/NimbusWiz/. I migrated the NimbusWiz-specific product name exceptions (NimbusWiz, Modernization Advisor, GitHub, CI/CD, etc.) to Microsoft.Headings.

Substitutions.yml: Controlled vocabulary

Enforces the preferred terms defined in the taxonomy. Examples:

Flagged termPreferred termLevel
user manualuser guideWarning
the Advisorthe Modernization AdvisorWarning
quirk engineQuirk IntelligenceWarning
please clickclickWarning
it is possible toyou canWarning

When Vale flags a substitution, it suggests the correct replacement inline in the PR review comment. Fixing it's a one-click action in the GitHub UI.

WeakVerbs.yml: Direct instruction enforcement

Flags weak constructions that soften instructions unnecessarily:

you can click → click
you can select → select
simply click → click
feel free to → [remove]
go ahead and → [remove]

This reinforces the second-person-with-context voice: "To X, click Y," not "You can click Y if you want to X."

Running Vale locally

To run Vale before pushing:

# Install Vale (macOS)
brew install vale

# Install the Microsoft package
vale sync

# Run against all docs (*.md only - avoids MDX parser errors)
vale --glob=*.md docs/

# Run against a single file
vale docs/technical-documentation/user-guide/getting-started.md

Example output:

docs/technical-documentation/user-guide/getting-started.md
47:18 warning Use 'user guide' instead of 'user manual'. NimbusWiz.Substitutions
89:1 suggestion 'You can click' is a weak construction. NimbusWiz.WeakVerbs

The --glob=*.md flag matters. Without it, Vale attempts to lint .mdx files and fails with a parser error (E100 [lintMDX] Runtime error) because mdx2vast isn't available in the GitHub Actions runner.

CI workflow scope

The GitHub Actions workflow (vale.yml) runs Vale on every push and pull request to master, scoped to docs/technical-documentation/ only:

files: docs/technical-documentation/

The scope is intentional. Persona pages, journey maps, and AI experiment pages use first-person voice, passive voice, and narrative "we" deliberately. Those directories have per-directory overrides in .vale.ini. Scoping CI to technical-documentation/ keeps the PR check focused on the content where style consistency matters most: the instructional docs a real NimbusWiz user would read.

vale lint
Vale workflow in GitHub

To check the full portfolio locally:

vale --glob=*.md docs/

To replicate the CI check exactly:

vale --glob=*.md docs/technical-documentation/

Vale as a teaching tool

Beyond enforcement, Vale guides contributors who haven't read the taxonomy. A new contributor will receive inline feedback on every PR. The style guide becomes self-documenting.

With automated style enforcement, the rules don't need to be memorised; they're surfaced exactly when and where they're needed.