Modern documentation workflows are becoming increasingly intertwined with the software development workflow. You might track documentation issues in GitHub or Jira, or you might write docs in code comments or Markdown files. The developers on your team might be working directly with technical writers, or they might be writing docs independently. Docs are often stored in code repositories, tested for quality using linters, and published continually on static sites. Technical writers have recently coined the term docs-like-code or docs-as-code to describe this type of workflow.
Docs-as-code is defined by automation. It involves creating, updating, reviewing, and approving documentation using familiar development tools:
- Issue trackers
- Version control tools
- Plain-text files
- Text and code editors
- Static site generators
- Continuous publication
Docs can be stored in the same repositories as the related code, making it easier to ensure docs are updated alongside the code itself.
This workflow is flexible and adaptable to many combinations of tools and methodologies. For illustration purposes, this tutorial develops a docs-as-code workflow for a Rails app using Ruby-based tools, such as Jekyll. The docs are stored alongside the app in GitHub and managed using GitHub issues, labels, projects, and pull request reviews. This example illustrates docs-as-code principles that can be adapted to other tools and integrated into other workflows.
Prerequisites
This guide is intended for developers. You should be familiar with the following tools: Git, code editors, and Markdown. This article describes how to use these tools to create a documentation workflow.
Accompanying this article are a live sample site, hosted by Netlify, and a sample GitHub repository.
To follow along with this article, create a simple blog application in Rails with a few commands:
gem install rails
rails new blog
cd blog
rails generate scaffold Post title:string body:text
In config/routes.rb
, create an index page:
Rails.application.routes.draw do
resources :posts
root 'posts#index'
end
Finally, run a database migration and start the Rails server to check that everything works:
rails db:migrate
rails s
Navigate to localhost:3000
. You should see an empty list of posts and a link to create a new post.
Creating a Content Strategy
Planning is the first step in developing a documentation workflow, just as it is with software. The plan for your docs should include a content strategy, which determines which topics need to be documented and how.
To start developing a content strategy, answer the following questions:
- Who is your intended audience?
- Are they developers, less technical users, or both?
- Are they allowed to contribute to your code or docs?
- Are they internal or external to your company or both?
- What are users trying to accomplish?
- What problems are users trying to solve by consulting your docs?
- How will users consult your docs?
- Would a simple readme be adequate?
- Will users need special permission to access the documentation?
For example, imagine you have a Rails app with an accompanying API. For customers, you might want to develop a public user guide for all of your UI features. A user story might be, "As a user, I want to create a blog post."
You could also create reference documentation for developers. A developer story might be, "As a developer, I want to retrieve all the blog posts of a specific user."
You can use a static site generator, such as Jekyll or WordPress, to present the user docs in a branded, user-friendly environment. For your internal developers, a simple YARD-generated site might be sufficient. This tutorial will show you examples of both.
Documentation can also be integrated into your current workflow. For example, if your team writes code in 2-week sprints, consider managing your documentation on the same schedule.
You can also track documentation issues alongside code issues. Create an issue for every docs feature or bug. A feature would be a new article or section of content, and a bug would be any error, omission, typo, or other issue requiring a fix.
Gathering feedback is an important part of a content strategy. Consider adding a way for users to contact you with feedback on every doc page or contribute to the docs through GitHub. A Feedback button is usually just a form that goes to a company email address; the person(s) assigned to this task can then take each feedback item and turn it into a Jira or GitHub issue for review and implementation.
To ensure a consistent style and the use of precise terminology, create a company style guide or follow an existing one. Here are some examples of documentation style guides that would work for most software projects:
- Google Developer Documentation Style Guide
- GitLab Documentation Style Guide
- Microsoft Writing Style Guide
Here is some further reading on content strategy to help get you started:
Building a Docs Site
From your content strategy, you can determine how your docs will be presented to the intended audience. Determining who will write your docs will also help inform this decision. For example, if developers and contributors will be writing documentation in code comments, then RDoc or YARD can be used to create a simple static docs site from these comments. If user documentation will be written in Markdown files, a static site generator, such as Jekyll, would be the better choice for publishing your docs. Of course, you can also create a site from scratch that works for your team and your project.
This article uses Jekyll and YARD to illustrate both types of documentation sites for a Rails app. Note that Jekyll is Ruby-based and integrates well into a Rails app.
Jekyll
The purpose of Jekyll is to transform plain text into a static website. Jekyll creates a _site
folder containing static site files that can be published by any hosting service. Pushing these files to GitHub means that you can use continuous publication tools, such as Netlify, to publish your docs.
The simplest workflow with Jekyll involves writing docs in Markdown files and pushing them to GitHub. If you use Netlify, it automatically deploys the site when you merge these changes to the repository. This process is described in more detail in the next section.
To create a Jekyll site, install Jekyll and Bundler from the root directory of your Rails app (e.g., /blog
):
gem install jekyll bundler
Creating a Jekyll site and running it from a local development server requires only three commands:
jekyll new docs
cd docs
bundle exec jekyll serve
This creates a /docs
directory containing a minimal Jekyll site (the default is a blog theme called Minima). You can use this as the base for your custom Jekyll docs site. Alternatively, you can install a docs theme, such as just-the-docs
, which comes with sidebar navigation and site search functionality.
This tutorial will use the just-the-docs
theme. To install it, run the following from the /docs
directory:
bundle add just-the-docs
Remove the minima
theme from the Gemfile since it is the default theme you will no longer be using. You can also delete the posts
directory.
Next, add this theme to Jekyll's _config.yml
file. You can also customize your site's title and description while you're here:
title: Docs Site
email: your-email@example.com
description: >-
A Jekyll docs site for a Rails app.
baseurl: "" # the subpath of your site, e.g. /blog
url: "" # the base hostname & protocol for your site, e.g. http://example.com
twitter_username: ""
github_username: ""
# Build settings
theme: just-the-docs
Start the server again, and you'll see a mostly empty docs site:
Check your Jekyll theme's documentation to see which directory should hold your Markdown files. For just-the-docs
, Markdown files can live in the root directory, which corresponds to the base path of your site. Create a new Markdown file in the root directory to see how it works:
---
layout: default
title: Sample Doc
nav_order: 1
---
# Models
{: .no_toc }
## Table of contents
{: .no_toc .text-delta }
1. TOC
{:toc}
---
## Markdown header
Write **Markdown** here!
Start the server again to see your new sample doc:
You now have a basic Jekyll site in a /docs
folder in your Rails app directory! See the Jekyll docs for help with customizing the Jekyll theme or writing your own.
YARD
Documentation generators, such as Rdoc and YARD, generate developer documentation from code comments. You can create a standalone docs site using YARD, which accepts Rdoc and other syntax. In this example, we'll add YARD documentation to our existing Jekyll site. Jekyll can publish the static files generated by YARD at a path such as /dev
. You could also use YARD on its own to create your documentation site.
When Rails generates an app, it also generates a few basic code comments:
# app/controllers/posts_controller.rb
class PostsController < ApplicationController
before_action :set_post, only: %i[ show edit update destroy ]
# GET /posts or /posts.json
def index
@posts = Post.all
end
# GET /posts/1 or /posts/1.json
def show
end
# GET /posts/new
def new
@post = Post.new
end
# GET /posts/1/edit
def edit
end
# code omitted
end
To see how YARD uses these comments to create a docs site, run the yard doc
or yardoc
command from the root directory of your Rails app:
yardoc --output-dir docs/dev app/**/*.rb
If the
yardoc
command doesn't work, install the YARD gem withbundle install yard
.
YARD will place its output files in the output-dir
, which is set to the Jekyll directory /docs/dev
in the command above. Jekyll can now publish YARD's site files with a base path of /dev
.
More complex documentation can be created using RDoc or other syntax (see the YARD documentation), but we'll stick with the existing documentation here.
Start the Jekyll server and navigate to localhost:4000/dev
to see your YARD-generated documentation:
At this point, there is no way to navigate to these developer docs from the main Jekyll site. To add a link from the Jekyll site to the developer docs, add the following to docs/_config.yml
:
# Aux links for the upper right navigation
aux_links:
"Developer Documentation":
- "/dev"
This concludes the discussion of Jekyll and YARD. Now that your docs site is set up, developers and writers can simply write content in Markdown files (or code comments) and push them to GitHub. The next section explains how to deploy these docs with continuous publication.
Continuous Publication and Deployment with Netlify
Continuous publication is convenient for docs sites because the live site can be updated automatically when changes to docs are approved and merged into the repository. This tutorial uses Netlify for this purpose, but other tools are available, such as GitHub Pages, GitLab Pages, and Firebase.
The site we've been building so far is hosted by Netlify: Docs Site.
To set up Netlify for your docs site, start by signing up for a Netlify account and connecting it to the GitHub repository containing your Rails app.
Use the following settings:
Repository
github.com/your-username/your-rails-repo
Base directory
docs
Build command
jekyll build
Publish directory
docs/\_site
Builds
Active
If some settings are not available when creating the Netlify site, click Deploy for now. You can then cancel it and return to the Deploy settings. Set the base directory to
docs
to ensure that Netlify deploys your Jekyll docs site rather than your Rails app.
When Netlify is finished deploying your Jekyll site, navigate to the live site to ensure that everything looks right.
One benefit of using Netlify is that it provides a live preview link directly from each pull request:
You can then check that your changes will be published correctly before merging the pull request and triggering the re-deploy of your site. The next section covers this workflow in more detail.
Setting Up an Editorial Workflow in GitHub
With a strategy for writing documentation and a site to publish it on, you're set to start writing docs and integrating them into your software workflow.
A typical editorial workflow involves drafting a document, reviewing the document, and then publishing it. Writers should perform their own reviews of their work, but editors, managers, and stakeholders are often part of the final review process. Because this is similar to the software development process, you can use software development tools to make the process more efficient.
Here is an example editorial workflow for a team using GitHub:
- [Writer] Create or update a file according to a documentation feature request or bug (as noted in a GitHub issue).
- [Writer] Push the change to a GitHub branch.
- [Writer] Open a pull request.
- [Reviewer] Review the changes.
- [Reviewer/Maintainer] Merge the changes to the repository, which should trigger a new build of the docs site.
GitHub automatically manages the change history of your content, which is also key in a docs-as-code workflow. You can see what was changed, who changed it, when it was changed, as well as why or how it was changed (if mentioned in the comments, discussion, or a related issue). This is stored in one place for all members of your team to see at any given time.
Issues and Labels
You can use the same issue templates for new documentation that you would use for code. This allows community members to request documentation that might be missing or to notify the team of errors. Managers can also use issues to assign developers or writers to documentation tasks.
To distinguish docs issues from code issues, you can use labels. Add a documentation
label to indicate that it's related to docs. You can also create labels for specific docs issues, such as docs::feature
or docs::fix
.
You might add instructions to your issue templates regarding the issue title or appropriate labels, just as you would for code-related issues.
Workflow labels, such as docs::in progress
and docs::in review
, are also useful. They reflect what is currently being worked on.
When defining your documentation process, be sure to specify who is responsible for changing these labels and when. For example, the person writing the draft would change the label to docs::in progress
when they begin writing the draft. When the reviewer receives the draft, the reviewer should change the issue label to docs::in review
.
Managing the Workflow
For small teams and projects, using GitHub Projects is a convenient way to manage your editorial content directly from GitHub. They are similar to project management boards, such as in Trello, but the columns can be linked directly to issues and pull requests.
For example, use the "Automated kanban with reviews" template so that new issues and pull requests are automatically added to the board. When a reviewer begins a review or approves a pull request, the issue card moves to the next column. This lets you keep track of active issues and where they are in the editorial process.
For larger projects that include more than just docs, use the project-bot
GitHub App to set up automation rules. For example, adding a specific label or assigning a specific reviewer would trigger automatic card movement. Alternatively, you can integrate documentation management into your larger project management workflow using a tool like Jira.
See the sample app for a demonstration of the
project-bot
app in a GitHub Project.
Creating Documentation
This section outlines the creation of documentation in more detail, from drafting to publication.
Writing and Revising Docs
The first step in your editorial workflow is writing some docs. For tips on writing documentation, see A Beginner's Guide to Writing Documentation from Write the Docs.
For example, to create an article about your Rails blog app, create a new Markdown file called blog-posts.md
in your Jekyll docs
directory:
---
layout: default
title: Blog Posts
nav_order: 1
---
## Creating a Blog Post
...
When you're writing code, you're probably checking the syntax as you write using syntax highlighters and code linters. If you write your docs in a code editor, you can use similar linters that check for spelling errors and grammar problems as you write. There are also linters that check your Markdown formatting.
For example, VSCode allows you to preview Markdown files directly in the editor, and it has an extension for the Markdownlint linter, which checks for errors in your Markdown syntax.
There is also a popular prose linter called Vale, which has extensions in VSCode and other editors.
Another bonus to writing Markdown in your code editor is that you don't need to switch between editors to write docs and code for your project. With your docs stored in the same directory as your Rails app, you can use a split layout to write documentation while viewing the code.
Committing Changes
You've written a new document in VSCode and checked it for spelling mistakes and syntax errors. The next step is to create a new branch and commit the change to Git:
git checkout -b docs/blog-posts
git add docs/blog_posts.md
git commit -m "Create doc: Blog Posts"
git push -u origin docs/blog-posts
Push this commit to the docs/blog-post
branch in the remote GitHub repository.
Finally, on GitHub, create a pull request between your new branch and the master (or main) branch. This pull request allows your changes to be reviewed and approved like any other code in the project.
Reviewing and Approving Docs
Merging documentation changes to a repository can be as dangerous as it is in software development. You're deploying changes to documentation that your customers and users rely on, so you'll want to ensure the review process is rigorous. It's a good idea to have several reviewers involved, including developers, product managers, technical writers, and editors.
Keep track of the changes everyone makes to the file, and discuss any further revisions that are needed. GitHub and similar tools allow you to view the change history of your files, including what was changed, when the change was made, and who made it.
You can also add GitHub Actions to automatically check your Markdown files before someone merges them into the code base. For each linter you use in VSCode, add the corresponding GitHub Action if it exists:
These actions will check your Markdown files for various spelling and syntax errors before the changes to your docs go live:
Click Details to see why a check isn't passing:
To add Vale and Markdownlint to your pull request checks, copy the docs.yml workflow file from the sample repository.
For the Vale action to work, you might need to create the .github/styles/vocab.txt
file in your repository. This is a list of words (one per line) that will be ignored by Vale, such as your company name or the names of people on your team.
If you have a GitHub Pro, Team, or Enterprise account, you can create branch protection rules. These rules prevent users from merging changes unless certain requirements are met, such as passing status checks or obtaining approval from at least one team member.
Remember that Netlify also provides a preview of your site in the list of checks, so the reviewer can check that everything looks good before merging the changes and re-deploying the site.
After you've thoroughly reviewed and then merged the changes to your documentation, Netlify will re-deploy your site. Navigate to your live Jekyll site to see the changes.
Conclusion
You should now have a basic documentation workflow in GitHub for a Rails app or any other project. Managing docs like code can be as simple or complex as it needs to be. For small projects, a bit of automation in GitHub might be all you need. Larger projects might be more closely integrated with other departments and teams and, therefore, with other tools.
Be sure to look through the sample GitHub repository for the Rails app and sample Jekyll site we created in this article. The repo includes sample issues and a pull request, as well as labels. It also has an automated GitHub Project and a sample pull request template for authors, reviewers, and maintainers to follow when adding documentation to the code base.
For further reading, check out GitLab's documentation process, which could be used as a starting point for developing your own. Their Documentation Guidelines might also provide inspiration.