blog-main-1
This is human generated content.

Table of contents

A recent project called for a documentation portal, and the discovery call reshaped the engagement before any writing began. The client had scoped me as a content writer: I’d supply the words, and they’d find someone else to build the site. Once it was clear I worked in a docs-as-code workflow, the brief widened to cover both.

We set it up accordingly: Markdown, a static site generator, and a build pipeline running through the client’s existing Azure DevOps infrastructure. The content grew quickly. By the end we had close to 90 files of prose, images, Markdown, and HTML. Naturally, before handing it over, I owed them a final proofread.

But reviewing 90 files by hand is exactly how inconsistencies slip through. The alternative was a linter: a tool that reads every file and flags grammatical and stylistic issues automatically. After comparing proselint and Vale, I picked Vale.

Disclaimer: I installed vale as python package. So, this guide is based on the same assumption that you installed vale’s python package.

Step 1: pip install Vale

After a quick search, I discovered that some kind samaritan had created a python package to install vale. This made the job cleaner and easier. If you haven’t already, run the following command on your terminal window.

pip install vale

Optionally, you can verify whether the installation was successful by running vale -v in the same terminal window.

vale -v

Step 2: create a .vale.ini file

Vale reads its configuration from a .vale.ini file in the root of your documentation. This is the step most people miss, and the reason for the “file not found” error. Create the file and tell Vale where your styles live, the minimum alert level to report, and which style packages to base your checks on.

StylesPath = styles
MinAlertLevel = suggestion
Packages = Microsoft

[*]
BasedOnStyles = Vale, Microsoft

StylesPath is where Vale looks for style packages. By setting this configuration to styles, you are telling vale to create a new directory — styles — in the root directory. This directory should have the style guide you wish to use.

MinAlertLevel sets the minimum severity Vale reports, from suggestion through warning to error.

Packages lists the pre-built style packages to pull in, such as the Google or Microsoft Style Guide. Simply use Packages = Microsoft to pull in the Microsoft style package, which is a can also serve as a default for your technical writing needs.

BasedOnStyles applies those styles to the files matched by the section.

Now, this is not an exhaustive list of configuration. Check out vale’s documentation site for a complete list of configurations.

Step 3: vale sync

Run vale sync to download the style packages named in your config into your StylesPath. Without this step Vale has the rules named but not the actual style files.

vale sync

Step 4: run Vale

Now you can lint. Point Vale at a single file, or at the whole directory.

To run vale on a single file, use the following command.

vale path/to/file.md

To run vale on all the files at once, use the following command

vale .

You will see the output of these commands in the terminal window.

Sample vale output

Step 5: (optional) advanced setup: building a custom style

The Microsoft package was a great way to start, but it didn’t take long on that documentation portal before I hit a wall. The client had their own quirks. They had a handful of words they never wanted used, product terms spelled a particular way, phrasing they’d rather avoid. A borrowed style guide can’t know any of that. It enforces someone else’s rules, not yours.

That’s where building your own in-house style comes in. And the good news is that it’s far less work than it sounds.

A style is just a folder of rules under your StylesPath, and each rule is a small YAML file. Two rule types cover most of what a team actually needs: substitution (flag a word, suggest a better one) and existence (forbid a word outright). Let me show one of each.

A substitution rule

Create a folder for your own style — I’ll called mine Studio, but use your team or client name — and add a file at styles/Studio/Wordiness.yml:

  extends: substitution
  message: "Prefer '%s' over '%s'."
  level: warning
  ignorecase: true
  swap:
    utilise: use
    utilize: use
    in order to: to
    leverage: use
    functionality: features

The swap map is the whole rule: the word on the right is what you want, the word on the left is what vale flags. The %s placeholders in the message get filled in automatically.

An existence rule

Some words you just want gone. Here’s one I use to catch language that can sound dismissive in a tutorial — styles/Studio/Condescending.yml:

  extends: existence
  message: "Avoid '%s'; it can sound dismissive to a reader who's stuck."
  level: suggestion
  ignorecase: true
  tokens:
    - simply
    - just
    - obviously
    - of course
    - easy

tokens is simply the list of words to flag. vale has more rule types — occurrence, repetition, capitalization, and others — but these two will take you a long way.

Switch your style on

Add your style to the BasedOnStyles line in the .vale.ini you created in Step 2:

  [*]
  BasedOnStyles = Vale, Microsoft, Studio

One thing that tripped me up: unlike the Microsoft package from Step 3, custom styles you wrote yourself don’t need vale sync. They already live in your StylesPath, so vale picks them up the moment you run it.

And that’s an in-house style in a few minutes, using the same handful of decisions your reviewers keep repeating, now enforced automatically.

Conclusion

Four steps get you from a fresh install to a working lint run: install Vale, create a .vale.ini, sync your styles, then run it. The configuration step is the one that trips people up, so once that file is in place the rest is straightforward. Happy linting.

Work with Weesho Lapara

Want Vale wired into your docs pipeline and CI with a style guide your team agrees on? If you’d like to automate enforcement on pull requests, see our guide on using Vale as a GitHub Actions merge gate. Book a consult or get in touch.

Additional resources

Frequently asked questions

  • Vale needs a .vale.ini configuration file in your project root before it can run. Running a vale command before creating that file is the most common cause of the error.

  • At minimum a StylesPath, a MinAlertLevel, the style packages you want such as Microsoft, and a section that sets BasedOnStyles for the files you are linting.

  • After running vale sync to download your style packages, run vale followed by a dot to lint the whole directory, or vale with a file path to check a single file.