Docs as Code with Vale

Docs as Code with Vale

The cool way to document


Most of the developer’s time goes into writing and maintaining a codebase. So documenting the same can often feel unnecessary, especially when it’s not a part of the final product.

Docs as Code (DaC) attempts to fix that. Today, we’ll be looking at Vale and how it helps us implement a DaC workflow.

The Origin Story

According to the Agile Manifesto, we value “working software over comprehensive documentation.”

Does that mean you can choose one over the other? Not quite, because it also says, “while there is value in the items on the right, we value the items on the left more.”

What does that indicate? For you to prioritize working software, but not to leave out comprehensive documentation.

Thanks to this line of thinking, DaC was born.

How Does DaC Work?

DaC attempts to merge your documentation with your codebase. It lives with the code and is maintained like code. It even becomes a part of your ticket description, which means without this task, the ticket is incomplete.

This approach has a few benefits:

  • Developers don’t leave their environment to write Docs
  • History of changes
  • Changes added as part of PR makes for easy tracking
  • Incrementally growing the documentation
  • Platform agnostic, docs live in the repo
  • You can leverage various tools to make things easier, faster, and more consistent

By slowly working on the documentation as you write your code, it becomes a part of your day-to-day workflow. Let’s focus on the last point by using Vale.

Note that the following approach may or may not work for you depending on the style of documentation you prefer. If you're looking for purely text-based documentation, this approach will work just fine. DaC is just an idea, the execution is left to us.

What Is Vale?

Vale is a CLI tool you can leverage for your DaC approach. It’s a linter, similar to the ones you use for code, but for regular text.

They use style guides by Microsoft and Google, among others, to ensure that the language follows certain rules. Things like passive voice, weasel words, excess verbiage, and more can be enforced according to the style guide.

You have the freedom to customize the rules as per your requirements, making it a truly versatile tool.

Do note that Vale does not make the changes for you. It tells you what the issues are and where, so you can fix them yourself. On a side note, this will mold you into a better writer.

The Setup

Setting up Vale is simple. We run brew install vale. And that’s it. One of our favorite reasons for using Homebrew. Once Vale has been installed, run vale -h to confirm whether it’s installed correctly.

To run Vale, run vale path/to/ It runs on a variety of file types, including Markdown, which is often a go-to for developers. Its syntax is fairly simple and readable, so it doesn’t take too long to learn.

You can also run Vale on multiple files by running vale --glob="*.md" folder_name. This command runs Vale on all .md files within the folder_name directory. It’s a useful command you’ll need as the documentation grows.

Example Scenario

In this section, we’ll go over an example scenario where Vale is used. This is not meant to be a recommended setup. If you feel this isn’t working for you, feel free to play around a little bit.

The idea is to make Vale work for you, not the other way around.

Project Directory

Vale - Project Directory.png

To get started, let’s fork/download the Vale Boilerplate project. It’s a starting point provided by the creators of Vale, so we don’t worry about the Vale-specific setup.

Here is a basic directory structure we’ve followed for this post, using the Vale Boilerplate.

  • Docs (Contains all of our documentation)
    • Templates (I’ve created some templates here as an example)
      • Components (Here is where we’ll add Component-specific documentation)
  • styles (Comes with the boilerplate project. It contains the Microsoft and write-good style guides, as well as a Vocab folder for our own customizations)
  • .vale.ini (Comes with the boilerplate project. A configuration file for Vale)

Note that there’s no project-specific code here. Since we’re using Vale for documentation and the documentation process is project-agnostic, we have opted to leave out the code for now. The actual content and style of documentation may vary.


For this post, we’re using VS Code, an industry-standard code editor. VS Code supports Markdown out of the box.

Vale - Editor - Markdown Pane.png

Let’s say you have a Markdown file called To the extreme right of the Tabs panel, you’ll see a few icons.

Clicking on the dual paned icon with the magnifying glass will open up a Preview pane on the right, showing you what your Markdown looks like once it’s rendered.

