Developmentteams also maintain documentation for their solutions nowadays. Using Docusaurus, DevOps/Github and Azure, building a documentation website is fairly easy. This blog contains my own experiences on the matter.

To provide some context: My company provides several products & services which are backed by dedicated DevOps-teams working on continuous improvements and delivering support.

These teams all maintain documentation like a service descriptions and onboarding instructions. This documentation is maintained together with sourcecode in a DevOps or Github repo.

This documentation needs to be accessible by several engineers and consulants throughout the organisation. So, a central location containing this information is a must. And with that, the content should only be accessible by employees using their corporate Azure AD accounts.

By the way, this post assumes some familiarity with Azure, npm and YAML.

Docusaurus

After gathering requirements and reviewing several solutions, we choose Docusaurus as the platform to build our documentation website.
Docusaurus is an open source solution based on React backed by Facebook (Meta). It supported >90% of our requirements (including multi-language) and was fairly easy to implement.

As I had taken the responsibility of creating the platform, I started downloading the Docusaurus repo and initiated a new Docusaurus instance in a working folder on my PC using the installation guidance from their own documentation site.

npx create-docusaurus@latest website classic

This initiates a new instance in the folder ‘website’ including an example project structure.

For the look & feel, I made some simple css adjustments (/src/css/custom.css) like specific color codes and adding a logo image (/static/img). Nothing to fancy, but in line with our corporate branding.

If you need to test and explore the expected output, you can create a local build:

npm run build

Creating mark down files

Within the project structure, you can add or create your mark down files. The basic mark down syntax is supported of course, but Docusarus has some additional mark down syntax to make it all fancy.

Azure prerequisites

Once I pushed my project to DevOps, the next step was to register an Azure AD app that would allow me to authenticate only our corporate user accounts using a client ID and client secret from the website.

The Microsoft guidance (Configure your App Service or Azure Functions app to use Azure AD login) for this is more than sufficient.

Make sure you save the client ID and client secret for later use. Also, copy the deployment token from the “Overview” page for the Azure Static web app. This is the key to use when deploying the static website to this instance.

You also need to consider adding a custom domain, as Azure Static websites use a not so easy naming convention when creating them.

Deploying to Azure

Docusaurus is basically a static website generator. And we now have Azure Static websites in preview to support such generators as a landing zone for the output.

For the authenicaton, we need to add 2 new application settings for the Azure Static Website and save them:

  • AAD_CLIENT_ID
  • AAD_CLIENT_SECRET

For the values, you can use the saved info from creating the Azure AD app.

Configuration

One of the important files used to configure the static website during deployment, is the staticwebapp.config.json file, which is located in the root of your website project in DevOps.
The following example leverages the AAD_CLIENT_ID and AAD_CLIENT_SECRET application setting values to support authentication.

{
    "routes": [
        {
            "route": "/logout",
            "redirect": "/.auth/logout"
        },
        {
            "route": "/.auth/login/twitter",
            "statusCode": 404
        },
        {
            "route": "/.auth/login/github",
            "statusCode": 404
        },
        {
            "route": "/*",
            "allowedRoles": ["authenticated"]
        }
    ],
    "responseOverrides": {
        "401": {
          "redirect": "/.auth/login/aad?post_login_redirect_uri=.referrer",
          "statusCode": 302
        }
    },    
    "auth": {
        "identityProviders": {
            "azureActiveDirectory": {
                "registration": {
                "openIdIssuer": "https://login.microsoftonline.com/{tenant ID}/v2.0",
                "clientIdSettingName": "AAD_CLIENT_ID",
                "clientSecretSettingName": "AAD_CLIENT_SECRET"
                }
            }
        }
    }
}

Make sure you replace {tenant ID} with the Azure AD ID (guid) for the tenant in which the user accounts reside.
Also, ensure that your login redirect has the “post_login_redirect_uri=.referrer” parameter added to the URL to ensure that the user is redirected to the intended URL after authentication.

Deployment

To build and deploy the static website, you can use e.g. Azure pipelines (as used on the remainder of this post) or Github actions.

For this example, only the essential tasks are listed in the YAML snippet below. Basically, the pipeline creates a new agent, checks out the repo, and builds the project using npm.

As the project already contains the static website configuration file, this is included by default without any additional action.

trigger:
- none

pool:
  vmImage: ubuntu-latest

steps:
  - checkout: self
    submodules: true
  - task: AzureStaticWebApp@0
    displayName: Build and deploy docs
    inputs:
      app_location: '/'
      app_build_command: 'npm run build'
      output_location: 'build'
      azure_static_web_apps_api_token: $(deployment_token)

For the deployment_token, create a pipeline variable and populate the value with the saved deployment token from the created Azure Static website instance.

Building the project and deploying the site takes around 3 minutes without any optimizations in the pipeline.

Pipeline build

After that, you can access the secured static website on any screen as responsive design is builtin.

Example documentation website - light mode

Also notice the darkmode toggle button in the right uppercorner. It’s awesome!

Example documentation website - dark mode