Hinode logo
  • About 
  • Docs 
  • Components 
  • Guides 
  • Releases 
  •  

Creating Versioned Documentation

Posted on August 2, 2023  (Last modified on December 13, 2024) • 12 min read • 2,430 words
Guide   Versioning  
Guide   Versioning  
Share via
Hinode
Link copied to clipboard

Guide on how to create versioned documentation using folders and branch deployments.

On this page
Introduction   Step 1 - Preparing the Basic Content   Creating a New Site   Starting a Local Server   Adding Documentation   Supporting Redirection   Step 2 - Configuring Versioned Navigation   Enabling Navigation   Configuring the Version Switcher   Deploying the Current Branch   Step 3 - Using Multi-Branch Deployments   Creating a New Branch   Configuring the Multi-Branch Deployment   Step 4 - Updating the Main Site   Using Server-Side Redirection   Redirecting the Versioned Docs   Adding a Version Overview   Defining a Version Check   Exposing the Latest Release as 1.0   Conclusion  
Creating versioned documentation
Photo by Chris Lawton  on Unsplash 

Introduction  

Providing up-to-date and accurate documentation is an important aspect of many software products. Hinode supports Sidebar Navigation to help your users find the relevant content. However, as your software evolves, you might need to support different versions too. This guides illustrates how you can use Hinode to maintain versioned documentation.

The next paragraphs explain two main strategies. The first strategy is to maintain separate content folders in your repository. The second strategy uses so-called multi-branch deployments to publish a specific repository branch. You will need a Netlify Account to be able to test the multi-branch deployment.

  Note

A full-working example of this guide is available on GitHub  . Visit version-demo.gethinode.com  for a live demo.

Step 1 - Preparing the Basic Content  

In the first step, we will create a basic documentation site using the Hinode template. The site will be in English only, with a main section called Docs.

Creating a New Site  

We will now create a new site using the Hinode template. Follow the first step of the guide on how to Set Up a New Site Using the Hinode Template. Give the repository a recognizable name, such as version-demo.

Starting a Local Server  