Vale - Editor - Preview.png

This makes it easier to see if what we think and write is the same. The preview pane your movements around the code, by auto-scrolling to the relevant section.

To make things easier, there are a ton of extensions for VS Code that can help with Markdown. We haven’t used any because we want the project to be as vanilla as possible, but we encourage you to explore what the VS Code Marketplace has to offer.

Example Document

Vale - Get Started Template.png

Every project needs a Get Started page. This is where we let other developers know what they need to start the project. It outlines the required steps to be ready.

We use Headings (#, ##) of various levels to provide a good structure. We also use Code Snippets (code) to highlight code. There’s much more you can do. To learn more, you can head over to the MarkdownGuide, where all the syntax and their usages are listed.

Linting with Vale

Now that you have your document let’s run Vale.

vale docs/templates/

This command runs Vale on your []( file, which is inside the docs/templates directory. Running this gives you the following output.

Vale - No Error.png

Did we get zero errors in our first try? Far from it.

We used Vale on this document and brought it down to zero warnings and errors. Vale provides suggestions, too, but they’re disabled by default to avoid getting too many. This can also be tweaked.

Now, let’s introduce some errors. We’re going to add the following text to the end of our document.

This sentence will be written in Passive Voice.

Running Vale after adding that sentence will give you the following output.

Vale - Passive Voice Error.png

You’ll notice a Passive Voice warning. While it’s not inherently bad, passive voice can lead to unclear and weak-sounding sentences. By rewriting them in Active Voice, your sentences sound confident and have more clarity.

Customizing Vale

The Vale Boilerplate is a great place to start. However, you may want to create some rules of your own. Vale allows you to customize the rules to fit your writing style and requirements. Vale’s Documentation tells you everything you need to know, but there’s much to do. We’ll be going through an existing style to see what goes into creating a style.

Existing Style

Vale - Style - ThereIs.png

This is the ThereIs.yml file under the write-good style. There are a few keys here. Let’s break them down.

Extends: Choose the basis for the rule to be applied. In this case, we’re looking for the existence of a particular word. Message: What should be printed in the console as the error message when text violates this rule. Ignorecase: Should the rule be case-sensitive or not? Level: The severity of the mistake. It could be error, warning, or suggestion Raw: This is where you add the content of your rule. In this case, we’re looking for combinations of There is and There are at the beginning of a sentence. You can provide a regex pattern or pass it in plain text.

The idea behind this rule is to start a sentence with the subject, so it’s clearer for the reader.

Though this rule is generally applied in academic writing, it’s a good idea to use it as a commonplace practice. This is why the rule has a level of warning and not error.

Custom Style

To add your own custom style, you need to create a new directory.

Vale - Custom Style - Directory.png

We’ve created a folder called Tech under styles. In the Tech folder, we’ve added a rule file called HelloWorld.yml.

extends: existence
message: "Hello to you too!"
ignorecase: true
level: warning
  - "Hello, World!"

In this file, we’ve added the lines shown above. It looks for the existence of “Hello, World!” in our text and outputs a greeting back.

Next, we need to tell Vale that we’re using this new style guide. To do this, you can head over to .vale.ini and add the name of your folder under BasedOnStyles, like so:

Vale - Vale Ini.png

Now let’s add “Hello, World!” to our text.

Vale - Custom Style - Output.png

You’ll see a warning thrown by the Tech.HelloWorld rule that says “Hello to you too!”.

Obviously, you can do more than that, but that’s the general process and structure you need to follow.


Docs as Code is the agile mindset we use while maintaining documentation. By living with the code, we not only manage it but leverage tools like Vale as well. Vale’s linting of the text provides you with consistency in language by following existing style guides by Microsoft and Google.

By allowing you to customize and add styles of your own, it becomes an essential part of the DaC workflow. This allows developers to write their documentation smoothly, without disconnecting from their natural habitat, the almighty code editor.