For the purpose of this guide we will support the English language only. Be sure to create a new branch first, so you can test any changes before publishing them. The remainder of this guide uses the develop branch for development and the main branch for production. Start a local server to test the site is working as expected. Navigate in your browser to the local address (http://localhost:1313/ by default) to visually inspect the site.

npm run start

Environment: "development"
Serving pages from memory
Web Server is available at http://localhost:1313/ (bind address 0.0.0.0)
Press Ctrl+C to stop

Adding Documentation  

Create a new folder docs within content/en to create a new section. We will create three subfolders within the docs section, one for each documentation version:

  • content/en/docs/0.1
  • content/en/docs/0.2
  • content/en/docs/latest

We will now create a simple about page for each version. Create a file about.md within each version folder. Add the following frontmatter to each file, replacing {version} with 0.1, 0.2, and latest.

---
title: About (v{version})
description: About my product
date: "2023-06-21"
layout: docs
aliases:
  - "/docs/{version}/"
  - "/docs/" # only add this alias in `content/en/docs/latest/about.md``
---

The aliases instruct Hinode to redirect each docs/{version} entry to the correct page. The docs path redirects to the latest about page.

Supporting Redirection  

Hugo recognizes the /docs/ page as a list page by default. To properly map this entry to the latest about page (defined as an alias previously), we will need to explicitly instruct Hugo not to generate a list page. Create a new file _index.md within content/en/docs with the following content to do so:

---
title: Docs
redirect: "/docs/"
_build:
  list: false
  render: false
---

Step 2 - Configuring Versioned Navigation  

As a next step, we will enable navigation for the Docs section. We will add an entry in the main navigation bar and enable versioned sidebar navigation. Finally, we will add a dropdown menu to the main navigation to enable switching of versions.

Enabling Navigation  

First we will add a main menu entry for the (latest) docs content. Add the following content to config/_default/menus/menus.en.toml:

[[main]]
  name = "Docs"
  url = "/docs/"
  weight = 40

Update the weight of the tags to 50:

[[main]]
  name = "Tags"
  url = "/tags/"
  weight = 50

Now create a file docs.yml in the data folder with the following content to enable sidebar navigation:

- title: About

  Note

You can copy the docs.yml file to docs-0.1.yml and docs-0.2.yml to create versioned sidebar navigation. Hinode uses data/docs.yml as default sidebar navigation data when no versioned file is available.

Finally, we will tell Hinode where to find the versioned docs pages. Hinode uses the permalink of the current page to extract the version label, if any. This label is used to generate the correct links for the main navigation and sidebar navigation. Add the following value to config/_default/params.toml:

[docs]
  contentPath = "/docs/"

Configuring the Version Switcher  

We will now configure a drop-down menu in the main navigation to enable switching of the active version. We will add an entry for each release, identified by the labels v0.1, v0.2, and latest. The argument url matches the release with the correct content folder.

To improve the layout of the menu, we can tag a specific release as latest. We can also group releases by adding a label without an url. The menu is rendered in the order as configured. Add the following content to config/_default/params.toml:

[[docs.releases]]
  label = "Current release"

[[docs.releases]]
  label = "latest"
  url = "/docs/latest/"
  latest = true

[[docs.releases]]
  label = "Previous releases"

[[docs.releases]]
  label = "v0.2"
  url = "/docs/0.2/"

[[docs.releases]]
  label = "v0.1"
  url = "/docs/0.1/"

Check if your site is working correctly. You may need to restart your local server for the aliases to work properly. Additionally, you might have to clear your browser cache too.

Deploying the Current Branch  

We will now deploy and publish the main branch with Netlify. For the deployment to be successful, you will need to specify the baseURL in config/_default/hugo.toml. The Hinode template defines a default value that you will need to replace. You can use a domain that you own, or use a domain provided by Netlify (such as {sitename}.netlify.app/). If you do not know the sitename or domain name yet, you can go ahead with the deployment and come back to this step later - you will need to redeploy the site though.

baseURL = "https://template.gethinode.com/" # replace this

Head over to your repository on Github and submit a Pull Request (PR) to update your main branch. When successful, login to your Netlify account and create a new site. You can follow the Netlify Deployment Guidelines for a more detailed explanation. Once done, validate that you have a working site in production.

Initial Site With Basic Versioning
Initial Site With Basic Versioning
Initial Site With Basic Versioning
Initial Site With Basic Versioning

Step 3 - Using Multi-Branch Deployments  

The approach with various version folders in the same repository might be adequate for smaller documentation sites. However, complex documentation sites might have thousands of pages. Ideally, we would use Git to track all of the versioned changes. We can use multi-branch deployments to achieve this goal. The support and configuration of multi-branch deployments varies across hosting providers. The remainder of this guide uses Netlify as provider.

Creating a New Branch  

Create a new branch called v0.9 that is derived from your current branch (be sure to commit the current branch first). For demonstration purposes, we will expose the latest folder as the specific version 0.9. Ofcourse, we could simply rename the physical folder and be done with it. However, we would loose the ability to easily track changes to our documentation in the Git repository. Renaming a folder implies that the old folder and content are removed, and a new folder is created. Instead, we will use Hugo’s mounting feature to rename and expose the folder on the fly1.

  Important

Mounting a Content Folder Overrides the Language-Specific Settings  . In our configuration we have set defaultContentLanguage to en and defaultContentLanguageInSubdir to false. We will need to manually refine our mounts to achieve the same behavior.

Add the following mount to config/_default/hugo.toml to map the latest folder to 0.9. We will keep the remaining content within the docs folder as is.

  [[module.mounts]]
    source = "content/en/docs/latest"
    target = "content/docs/0.9"
    lang = 'en'
  [[module.mounts]]
    source = "content/en"
    target = "content"
    lang = 'en'
    excludeFiles = 'docs/latest/*'

Next we will update the title and alias in the frontmatter of content/en/docs/latest/about.md:

title: About (0.9)
aliases:
  - "/docs/0.9/"
  - "/docs/"

And finally, we will replace the label and url for the latest release in config/_default/params.toml:

[[docs.releases]]
  # label = "latest"      # old value
  label = "0.9"           # new value
  # url = "/docs/latest/" # old value
  url = "/docs/0.9/"      # new value
  latest = true

Configuring the Multi-Branch Deployment  

We will deploy the v0.9 branch on a separate subdomain with a so-called multi-branch deployment. By default, Netlify publishes the main branch only, along with any previews. We can instruct Netlify to deploy an additional branch, such as v0.9. Netlify uses the branch name followed by two hyphens and your internal Netlify subdomain. We will use this pattern as our baseURL in config/_default/hugo.toml.

Update the baseURL of hugo.toml in your v0.9 branch, replacing {branch} and {sitename} with the correct values. Commit the changes to your branch when done.

baseURL = "https://{branch}--{sitename}.netlify.app/"

We will also need to use absolute URLs for our page assets to ensure our references link to the correct server. For this purpose, set the custom parameter canonifyAssetsURLs in the main section of config/_default/params.toml to true.

[main]
    canonifyAssetsURLs = true

  Important

In the default state, Hinode uses relative links to include images, scripts, stylesheets, and other files. In this setup, the browser would retrieve these assets from the wrong backend server when using redirection. We therefore explicitly instruct Hugo to use absolute URLs for selected assets with the canonifyAssetsURLs setting.

Configure Netlify Branch Deployment
Configure Netlify Branch Deployment

Head over to your Netlify configuration and navigate to the section Site configuration / Build & deploy / Continuous deployment. Next, scroll to the section Branches and deploy contexts and click the button Configure. Select the option Let me add individual branches for Branch deploys. In the text field, enter v0.9 as branch name. When done, click Save.

  Caution

By default, any changes submitted to the v0.9 branch are processed and released to production immediately. Set up branch protection rules and automated testing (similar to the main branch) as needed.

Branch-Deployed Site for Release V0.9
Branch-Deployed Site for Release V0.9
Branch-Deployed Site for Release V0.9
Branch-Deployed Site for Release V0.9

Test if the branch is deployed successfully by navigating to https://{branch}--{sitename}.netlify.app/. The default netlify.toml file in the repository root has enabled netlify.app in the Content Security Policy by default. Review and Adjust the Server Headers as needed.

Step 4 - Updating the Main Site  

Now that we have configured a branch-specific site for v0.9 of our documentation, it is time to go back to our main documentation site. In the final step of this guide we will set up server-side redirection to link to the newly deployed site. We will finish our configuration by adding a version overview and by configuring a version check.

Using Server-Side Redirection  

Hugo supports Client-Side Redirection Using Aliases  . We have defined these aliases in our about pages. In this approach, the browser receives an instruction to redirect to a new URL when visiting the initial page. We can instruct the server to redirect the URL instead, thus safing an additional roundtrip.

Hinode has defined a template in Layouts/Index.redir  to automatically generate server-side redirection rules for Netlify. When you add the status code 200 to such a rule, the Redirection Becomes a Rewrite  . In a rewrite, the URL in the visitor’s address bar remains the same, while the content is fetched from a different location behind the scenes. We will use this mechanism to fetch the content from the branch site.

Go back to your develop branch and add the below code to your production configuration in config/production/hugo.toml. The setting disableAliases disables all client-side redirection rules. Instead, the REDIR output generates all redirection rules for the server, including rewrites.

disableAliases = true

[outputFormats.REDIR]
mediaType = "text/netlify"
baseName = "_redirects"
isPlainText = true
notAlternative = true

[mediaTypes."text/netlify"]
delimiter = ""

[outputs]
home = ["HTML", "RSS", "REDIR", "netlify", "server"]

Redirecting the Versioned Docs  

Still within the develop branch, add the below release configuration to config/_default/params.toml, replacing {sitename} with the correct value:

[[docs.releases]]
  label = "v0.9"
  url = "/docs/0.9/"
  redirect = "https://v0-9--{sitename}.netlify.app/docs/0.9/"

  Note

In local development mode the link is disabled, as server-side redirection is not supported by Hugo’s web server.

The redirect value maps the release 0.9 to our branch deployment in production. The url points to the mount that we have defined previously.

You can test the redirection rules by building the site locally:

npm run build

Open the file public/_redirects to review the rules. The first rule uses the code 200 to instruct Netlify to set up a rewrite. The other rules are common redirects as defined by the various aliases.

/docs/0.9/* https://v0-9--{sitename}.netlify.app/docs/0.9/docs/0.9/:splat 200
/docs/1.0/ /docs/1.0/about/
/docs/ /docs/1.0/about/
/docs/0.1/ /docs/0.1/about/
/docs/0.2/ /docs/0.2/about/

Adding a Version Overview  

You can add a link to a custom overview page. An example of such a Version Overview Page Is Available in the Demo Repository  . Add the link to the page in the overview setting within the docs section of the config/_default/params.toml. Do not forget to add the configuration to the v0.9 branch too, if desired.

[docs]
  overview = "/docs/versions/"

Defining a Version Check  

You can add an alert to inform your users that they are not looking at the latest version of the available documentation. Specify the latest available version in latest. When you set checkVersion to true, Hinode checks if the current version is equal or newer than the latest version. Hinode shows an alert at the top of the page when the current version is behind. The alert links to the latestURL. Do not forget to add the configuration to the v0.9 branch too, if desired.

[docs]
  latest = "1.0"
  checkVersion = true
  latestURL = "https://version-demo.gethinode.com/docs/"

Exposing the Latest Release as 1.0  

Similar to the v0.9 release, you can can expose the latest release as a specific version too. In the develop branch, add the following mounts to config/_default/hugo.toml:

  [[module.mounts]]
    source = "content/en/docs/latest"
    target = "content/docs/1.0"
    lang = 'en'
  [[module.mounts]]
    source = "content/en"
    target = "content"
    lang = 'en'
    excludeFiles = 'docs/latest/*'

Next, update the Title and aliases in the frontmatter of content/en/docs/latest/about.md:

title: About (1.0)
aliases:
  - "/docs/1.0/"
  - "/docs/"

And finally, we will replace the label and url for the latest release in config/_default/params.toml:

[[docs.releases]]
  # label = "latest"      # old value
  label = "1.0"           # new value
  # url = "/docs/latest/" # old value
  url = "/docs/1.0/"      # new value
  latest = true

Conclusion  

In this guide we have configured a version-aware documentation site using two different strategies. The approach using different folders is the most straightforward and might be sufficient for smaller sites. You could consider a multibranch approach when maintaining a complex documentation site. The configuration and deployment of such a site is provider-specific though. In this guide we have used Netlify as an example, which you could adapt to your own needs.


  1. We could skip the mounting entirely and use a server-side rewrite instead. However, we would lose the ability to test the site locally. ↩︎

 Optimizing the user experience
Customizing the appearance of your site 
On this page:
Introduction   Step 1 - Preparing the Basic Content   Creating a New Site   Starting a Local Server   Adding Documentation   Supporting Redirection   Step 2 - Configuring Versioned Navigation   Enabling Navigation   Configuring the Version Switcher   Deploying the Current Branch   Step 3 - Using Multi-Branch Deployments   Creating a New Branch   Configuring the Multi-Branch Deployment   Step 4 - Updating the Main Site   Using Server-Side Redirection   Redirecting the Versioned Docs   Adding a Version Overview   Defining a Version Check   Exposing the Latest Release as 1.0   Conclusion  
Creating versioned documentation
Creating versioned documentation
Hinode is a clean documentation and blog theme for your Hugo site based on Bootstrap 5.
Code licensed MIT, docs CC BY-NC 4.0
Currently v0.29.3
Privacy | Cookies
 
Links
Home 
About 
Docs 
Components 
Releases 
Guides
Getting Started 
Developing Modules 
Optimization 
Versioning 
Community
Issues   
Discussions   
Contribute 
Hinode
Code copied to clipboard