From f10c18d7648dcc37acbfb4a257e3e53b38173c4f Mon Sep 17 00:00:00 2001
From: Nick Brown <nb745@cam.ac.uk>
Date: Tue, 11 Mar 2025 13:31:34 +0000
Subject: [PATCH] chore: Updated all site: links to not end .md

---
 docs/cards/diataxis/cards.yml                 |  8 +--
 docs/explanations/cloud-platform/aws.md       |  3 +-
 .../cloud-platform/azure-and-entra-id-apps.md |  6 +--
 .../cloud-platform/gcloudadmin-accounts.md    |  4 +-
 .../cloud-platform/gcp-budgets-alerts.md      |  6 +--
 .../cloud-platform/gke-gitlab-runners.md      |  6 +--
 .../google-cloud-permissions-model.md         |  2 +-
 .../cloud-platform/service-infrastructure.md  | 14 +++---
 .../development/webapp-boilerplate.md         | 16 +++---
 docs/explanations/git-gitlab/git.md           |  2 +-
 .../git-gitlab/gitlab-release-automation.md   | 12 ++---
 docs/explanations/misc/identifiers.md         |  2 +-
 docs/explanations/renovatebot/index.md        | 18 +++----
 docs/howtos/aws/access-aws-console.md         |  4 +-
 docs/howtos/aws/audit-aws-console-access.md   |  2 +-
 docs/howtos/aws/create-aws-accounts.md        |  2 +-
 docs/howtos/aws/get-started-with-aws.md       |  2 +-
 docs/howtos/aws/use-aws-cli.md                |  4 +-
 .../create-gcloudadmin-account.md             |  2 +-
 .../respond-to-billing-alerts.md              |  6 +--
 docs/howtos/development/copier/create.md      |  4 +-
 docs/howtos/development/copier/migrate.md     |  2 +-
 docs/howtos/development/copier/update.md      |  2 +-
 docs/howtos/development/create-a-new-app.md   |  8 +--
 .../development/generate-api-clients.md       |  4 +-
 ...loud-run-app-terraform-deployment-to-v9.md |  4 +-
 .../howtos/development/prepare-your-system.md |  6 +--
 .../howtos/development/run-an-existing-app.md | 10 ++--
 .../development/setup-pre-commit-hooks.md     |  4 +-
 .../howtos/email/register-with-user-notify.md |  6 +--
 docs/howtos/entra-azure/add-sso-sign-in.md    |  6 +--
 .../authorise-web-apps-with-custom-roles.md   |  2 +-
 .../register-azure-api-management-app.md      |  2 +-
 docs/howtos/git-gitlab/common-git-tasks.md    |  4 +-
 .../git-gitlab/create-a-feature-branch.md     |  4 +-
 .../enable-automated-gitlab-releases.md       |  8 +--
 docs/howtos/git-gitlab/open-an-issue.md       |  8 +--
 docs/howtos/git-gitlab/sign-in-to-gitlab.md   |  2 +-
 docs/howtos/git-gitlab/size-issues.md         |  4 +-
 ...-secrets-in-ci-jobs-using-impersonation.md |  2 +-
 .../gke-gitlab-runners/developer-overview.md  |  2 +-
 .../register-a-gke-gitlab-runner.md           |  6 +--
 .../run-ci-jobs-on-a-gke-gitlab-runner.md     |  2 +-
 ...d-common-pipeline-and-precommit-to-java.md |  2 +-
 docs/howtos/products/bootstrap-a-product.md   | 20 ++++----
 .../products/check-product-configuration.md   |  2 +-
 .../products/delete-product-infrastructure.md |  2 +-
 .../howtos/python/publish-a-python-package.md |  6 +--
 docs/howtos/python/pypi.md                    |  2 +-
 .../deploy-releases-with-renovatebot.md       |  6 +--
 .../trigger-renovatebot-from-ci.md            |  2 +-
 .../trigger-renovatebot-from-cli.md           |  4 +-
 docs/libraries-tools/gcp-terraform.md         | 16 +++---
 docs/libraries-tools/git-ci-docker.md         |  8 +--
 docs/libraries-tools/python.md                | 50 +++++++++----------
 docs/reference/best-practice/ourtools.md      |  4 +-
 docs/reference/best-practice/python.md        |  6 +--
 docs/reference/cloud-platform/dns.md          |  4 +-
 .../cloud-platform/gke-gitlab-runners.md      |  8 +--
 docs/reference/cloud-platform/index.md        |  2 +-
 docs/reference/deployment/index.md            |  6 +--
 docs/reference/deployment/secrets.md          |  8 +--
 docs/reference/deployment/sql-instances.md    | 10 ++--
 docs/reference/deployment/templates.md        |  6 +--
 docs/reference/deployment/terraform.md        |  2 +-
 docs/reference/deployment/traffic-ingress.md  |  2 +-
 docs/reference/deployment/web-applications.md |  8 +--
 docs/reference/misc/identifiers.md            |  2 +-
 .../misc/openapi-client-generation.md         |  2 +-
 docs/reference/misc/tech-lead-forum.md        |  2 +-
 .../misc/webapp-developer-environment.md      |  6 +--
 .../notes/google-domain-verification.md       |  2 +-
 .../reference/notes/ucs-dev-group-services.md | 24 ++++-----
 .../reference/notes/webapp-dev-environment.md |  2 +-
 docs/reference/workflow/flows.md              |  2 +-
 docs/reference/workflow/gitlab.md             |  6 +--
 docs/reference/workflow/pypi.md               | 10 ++--
 docs/services/caias.md                        |  2 +-
 docs/services/data-backup.md                  |  2 +-
 docs/services/integrated-reward-system.md     |  2 +-
 docs/services/job-opportunities.md            |  2 +-
 docs/services/lookup-gitlab-sync.md           |  2 +-
 docs/services/postbox.md                      |  2 +-
 docs/services/regent-house-ballots.md         |  2 +-
 docs/standards/change-management.md           | 16 +++---
 docs/standards/devsecops-cicd.md              |  6 +--
 docs/standards/devsecops-dev.md               | 10 ++--
 .../availability.md                           |  2 +-
 docs/standards/tech-lead-forum.md             |  4 +-
 docs/tutorials/automating-gitlab-releases.md  | 10 ++--
 .../bootstrapping-a-new-application.md        | 18 +++----
 docs/tutorials/creating-a-python-package.md   |  2 +-
 docs/tutorials/gcp-custom-dns.md              |  6 +--
 93 files changed, 278 insertions(+), 277 deletions(-)

diff --git a/docs/cards/diataxis/cards.yml b/docs/cards/diataxis/cards.yml
index d7fc1770..644f4b60 100644
--- a/docs/cards/diataxis/cards.yml
+++ b/docs/cards/diataxis/cards.yml
@@ -1,5 +1,5 @@
 - title: |
-    [Tutorials](site:tutorials/)
+    [Tutorials](site:tutorials/index.html)
   content: |
     <img class="dtx" src="site:cards/diataxis/img/tutorials.jpg" alt="Tutorials">
     <a href="https://diataxis.fr/tutorials/">
@@ -14,7 +14,7 @@
     <h6 class="dtx">e.g. <i>"How do I add automated releasing to my Python library?"</i></h6>
 
 - title: |
-    [How-To's](site:howtos/)
+    [How-To's](site:howtos/index.html)
   content: |
     <img class="dtx" src="site:cards/diataxis/img/howtos.jpg" alt="How-To's">
     <a href="https://diataxis.fr/how-to-guides/">
@@ -29,7 +29,7 @@
     <h6 class="dtx">e.g. <i>"Walk me through making a new Python library?"</i></h6>
 
 - title: |
-    [Explanations](site:explanations/)
+    [Explanations](site:explanations/index.html)
   content: |
     <img class="dtx" src="site:cards/diataxis/img/explanations.jpg" alt="Explanations">
     <a href="https://diataxis.fr/explanation/">
@@ -44,7 +44,7 @@
     <h6 class="dtx">e.g. <i>"Why do we use Poetry for packaging?"</i></h6>
 
 - title: |
-    [Reference](site:reference/)
+    [Reference](site:reference/index.html)
   content: |
     <img class="dtx" src="site:cards/diataxis/img/reference.png" alt="Reference">
     <a href="https://diataxis.fr/reference/">
diff --git a/docs/explanations/cloud-platform/aws.md b/docs/explanations/cloud-platform/aws.md
index 04e7d338..f15b6898 100644
--- a/docs/explanations/cloud-platform/aws.md
+++ b/docs/explanations/cloud-platform/aws.md
@@ -26,7 +26,8 @@ settled on the following design aims:
   cannot be rotated automatically,
 - to avoid maintaining a parallel set of roles, make use of the existing Google Cloud permissions
   model when possible, and
-- preserve our existing [permissions model](./google-cloud-permissions-model):
+- preserve our existing
+  [permissions model](site:explanations/cloud-platform/google-cloud-permissions-model):
     - allow existing "editor" users to access the AWS console and `aws` CLI tool, and
     - allow existing "deploy" users to be able to seamlessly manage AWS and Google Cloud resources
       within the same terraform configuration.
diff --git a/docs/explanations/cloud-platform/azure-and-entra-id-apps.md b/docs/explanations/cloud-platform/azure-and-entra-id-apps.md
index 9a81fa1e..8d97ee8b 100644
--- a/docs/explanations/cloud-platform/azure-and-entra-id-apps.md
+++ b/docs/explanations/cloud-platform/azure-and-entra-id-apps.md
@@ -37,7 +37,7 @@ The two products most relevant to this guide are:
     * authentication and authorisation via Entra ID-issued access tokens.
 
 **There is no such thing as "Azure API Gateway".** Using terms like "API Gateway" risks confusion
-with the [API Gateway service](site:services/api-gateway.md).
+with the [API Gateway service](site:services/api-gateway).
 
 ## The three hats of an Application Registration
 
@@ -193,5 +193,5 @@ In this explainer we covered:
 
 ## See also
 
-* [Useful URLs and IDs for dealing with Entra ID Applications](site:reference/misc/entra-id.md)
-* [How to add sign in to a web application](site:howtos/entra-azure/add-sso-sign-in.md)
+* [Useful URLs and IDs for dealing with Entra ID Applications](site:reference/misc/entra-id)
+* [How to add sign in to a web application](site:howtos/entra-azure/add-sso-sign-in)
diff --git a/docs/explanations/cloud-platform/gcloudadmin-accounts.md b/docs/explanations/cloud-platform/gcloudadmin-accounts.md
index ac9ff487..543847ba 100644
--- a/docs/explanations/cloud-platform/gcloudadmin-accounts.md
+++ b/docs/explanations/cloud-platform/gcloudadmin-accounts.md
@@ -1,6 +1,6 @@
 # Google Cloud admin accounts
 
-As noted in the [checklist for products](site:howtos/products/check-product-configuration.md),
+As noted in the [checklist for products](site:howtos/products/check-product-configuration),
 development team members who need to administer, deploy or examine Google Cloud resources need
 to be listed in our [team data file](
 https://gitlab.developers.cam.ac.uk/uis/devops/infra/terraform/team-data/-/blob/master/team_data.json)
@@ -43,4 +43,4 @@ DO:
 
 ## More information
 
-* [How to create a Google Cloud admin account](site:howtos/cloud-platform/create-gcloudadmin-account.md).
+* [How to create a Google Cloud admin account](site:howtos/cloud-platform/create-gcloudadmin-account).
diff --git a/docs/explanations/cloud-platform/gcp-budgets-alerts.md b/docs/explanations/cloud-platform/gcp-budgets-alerts.md
index 7d810074..8417e19e 100644
--- a/docs/explanations/cloud-platform/gcp-budgets-alerts.md
+++ b/docs/explanations/cloud-platform/gcp-budgets-alerts.md
@@ -7,7 +7,7 @@ title: Budgets and Alerts
 This document explains how billing budgets and alerts are configured for our
 Google Cloud Platform (GCP) products. For information on how to react to
 triggered alerts see [How to respond to billing
-alerts](site:howtos/cloud-platform/respond-to-billing-alerts.md).
+alerts](site:howtos/cloud-platform/respond-to-billing-alerts).
 
 ## Introduction
 
@@ -56,7 +56,7 @@ The product factory configures two alerts by default. The first alert triggers
 when the budget is _forecasted_ to exceed 100%, the second triggers when the
 budget _exceeds_ 100%.
 
-See [How to respond to billing alerts](site:howtos/cloud-platform/respond-to-billing-alerts.md)
+See [How to respond to billing alerts](site:howtos/cloud-platform/respond-to-billing-alerts)
 for information on how to handle these alerts when they're triggered.
 
 ### Tags/labels
@@ -76,7 +76,7 @@ example product's meta project.</figcaption>
 
 ## See also
 
-- [How to respond to billing alerts](site:howtos/cloud-platform/respond-to-billing-alerts.md)
+- [How to respond to billing alerts](site:howtos/cloud-platform/respond-to-billing-alerts)
 
 [^1]:
     Our reseller, TI Sparkle (or just Sparkle), is an Italian company which is
diff --git a/docs/explanations/cloud-platform/gke-gitlab-runners.md b/docs/explanations/cloud-platform/gke-gitlab-runners.md
index 33f4cc13..c1cd40ad 100644
--- a/docs/explanations/cloud-platform/gke-gitlab-runners.md
+++ b/docs/explanations/cloud-platform/gke-gitlab-runners.md
@@ -93,8 +93,8 @@ takes some time to prepare the certificates. This is to avoid the
 ## See also
 
 - [How to register GKE-hosted GitLab
-  runners](site:howtos/gke-gitlab-runners/register-a-gke-gitlab-runner.md)
+  runners](site:howtos/gke-gitlab-runners/register-a-gke-gitlab-runner)
 - [How to run CI/CD jobs on a GKE-hosted GitLab
-  runner](site:howtos/gke-gitlab-runners/run-ci-jobs-on-a-gke-gitlab-runner.md)
+  runner](site:howtos/gke-gitlab-runners/run-ci-jobs-on-a-gke-gitlab-runner)
 - [How to access a Google Secret Manager secret using service account
-  impersonation](site:howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation.md)
+  impersonation](site:howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation)
diff --git a/docs/explanations/cloud-platform/google-cloud-permissions-model.md b/docs/explanations/cloud-platform/google-cloud-permissions-model.md
index d1b7dfb6..85414145 100644
--- a/docs/explanations/cloud-platform/google-cloud-permissions-model.md
+++ b/docs/explanations/cloud-platform/google-cloud-permissions-model.md
@@ -103,5 +103,5 @@ additionally be able to modify Cloud Scheduler, Cloud Filestore and Pub/Sub reso
 
 ## See also
 
-- [How to start a new product](site:howtos/products/bootstrap-a-product.md)
+- [How to start a new product](site:howtos/products/bootstrap-a-product)
 - [The explainer guide on our service infrastructure](./service-infrastructure.md)
diff --git a/docs/explanations/cloud-platform/service-infrastructure.md b/docs/explanations/cloud-platform/service-infrastructure.md
index 125ea235..7ca602c2 100644
--- a/docs/explanations/cloud-platform/service-infrastructure.md
+++ b/docs/explanations/cloud-platform/service-infrastructure.md
@@ -11,8 +11,8 @@ This document covers a few different *technical* meanings of "product" in DevOps
 decide how to group service infrastructure resources into products.
 
 There are quicker task-focused guides if all you want to do is [start a new
-service](site:howtos/products/bootstrap-a-product.md) or [ensure an existing service is
-up-to-date](site:howtos/products/check-product-configuration.md).
+service](site:howtos/products/bootstrap-a-product) or [ensure an existing service is
+up-to-date](site:howtos/products/check-product-configuration).
 
 This document is long, dense and necessarily pedantic with terminology. We'd recommend getting your
 drink of choice and reading the document a few times from top-to-bottom.
@@ -40,7 +40,7 @@ multiple Google Cloud "products" sharing a single GitLab "product".
 
 The *common case*, and the preferable one, is to align Google's, GitLab's and GitLab CI's idea of a
 "product" with one another and to have exactly one "product" for a given service. That situation is
-covered in a [dedicated how-to guide](site:howtos/products/bootstrap-a-product.md).
+covered in a [dedicated how-to guide](site:howtos/products/bootstrap-a-product).
 
 As services split and merge, however, we may find that the case becomes more complex. This document
 explains what we mean by "product" in each of these cases, what the relationship between products
@@ -523,10 +523,10 @@ require you knowing the `gcp-product-factory` or `gitlab-runner-infrastructure`
       <code>principalSet://iam.googleapis.com/projects/421963284348/locations/global/workloadIdentityPools/gitlab/attribute.gitlab_namespace_id/<em>&laquo;numeric-gitlab-namespace-id&raquo;</em></code>
     * CI jobs running triggered by a specific GitLab user:
       <code>principalSet://iam.googleapis.com/projects/421963284348/locations/global/workloadIdentityPools/gitlab/attribute.gitlab_user_id/<em>&laquo;numeric-gitlab-user-id&raquo;</em></code>
-* GitLab CI/CD Runner principals ([documentation](site:explanations/cloud-platform/gke-gitlab-runners.md)):
+* GitLab CI/CD Runner principals ([documentation](site:explanations/cloud-platform/gke-gitlab-runners)):
     * Any CI job running within a specific GitLab CI runner:
       <code>serviceAccount:gitlab-runner-prod-22257483.svc.id.goog[<em>&laquo;runner-product-name&raquo;</em>/gke-ci-run]</code>
-* Product-wide Google Project principals ([documentation](site:reference/cloud-platform/permissions-and-roles.md)):
+* Product-wide Google Project principals ([documentation](site:reference/cloud-platform/permissions-and-roles)):
     * Generic CI service account for CI not based in GitLab or if CI/CD jobs prefer to impersonate:
       <code>serviceAccount:gke-ci-run@<em>&laquo;meta-project-id&raquo;</em>.iam.gserviceaccount.com</code>
     * GitLab API token secret accessor:
@@ -714,6 +714,6 @@ flowchart TB
 
 After reading this guide, the following pages may be of interest:
 
-* [How-to configure the common-case](site:howtos/products/bootstrap-a-product.md)
+* [How-to configure the common-case](site:howtos/products/bootstrap-a-product)
 * [More information on our Google Cloud deployments](site:reference/cloud-platform)
-* [How we run GitLab CI/CD runners in the Cloud](site:explanations/cloud-platform/gke-gitlab-runners.md)
+* [How we run GitLab CI/CD runners in the Cloud](site:explanations/cloud-platform/gke-gitlab-runners)
diff --git a/docs/explanations/development/webapp-boilerplate.md b/docs/explanations/development/webapp-boilerplate.md
index fbac87cd..c76bef49 100644
--- a/docs/explanations/development/webapp-boilerplate.md
+++ b/docs/explanations/development/webapp-boilerplate.md
@@ -8,7 +8,7 @@ title: Webapp developer environment
 ??? warning "This document is appropriate for applications which do **not** have a `compose.sh` file in the root of the repository."
 
     The presence of `compose.sh` indicates that an application is using our older development
-    environment. See the [original guide](site:notes/webapp-dev-environment.md) if that file is
+    environment. See the [original guide](site:notes/webapp-dev-environment) if that file is
     present.
 
 This document provides a more "behind the scenes" guide to how our webapp developer environment
@@ -19,14 +19,14 @@ more about the "how" and the "why" of our developer environment.
 By contrast, the following documentation may be more useful if you have a specific goal or want to
 learn how to get started:
 
-* The [reference guide](site:reference/misc/webapp-developer-environment.md) contains cut-and-paste command
+* The [reference guide](site:reference/misc/webapp-developer-environment) contains cut-and-paste command
   snippets to quickly accomplish common tasks.
 * Our [how-to section](site:howtos) contains more task-focussed guides covering how to
   perform specific tasks within the environment. In particular you may want to read the following
   guides:
-    * [Preparing your system with required software](site:howtos/development/prepare-your-system.md).
-    * [Configuring your IDE](site:howtos/development/configure-your-ide.md).
-    * [Running an application](site:howtos/development/run-an-existing-app.md).
+    * [Preparing your system with required software](site:howtos/development/prepare-your-system).
+    * [Configuring your IDE](site:howtos/development/configure-your-ide).
+    * [Running an application](site:howtos/development/run-an-existing-app).
 
 ## Guiding philosophy
 
@@ -119,7 +119,7 @@ that they need only recall the short `poe up` command and do not need to recall
 compose` command.
 
 A list of the standard poe tasks shipped with our standard webapp developer environment can be found
-in the [reference guide](site:reference/misc/webapp-developer-environment.md).
+in the [reference guide](site:reference/misc/webapp-developer-environment).
 
 Providing common tasks behind a short alias aligns with our guiding philosophy in that we're
 providing both opinionated defaults about how to run and manage the application along with a
@@ -127,7 +127,7 @@ documented "paved path" for various tasks.
 
 ### Pre-commit
 
-We ship a number of [pre-commit checks](site:howtos/development/setup-pre-commit-hooks.md) in the standard
+We ship a number of [pre-commit checks](site:howtos/development/setup-pre-commit-hooks) in the standard
 environment which run various linting and auto-formatting tools over the source. These same checks
 are run in CI jobs.
 
@@ -222,7 +222,7 @@ For most applications, this packaging is fairly light. For the production contai
 
 The "development container" image is similar but additionally has the development time dependencies
 installed into it. See the [developer environment reference
-guide](site:reference/misc/webapp-developer-environment.md#dependencies) for more information on the
+guide](site:reference/misc/webapp-developer-environment#dependencies) for more information on the
 difference between "development time" and "run time" dependencies.
 
 ### CI/CD
diff --git a/docs/explanations/git-gitlab/git.md b/docs/explanations/git-gitlab/git.md
index a0d2b545..3f5c607a 100644
--- a/docs/explanations/git-gitlab/git.md
+++ b/docs/explanations/git-gitlab/git.md
@@ -5,7 +5,7 @@ details](https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Porcelain) in
 is also a [terminology section](#terminology) at the end of this document if any of the terms used
 herein are unknown.
 
-See the list of [external Git documentation](site:reference/git-gitlab/git-docs.md) for more in-depth
+See the list of [external Git documentation](site:reference/git-gitlab/git-docs) for more in-depth
 information.
 
 ## Pushing and pulling
diff --git a/docs/explanations/git-gitlab/gitlab-release-automation.md b/docs/explanations/git-gitlab/gitlab-release-automation.md
index 83890494..0b1ab86e 100644
--- a/docs/explanations/git-gitlab/gitlab-release-automation.md
+++ b/docs/explanations/git-gitlab/gitlab-release-automation.md
@@ -21,18 +21,18 @@ The `release-it` tool is very configurable and can handle many different
 requirements (see [the configuration
 doc](https://github.com/release-it/release-it/blob/main/docs/configuration.md)),
 however, there's an example `.release-it.json` file in the [How to enable
-automated GitLab releases](site:howtos/git-gitlab/enable-automated-gitlab-releases.md) page
+automated GitLab releases](site:howtos/git-gitlab/enable-automated-gitlab-releases) page
 which serves as a good starting point for most of our projects.
 
 ### Commit messages
 
-As recommended in the [Git commits](site:explanations/git-gitlab/git.md#commits) section,
+As recommended in the [Git commits](site:explanations/git-gitlab/git#commits) section,
 teams should ideally follow the [Conventional
 Commits](https://www.conventionalcommits.org/) standard for projects using the
 `release-it.yml` pipeline template. This is also a requirement for the
 `conventional-changelog` plugin which is configured in the example
 `.release-it.json` config file in [How to enable automated GitLab
-releases](site:howtos/git-gitlab/enable-automated-gitlab-releases.md). The `release-it` tool
+releases](site:howtos/git-gitlab/enable-automated-gitlab-releases). The `release-it` tool
 can be configured to work without Conventional Commits if required, however, it
 should be noted that the `release-it.yml` pipeline template has only ever been
 tested using Conventional Commits.
@@ -73,12 +73,12 @@ hotfix branches. This allows you to checkout hotfix branches from previous tags
 and commit your bug fixes. You then follow the standard workflows above to
 automatically release the hotfix version. See the [Creating a hotfix for a
 previously released
-version](site:tutorials/automating-gitlab-releases.md#creating-a-hotfix-for-a-previously-released-version)
+version](site:tutorials/automating-gitlab-releases#creating-a-hotfix-for-a-previously-released-version)
 section of the Automating GitLab Releases tutorial for steps on how to achieve
 this.
 
 ## See also
 
-- [How to enable automated GitLab releases](site:howtos/git-gitlab/enable-automated-gitlab-releases.md).
-- [Automating GitLab releases](site:tutorials/automating-gitlab-releases.md)
+- [How to enable automated GitLab releases](site:howtos/git-gitlab/enable-automated-gitlab-releases).
+- [Automating GitLab releases](site:tutorials/automating-gitlab-releases)
   tutorial.
diff --git a/docs/explanations/misc/identifiers.md b/docs/explanations/misc/identifiers.md
index fba963af..f85d7f3a 100644
--- a/docs/explanations/misc/identifiers.md
+++ b/docs/explanations/misc/identifiers.md
@@ -19,7 +19,7 @@ We have taken a pragmatic approach in defining a common structure for identifier
 precise *formatting* of the structure as flexible to allow for integration with a wider range of
 systems. We discuss this in more detail below.
 
-There is a [separate page of well-known identifier scopes](site:reference/misc/identifiers.md) used within
+There is a [separate page of well-known identifier scopes](site:reference/misc/identifiers) used within
 UIS. This page explains how we use identifiers in DevOps.
 
 ## Scoped and unscoped identifiers
diff --git a/docs/explanations/renovatebot/index.md b/docs/explanations/renovatebot/index.md
index e25d464b..21f03c56 100644
--- a/docs/explanations/renovatebot/index.md
+++ b/docs/explanations/renovatebot/index.md
@@ -35,7 +35,7 @@ of its abilities. Some other features which are of use to DevOps:
 * Automatically applying updates from our webapp and GCP deployment boilerplate template
   repositories. ([Example
   MR](https://gitlab.developers.cam.ac.uk/uis/devops/experiments/rjw57/misc/-/merge_requests/4))
-* Keeping [pre-commit hooks](site:explanations/development/webapp-boilerplate.md#pre-commit) fresh. ([Example
+* Keeping [pre-commit hooks](site:explanations/development/webapp-boilerplate#pre-commit) fresh. ([Example
   MR](https://gitlab.developers.cam.ac.uk/uis/devops/infra/gitlab-bots-deployment/-/merge_requests/24))
 * Making sure that we're always using the most recent version of our [CI
   templates](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-templates).
@@ -157,7 +157,7 @@ This section covers some general tips-and-tricks for renovatebot.
 
 Renovatebot can auto-assign reviewers to the MRs it creates if you make use of a `CODEOWNERS` file.
 There are some limitations in renovatebot's support for this. See the [how to
-guide](site:howtos/renovatebot/auto-assign-renovatebot-mr-reviewers.md) for more information.
+guide](site:howtos/renovatebot/auto-assign-renovatebot-mr-reviewers) for more information.
 
 ### Follow the dashboard issue
 
@@ -191,12 +191,12 @@ manager looks for, add the following to `renovate.json`:
 
 Renovatebot can freshen hooks from [pre-commit configurations](https://pre-commit.com/) but this
 support is currently in beta and you must explicitly
-[opt-in](site:howtos/renovatebot/use-pre-commit-hooks-with-renovatebot.md).
+[opt-in](site:howtos/renovatebot/use-pre-commit-hooks-with-renovatebot).
 
 ### Copier
 
 Renovatebot can try to update webapp and boilerplate configurations which make use of our [copier
-templates](site:howtos/development/copier/create.md). In order to do this the `_src_path` *must*
+templates](site:howtos/development/copier/create). In order to do this the `_src_path` *must*
 be of the form `https://gitlab.developers.cam.ac.uk/...`.
 
 This can make it difficult when using private templates, such as the GCP deployment boilerplate, and
@@ -212,10 +212,10 @@ git config set --global \
 
 The following how-to guides cover specifics of configuring renovatebot:
 
-* [Configure renovatebot for your projects](site:howtos/renovatebot/start-using-renovatebot.md).
-* [Automatically assigning reviewers to MRs](site:howtos/renovatebot/auto-assign-renovatebot-mr-reviewers.md).
+* [Configure renovatebot for your projects](site:howtos/renovatebot/start-using-renovatebot).
+* [Automatically assigning reviewers to MRs](site:howtos/renovatebot/auto-assign-renovatebot-mr-reviewers).
 * [Testing per-project changes to renovatebot's
-  configuration](site:howtos/renovatebot/run-renovatebot-locally.md).
-* [Temporarily disabling renovatebot](site:howtos/renovatebot/disable-renovatebot.md).
+  configuration](site:howtos/renovatebot/run-renovatebot-locally).
+* [Temporarily disabling renovatebot](site:howtos/renovatebot/disable-renovatebot).
 * [Keep docker images fresh in terraform
-  deployments](site:howtos/renovatebot/keep-docker-image-references-fresh.md).
+  deployments](site:howtos/renovatebot/keep-docker-image-references-fresh).
diff --git a/docs/howtos/aws/access-aws-console.md b/docs/howtos/aws/access-aws-console.md
index a421816d..cbec6996 100644
--- a/docs/howtos/aws/access-aws-console.md
+++ b/docs/howtos/aws/access-aws-console.md
@@ -8,7 +8,7 @@ guide](./get-started-with-aws.md) then they will have a file named `.aws-helper.
 the repository. This guide covers how to access the AWS console for such products.
 
 If you're interested in the rationale and background for how we integrate with AWS, there is a
-dedicated [explainer guide](site:explanations/cloud-platform/aws.md).
+dedicated [explainer guide](site:explanations/cloud-platform/aws).
 
 ## Requirements and deliverables
 
@@ -18,7 +18,7 @@ Before you start you will need:
   [template](https://gitlab.developers.cam.ac.uk/uis/devops/gcp-deploy-boilerplate),
 - AWS configuration for that deployment as per the [relevant guide](./get-started-with-aws.md), and
 - the ability to access the Google Cloud console for your project with "editor" rights through a
-  [gcloudadmin account](site:howtos/cloud-platform/create-gcloudadmin-account.md).
+  [gcloudadmin account](site:howtos/cloud-platform/create-gcloudadmin-account).
 
 At the end of the process you will have the ability to access the AWS console for each environment.
 
diff --git a/docs/howtos/aws/audit-aws-console-access.md b/docs/howtos/aws/audit-aws-console-access.md
index 050ed071..ac8dea19 100644
--- a/docs/howtos/aws/audit-aws-console-access.md
+++ b/docs/howtos/aws/audit-aws-console-access.md
@@ -6,7 +6,7 @@ title: Audit AWS console access
 In Google Cloud, changes made via the console or `gcloud` CLI tool are logged against the user's
 `...@gcloudadmin.g.apps.cam.ac.uk` account in the [audit
 log](https://cloud.google.com/logging/docs/audit). Although AWS also has an audit log, we [use a
-shared Admin role](site:explanations/cloud-platform/aws.md) to access the console and so it is
+shared Admin role](site:explanations/cloud-platform/aws) to access the console and so it is
 not quite as straightforward to identify which individuals performed an action should that
 knowledge be needed after the event.
 
diff --git a/docs/howtos/aws/create-aws-accounts.md b/docs/howtos/aws/create-aws-accounts.md
index d34f8450..ab0df9fd 100644
--- a/docs/howtos/aws/create-aws-accounts.md
+++ b/docs/howtos/aws/create-aws-accounts.md
@@ -8,7 +8,7 @@ the AWS organisational management account you will need to ask {{ gitlab_label("
 complete these steps for you.
 
 If you're interested in the rationale and background for how we integrate with AWS, there is a
-dedicated [explainer guide](site:explanations/cloud-platform/aws.md).
+dedicated [explainer guide](site:explanations/cloud-platform/aws).
 
 ## Requirements and deliverables
 
diff --git a/docs/howtos/aws/get-started-with-aws.md b/docs/howtos/aws/get-started-with-aws.md
index 2cb33da0..3cdd81c7 100644
--- a/docs/howtos/aws/get-started-with-aws.md
+++ b/docs/howtos/aws/get-started-with-aws.md
@@ -13,7 +13,7 @@ Cloud and so your product will also need to have a set of Google Cloud projects
 you only intend to use AWS**.
 
 If you're interested in the rationale and background for how we integrate with AWS, there is a
-dedicated [explainer guide](site:explanations/cloud-platform/aws.md).
+dedicated [explainer guide](site:explanations/cloud-platform/aws).
 
 ## Differences between AWS and Google Cloud
 
diff --git a/docs/howtos/aws/use-aws-cli.md b/docs/howtos/aws/use-aws-cli.md
index 1e692c10..e08b70f3 100644
--- a/docs/howtos/aws/use-aws-cli.md
+++ b/docs/howtos/aws/use-aws-cli.md
@@ -9,7 +9,7 @@ the repository. This guide covers how to configure the [AWS command line
 tool](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html) for such products.
 
 If you're interested in the rationale and background for how we integrate with AWS, there is a
-dedicated [explainer guide](site:explanations/cloud-platform/aws.md).
+dedicated [explainer guide](site:explanations/cloud-platform/aws).
 
 Just as only users with "editor" rights can directly manage resources in Google via the `gcloud`
 command line tool, only users with "editor" rights can directly manage resources in AWS via the
@@ -23,7 +23,7 @@ Before you start you will need:
   [template](https://gitlab.developers.cam.ac.uk/uis/devops/gcp-deploy-boilerplate),
 - AWS configuration for that deployment as per the [relevant guide](./get-started-with-aws.md), and
 - the ability to access the Google Cloud console for your project with "editor" rights through a
-  [gcloudadmin account](site:howtos/cloud-platform/create-gcloudadmin-account.md).
+  [gcloudadmin account](site:howtos/cloud-platform/create-gcloudadmin-account).
 
 At the end of the process you will have the ability to access the AWS console for each environment.
 
diff --git a/docs/howtos/cloud-platform/create-gcloudadmin-account.md b/docs/howtos/cloud-platform/create-gcloudadmin-account.md
index 1dab7356..333e06ce 100644
--- a/docs/howtos/cloud-platform/create-gcloudadmin-account.md
+++ b/docs/howtos/cloud-platform/create-gcloudadmin-account.md
@@ -12,7 +12,7 @@ Instead we prefer team members to have a dedicated "gcloudadmin" account used fo
 resources in the Google Cloud console and for deploying services.
 
 An explanation of the use of these accounts and expectations on developer's who have them is covered
-in a [dedicated explainer guide](site:explanations/cloud-platform/gcloudadmin-accounts.md).
+in a [dedicated explainer guide](site:explanations/cloud-platform/gcloudadmin-accounts).
 
 This page describes the process to create a "gcloudadmin" account.
 
diff --git a/docs/howtos/cloud-platform/respond-to-billing-alerts.md b/docs/howtos/cloud-platform/respond-to-billing-alerts.md
index 83521f16..89b87fb1 100644
--- a/docs/howtos/cloud-platform/respond-to-billing-alerts.md
+++ b/docs/howtos/cloud-platform/respond-to-billing-alerts.md
@@ -16,7 +16,7 @@ a corresponding GitLab issue against the
 [gcp-product-factory](https://gitlab.developers.cam.ac.uk/uis/devops/infra/gcp-product-factory)
 including the details from the email alert. This issue can then be worked on
 using our [standard issue lifecycle
-workflow](site:reference/workflow/gitlab.md#the-issue-lifecycle).
+workflow](site:reference/workflow/gitlab#the-issue-lifecycle).
 
 <figure markdown>
 ![Example billing alert](./example-billing-alert-issue.png)
@@ -26,7 +26,7 @@ alert email.</figcaption>
 
 ## Alert: 100% of budget expected to be reached
 
-As detailed in the [Budgets and Alerts](site:explanations/cloud-platform/gcp-budgets-alerts.md)
+As detailed in the [Budgets and Alerts](site:explanations/cloud-platform/gcp-budgets-alerts)
 section, this is the first of two default billing alerts that we configure. When
 this alert is received for a particular product the steps below should be
 followed.
@@ -135,4 +135,4 @@ detailed above to reach a resolution ASAP.
 ## See also
 
 - [Google Cloud Platform Budgets and
-  Alerts](site:explanations/cloud-platform/gcp-budgets-alerts.md)
+  Alerts](site:explanations/cloud-platform/gcp-budgets-alerts)
diff --git a/docs/howtos/development/copier/create.md b/docs/howtos/development/copier/create.md
index 8c563d2b..9826a073 100644
--- a/docs/howtos/development/copier/create.md
+++ b/docs/howtos/development/copier/create.md
@@ -6,7 +6,7 @@ title: Create a new project from a template using the Copier tool
 
 !!! Info
     This how-to guide assumes that the Copier tool has been installed as described in
-    [the how-to guide for preparing your system](site:howtos/development/prepare-your-system.md).
+    [the how-to guide for preparing your system](site:howtos/development/prepare-your-system).
 
 There are two copier-based boilerplate projects:
 
@@ -63,7 +63,7 @@ creation is the following:
 !!! tip "Using https URLs for templates"
 
     The `_src_path` URL in `.copier-answers.yml` should be a `https://...` URL to work well with
-    [renovatebot](site:howtos/renovatebot/start-using-renovatebot.md).
+    [renovatebot](site:howtos/renovatebot/start-using-renovatebot).
     This is fine for public templates but private templates, such as the GCP deploy boilerplate,
     will need the following command to be run to tell git to use SSH to clone those repositories:
 
diff --git a/docs/howtos/development/copier/migrate.md b/docs/howtos/development/copier/migrate.md
index 5f6afc48..64dba042 100644
--- a/docs/howtos/development/copier/migrate.md
+++ b/docs/howtos/development/copier/migrate.md
@@ -6,7 +6,7 @@ title: Migrate an existing cookiecutter project to Copier
 
 !!! Info
     This how-to guide assumes that the Copier tool has been installed as described in
-    [the how-to guide for preparing your system](site:howtos/development/prepare-your-system.md).
+    [the how-to guide for preparing your system](site:howtos/development/prepare-your-system).
 
 !!! info
     For this operation it is necessary to know answers that were used initially.
diff --git a/docs/howtos/development/copier/update.md b/docs/howtos/development/copier/update.md
index 0f3938ae..8a6aa436 100644
--- a/docs/howtos/development/copier/update.md
+++ b/docs/howtos/development/copier/update.md
@@ -6,7 +6,7 @@ title: Update Projects Created from Boilerplate Templates
 
 !!! Info
     This how-to guide assumes that the Copier tool has been installed as described in
-    [the how-to guide for preparing your system](site:howtos/development/prepare-your-system.md).
+    [the how-to guide for preparing your system](site:howtos/development/prepare-your-system).
 
 Over time, the boilerplate is updated and it is might becomes necessary to update the project as
 well with new changes. With copier it can be done in few simple steps.
diff --git a/docs/howtos/development/create-a-new-app.md b/docs/howtos/development/create-a-new-app.md
index 87b9f076..19615445 100644
--- a/docs/howtos/development/create-a-new-app.md
+++ b/docs/howtos/development/create-a-new-app.md
@@ -8,13 +8,13 @@ We have a standard template for our web applications. Our template includes supp
 provided alongside the application and for "pure" API applications. This guide covers how to create
 a new application from our boilerplate template, starting it and running the tests.
 
-Read our [explainer on the webapp boilerplate](site:explanations/development/webapp-boilerplate.md)
+Read our [explainer on the webapp boilerplate](site:explanations/development/webapp-boilerplate)
 if you're unsure whether the boilerplate is right for you.
 
 ## Prepare your system
 
 If you have not already done so, make sure you have followed our [how-to guide for preparing your
-system](site:howtos/development/prepare-your-system.md) and installed the software which it recommends.
+system](site:howtos/development/prepare-your-system) and installed the software which it recommends.
 
 We use the [copier](https://copier.readthedocs.io/) to apply our webapp templates.
 Make sure that it is installed on your system via:
@@ -35,7 +35,7 @@ application.
 
 !!! Info
     More information on working with copier templates is available
-    on a [dedicated page](site:reference/deployment/templates.md).
+    on a [dedicated page](site:reference/deployment/templates).
 
 Start the template process via:
 
@@ -87,5 +87,5 @@ In this guide you learned how to create a new boilerplate application using our
 
 ## Next steps
 
-- Read the [developer reference](site:reference/misc/webapp-developer-environment.md) for the developer
+- Read the [developer reference](site:reference/misc/webapp-developer-environment) for the developer
   environment.
diff --git a/docs/howtos/development/generate-api-clients.md b/docs/howtos/development/generate-api-clients.md
index 884b3205..5a648842 100644
--- a/docs/howtos/development/generate-api-clients.md
+++ b/docs/howtos/development/generate-api-clients.md
@@ -12,7 +12,7 @@ engage in "specification-first" development where one starts with a *description
 OpenAPI file and, from that specification, one generates the backend API implementation.
 
 This how-to guide describes how to generate API clients automatically using features in the
-[common pipeline](site:howtos/python/add-common-pipeline-to-python.md).
+[common pipeline](site:howtos/python/add-common-pipeline-to-python).
 
 ## Prerequisites
 
@@ -128,5 +128,5 @@ implementation.
 
 ## Next steps
 
-Read the full [reference guide](site:reference/misc/openapi-client-generation.md) for further
+Read the full [reference guide](site:reference/misc/openapi-client-generation) for further
 customisation.
diff --git a/docs/howtos/development/migrate-a-gcp-cloud-run-app-terraform-deployment-to-v9.md b/docs/howtos/development/migrate-a-gcp-cloud-run-app-terraform-deployment-to-v9.md
index 823752db..60ec2da4 100644
--- a/docs/howtos/development/migrate-a-gcp-cloud-run-app-terraform-deployment-to-v9.md
+++ b/docs/howtos/development/migrate-a-gcp-cloud-run-app-terraform-deployment-to-v9.md
@@ -18,7 +18,7 @@ _will_ require teams to perform some refactoring to migrate to. This page
 describes the steps required to upgrade to version `9.0.0` from previous
 versions of the module. For more information about the changes and
 considerations required when migrating from previous versions to version `9.0.0`
-please see the [explanation page](site:explanations/cloud-platform/gcp-cloud-run-app-module.md).
+please see the [explanation page](site:explanations/cloud-platform/gcp-cloud-run-app-module).
 
 !!! Warning
     Version `9.0.0` contains breaking changes! The web application will be redeployed once new
@@ -91,7 +91,7 @@ module "webapp" {
 ```
 
 If you use Copier, update your project to the latest boilerplate release following
-[the instructions](site:howtos/development/copier/copier-update.md).
+[the instructions](site:howtos/development/copier/copier-update).
 At this point it is possible for Terraform to download the new module version by running
 `terraform init`. The new version will be downloaded, but the command will fail as the module
 syntax has changed and needs to be updated.
diff --git a/docs/howtos/development/prepare-your-system.md b/docs/howtos/development/prepare-your-system.md
index 05727659..33a05c26 100644
--- a/docs/howtos/development/prepare-your-system.md
+++ b/docs/howtos/development/prepare-your-system.md
@@ -21,7 +21,7 @@ installed on your system:
    docker compose plugin](https://docs.docker.com/compose/install/linux/).
 3. **Git.** GitHub provide a [guide on installing
    git](https://github.com/git-guides/install-git). You will also need to make sure that you can
-   [sign in to GitLab](site:howtos/git-gitlab/sign-in-to-gitlab.md).
+   [sign in to GitLab](site:howtos/git-gitlab/sign-in-to-gitlab).
 4. **Python.** (Optional) On Mac machines you can use [homebrew](https://brew.sh/). On
    both Linux and Mac machines you can use the system Python or use solutions such as
    [pyenv](https://github.com/pyenv/pyenv) to install specific versions. We try to support
@@ -37,7 +37,7 @@ installed on your system:
    on Mac machines for OpenJDK to be found**. See the homebrew page for details. On Linux, OpenJDK
    will usually be available in your distribution's package manager. If your project uses
    the [GitLab package registry](https://docs.gitlab.com/ee/user/packages/maven_repository/), see
-   [how-to configure your Maven settings.xml](site:howtos/java/configure-access-to-gitlab-java-repositories.md).
+   [how-to configure your Maven settings.xml](site:howtos/java/configure-access-to-gitlab-java-repositories).
 7. **1Password cli tools.** (Optional) If you need to run scripts using the 'op' tool, follow the
 [official 1Password guide](https://developer.1password.com/docs/cli/get-started/) to install
 (step 1) and enable the desktop app integration (step 2).
@@ -194,4 +194,4 @@ In this guide you learned how to install software required for common developmen
 
 ## Next steps
 
-* Read [how to create a new web application](site:howtos/development/create-a-new-app.md).
+* Read [how to create a new web application](site:howtos/development/create-a-new-app).
diff --git a/docs/howtos/development/run-an-existing-app.md b/docs/howtos/development/run-an-existing-app.md
index d4df2f0b..3ef7900e 100644
--- a/docs/howtos/development/run-an-existing-app.md
+++ b/docs/howtos/development/run-an-existing-app.md
@@ -10,13 +10,13 @@ where you can access a local instance in your browser and run tests locally.
 !!! warning
 
     This guide is appropriate for applications which do **not** have a `compose.sh` file in the root
-    of the repository. See the [older reference guide](site:notes/webapp-dev-environment.md) if that
+    of the repository. See the [older reference guide](site:notes/webapp-dev-environment) if that
     file is present.
 
 ## Prerequisites
 
 If you have not already done so, make sure you have followed our [how-to guide for preparing your
-system](site:howtos/development/prepare-your-system.md) and installed the software which it recommends.
+system](site:howtos/development/prepare-your-system) and installed the software which it recommends.
 You should confirm that the `docker`, `poetry` and `poe` commands are present on your `PATH`
 and that the `docker compose` plugin is installed.
 
@@ -35,7 +35,7 @@ more information.
 !!! tip
 
     If the `README.md` file *doesn't* include something which you later find out is required for
-    bootstrapping, [open an issue](site:howtos/git-gitlab/open-an-issue.md) and,
+    bootstrapping, [open an issue](site:howtos/git-gitlab/open-an-issue) and,
     if you feel comfortable, a merge request adding the missing information.
 
 You may be used to manually creating a virtualenv for Python projects in a directory named `venv` or
@@ -48,7 +48,7 @@ poetry install
 
 ??? question "What is a "virtualenv" and what does "poetry install" do?"
 
-    We cover this in the [explainer document](site:explanations/development/webapp-boilerplate.md)
+    We cover this in the [explainer document](site:explanations/development/webapp-boilerplate)
     about our webapp boilerplate.
 
 Check that the test suite passes:
@@ -97,4 +97,4 @@ application.
 ## Next steps
 
 * Read more about what you can do with our webapp developer environment in the [reference
-  guide](site:reference/misc/webapp-developer-environment.md).
+  guide](site:reference/misc/webapp-developer-environment).
diff --git a/docs/howtos/development/setup-pre-commit-hooks.md b/docs/howtos/development/setup-pre-commit-hooks.md
index 9bb0259b..048fda4e 100644
--- a/docs/howtos/development/setup-pre-commit-hooks.md
+++ b/docs/howtos/development/setup-pre-commit-hooks.md
@@ -150,5 +150,5 @@ In this how-to you learned how to set-up a standard set of pre-commit hooks on a
 
 Further information on using pre-commit:
 
-- [Webapp developer environment](site:explanations/development/webapp-boilerplate.md#pre-commit)
-- [Creating a Python package](site:tutorials/creating-a-python-package.md#catching-and-fixing-style-issues)
+- [Webapp developer environment](site:explanations/development/webapp-boilerplate#pre-commit)
+- [Creating a Python package](site:tutorials/creating-a-python-package#catching-and-fixing-style-issues)
diff --git a/docs/howtos/email/register-with-user-notify.md b/docs/howtos/email/register-with-user-notify.md
index 69bc9cf7..d1fdc580 100644
--- a/docs/howtos/email/register-with-user-notify.md
+++ b/docs/howtos/email/register-with-user-notify.md
@@ -2,7 +2,7 @@
 title: Register your service
 ---
 
-In DevOps we have an internal [User Notify service](site:libraries-tools/user-notify.md)
+In DevOps we have an internal [User Notify service](site:libraries-tools/user-notify)
 which can be used to send email to users of your service. This guide covers how to register
 your service to send email.
 
@@ -67,7 +67,7 @@ To use advanced features, you will need:
   reports.)
 - **Technical IAM principals** which are principals such as Lookup groups or Google groups which
   will be able to read technical configuration information. These should ideally be Google groups
-  containing [gcloudadmin accounts](site:howtos/cloud-platform/create-gcloudadmin-account.md)
+  containing [gcloudadmin accounts](site:howtos/cloud-platform/create-gcloudadmin-account)
   and are intended for complex use cases where automated configuration provision does not suffice.
 
 ## Requesting registration
@@ -82,7 +82,7 @@ Once you have the required information you can request that your service be regi
 
     *Very* broadly speaking, only your production and, perhaps, staging environments should be able
     to send "real" email and for other environments you should instead log the emails which _would_
-    be sent.  We have a [mailtrap account](site:reference/best-practice/ourtools.md#mailtrap)
+    be sent.  We have a [mailtrap account](site:reference/best-practice/ourtools#mailtrap)
     which can be used for an "inbox-like" view of email messages which would be sent.
     The opinionated Python client library also includes a `MockSession` class
     if you don't need mailtrap's features and Django includes an in-memory email backend.
diff --git a/docs/howtos/entra-azure/add-sso-sign-in.md b/docs/howtos/entra-azure/add-sso-sign-in.md
index dcfcdd3a..320ecbbe 100644
--- a/docs/howtos/entra-azure/add-sso-sign-in.md
+++ b/docs/howtos/entra-azure/add-sso-sign-in.md
@@ -17,7 +17,7 @@ on integrating SSO with web applications. Configuration varies between web frame
 you will need the following information to configure sign in:
 
 * One or more URLs providing OAuth 2.0 or OpenID Connect (OIDC) endpoints. [Appropriate values for
-  University of Cambridge sign-in](site:reference/misc/entra-id.md) are provided elsewhere in the
+  University of Cambridge sign-in](site:reference/misc/entra-id) are provided elsewhere in the
   guidebook.
 * A "redirect URL" which is a URL pointing to your web application. Entra ID redirects the user
   to this URL after sign in is completed. **This URL is web framework dependant.**
@@ -305,7 +305,7 @@ credential_secrets:
 ### Granting an individual user access
 
 If you don't have a useful group defined in the team data file, you can grant access to individuals.
-We prefer using [gcloudadmin accounts](site:howtos/cloud-platform/create-gcloudadmin-account.md)
+We prefer using [gcloudadmin accounts](site:howtos/cloud-platform/create-gcloudadmin-account)
 when possible.
 
 To grant a user access to the secret:
@@ -354,4 +354,4 @@ how to store them in a Google Cloud secret using a custom format for your applic
 ## Next steps
 
 * [Use custom roles to add authorisation to your apps](./authorise-web-apps-with-custom-roles.md).
-* [Learn more about Azure and Entra ID Applications](site:explanations/cloud-platform/azure-and-entra-id-apps.md).
+* [Learn more about Azure and Entra ID Applications](site:explanations/cloud-platform/azure-and-entra-id-apps).
diff --git a/docs/howtos/entra-azure/authorise-web-apps-with-custom-roles.md b/docs/howtos/entra-azure/authorise-web-apps-with-custom-roles.md
index 95d8c1cb..0e1caae0 100644
--- a/docs/howtos/entra-azure/authorise-web-apps-with-custom-roles.md
+++ b/docs/howtos/entra-azure/authorise-web-apps-with-custom-roles.md
@@ -106,4 +106,4 @@ applications.
 
 ## Next steps
 
-* [Read more about Azure and Entra ID applications](site:explanations/cloud-platform/azure-and-entra-id-apps.md).
+* [Read more about Azure and Entra ID applications](site:explanations/cloud-platform/azure-and-entra-id-apps).
diff --git a/docs/howtos/entra-azure/register-azure-api-management-app.md b/docs/howtos/entra-azure/register-azure-api-management-app.md
index 5356e006..b4498c66 100644
--- a/docs/howtos/entra-azure/register-azure-api-management-app.md
+++ b/docs/howtos/entra-azure/register-azure-api-management-app.md
@@ -150,4 +150,4 @@ management and how to test that you can obtain an access token.
 
 ## Next steps
 
-* [Learn more about Azure and Entra ID Applications](site:explanations/cloud-platform/azure-and-entra-id-apps.md).
+* [Learn more about Azure and Entra ID Applications](site:explanations/cloud-platform/azure-and-entra-id-apps).
diff --git a/docs/howtos/git-gitlab/common-git-tasks.md b/docs/howtos/git-gitlab/common-git-tasks.md
index e5637589..5785a30c 100644
--- a/docs/howtos/git-gitlab/common-git-tasks.md
+++ b/docs/howtos/git-gitlab/common-git-tasks.md
@@ -157,5 +157,5 @@ above._
 
 ## Next steps
 
-* Learn more about [git concepts](site:explanations/git-gitlab/git.md).
-* See a list of [recommended external git documentation](site:reference/git-gitlab/git-docs.md).
+* Learn more about [git concepts](site:explanations/git-gitlab/git).
+* See a list of [recommended external git documentation](site:reference/git-gitlab/git-docs).
diff --git a/docs/howtos/git-gitlab/create-a-feature-branch.md b/docs/howtos/git-gitlab/create-a-feature-branch.md
index 87925183..cefa5cd4 100644
--- a/docs/howtos/git-gitlab/create-a-feature-branch.md
+++ b/docs/howtos/git-gitlab/create-a-feature-branch.md
@@ -37,5 +37,5 @@ push changes.
 
 ## Next steps
 
-* Learn more about [git concepts](site:explanations/git-gitlab/git.md).
-* See a list of [recommended external git documentation](site:reference/git-gitlab/git-docs.md).
+* Learn more about [git concepts](site:explanations/git-gitlab/git).
+* See a list of [recommended external git documentation](site:reference/git-gitlab/git-docs).
diff --git a/docs/howtos/git-gitlab/enable-automated-gitlab-releases.md b/docs/howtos/git-gitlab/enable-automated-gitlab-releases.md
index b5bf2175..1bac8650 100644
--- a/docs/howtos/git-gitlab/enable-automated-gitlab-releases.md
+++ b/docs/howtos/git-gitlab/enable-automated-gitlab-releases.md
@@ -8,7 +8,7 @@ This guide shows you how to enable automated releases of your GitLab code using
 the [release-it](https://github.com/release-it/release-it) tool via our
 [`release-it.yml`](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-templates/-/blob/master/auto-devops/release-it.yml)
 GitLab template. For detailed information on how this process works, see the
-[GitLab Release Automation](site:explanations/git-gitlab/gitlab-release-automation.md) page
+[GitLab Release Automation](site:explanations/git-gitlab/gitlab-release-automation) page
 in the [Learn](site:tutorials) section.
 
 ## Prerequisites
@@ -62,7 +62,7 @@ most of our projects.
 
 !!! warning
     The release it CI jobs are added as part of the [common
-    pipeline](site:howtos/python/add-common-pipeline-to-python.md) but can be added to
+    pipeline](site:howtos/python/add-common-pipeline-to-python) but can be added to
     projects not using the common pipeline by adding an appropriate `include` statement
     to your CI config which references [the
     template](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-templates/-/blob/master/auto-devops/release-it.yml?ref_type=heads):
@@ -78,7 +78,7 @@ most of our projects.
 
 For further information on how this process works see the following.
 
-- [GitLab release automation](site:explanations/git-gitlab/gitlab-release-automation.md)
+- [GitLab release automation](site:explanations/git-gitlab/gitlab-release-automation)
 explanation.
-- [Automating GitLab releases](site:tutorials/automating-gitlab-releases.md)
+- [Automating GitLab releases](site:tutorials/automating-gitlab-releases)
   tutorial.
diff --git a/docs/howtos/git-gitlab/open-an-issue.md b/docs/howtos/git-gitlab/open-an-issue.md
index 4962e9a8..cbda0286 100644
--- a/docs/howtos/git-gitlab/open-an-issue.md
+++ b/docs/howtos/git-gitlab/open-an-issue.md
@@ -7,7 +7,7 @@ title: Open an issue
 We use issues to track individual units of work. We use the University's GitLab
 instance at <https://gitlab.developers.cam.ac.uk/> to manage them. If you've not
 yet signed in to GitLab, see the [signing in to GitLab
-how-to](site:howtos/git-gitlab/sign-in-to-gitlab.md).
+how-to](site:howtos/git-gitlab/sign-in-to-gitlab).
 
 This how-to covers creating issues and their structure.
 
@@ -49,7 +49,7 @@ To create a new issue:
 8. Add an `issueType::...` label if the template did not do so already.
 9. Consider adding special-use labels such as {{ gitlab_label("chore") }} or {{
    gitlab_label("good first issue") }}. See the [labels
-   reference](site:reference/git-gitlab/gitlab-labels.md) for possible labels.
+   reference](site:reference/git-gitlab/gitlab-labels) for possible labels.
 
 ## Summary
 
@@ -58,5 +58,5 @@ issue within it.
 
 ## Next steps
 
-* Learn about [writing good issues](site:explanations/git-gitlab/good-issues.md).
-* See how we use [GitLab labels on issues](site:reference/git-gitlab/gitlab-labels.md).
+* Learn about [writing good issues](site:explanations/git-gitlab/good-issues).
+* See how we use [GitLab labels on issues](site:reference/git-gitlab/gitlab-labels).
diff --git a/docs/howtos/git-gitlab/sign-in-to-gitlab.md b/docs/howtos/git-gitlab/sign-in-to-gitlab.md
index 1319e580..5bcb7cd7 100644
--- a/docs/howtos/git-gitlab/sign-in-to-gitlab.md
+++ b/docs/howtos/git-gitlab/sign-in-to-gitlab.md
@@ -34,4 +34,4 @@ In this how-to, you learned how to sign in to GitLab using GitLab.
 
 ## Next steps
 
-* Try [opening an issue](site:howtos/git-gitlab/open-an-issue.md).
+* Try [opening an issue](site:howtos/git-gitlab/open-an-issue).
diff --git a/docs/howtos/git-gitlab/size-issues.md b/docs/howtos/git-gitlab/size-issues.md
index 576746d4..3ef42550 100644
--- a/docs/howtos/git-gitlab/size-issues.md
+++ b/docs/howtos/git-gitlab/size-issues.md
@@ -82,5 +82,5 @@ In this guide, you learned how we size issues.
 
 ## Next steps
 
-- Learn about [writing good issues](site:explanations/git-gitlab/good-issues.md).
-- See how we use [GitLab labels on issues](site:reference/git-gitlab/gitlab-labels.md).
+- Learn about [writing good issues](site:explanations/git-gitlab/good-issues).
+- See how we use [GitLab labels on issues](site:reference/git-gitlab/gitlab-labels).
diff --git a/docs/howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation.md b/docs/howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation.md
index 136192ae..f3d7085f 100644
--- a/docs/howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation.md
+++ b/docs/howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation.md
@@ -100,4 +100,4 @@ account to retrieve the secret value from a CI job script.
 
 ## See also
 
-- [GKE GitLab Runners explanation](site:explanations/cloud-platform/gke-gitlab-runners.md)
+- [GKE GitLab Runners explanation](site:explanations/cloud-platform/gke-gitlab-runners)
diff --git a/docs/howtos/gke-gitlab-runners/developer-overview.md b/docs/howtos/gke-gitlab-runners/developer-overview.md
index b07aeecc..cc24c93c 100644
--- a/docs/howtos/gke-gitlab-runners/developer-overview.md
+++ b/docs/howtos/gke-gitlab-runners/developer-overview.md
@@ -34,7 +34,7 @@ will automatically run on the correct runner.
 ## What should I read next?
 
 <!-- markdownlint-disable MD013 -->
-- [GitLab CI runners](site:explanations/cloud-platform/service-infrastructure.md#gitlab-ci-runners): Explains the
+- [GitLab CI runners](site:explanations/cloud-platform/service-infrastructure#gitlab-ci-runners): Explains the
   architecture of the GitLab runners in UIS.
 - [How to register GKE-hosted GitLab runners](./register-a-gke-gitlab-runner.md):
   A guide on how to deploy/register Google Kubernetes Engine (GKE) hosted GitLab runners.
diff --git a/docs/howtos/gke-gitlab-runners/register-a-gke-gitlab-runner.md b/docs/howtos/gke-gitlab-runners/register-a-gke-gitlab-runner.md
index 7dcd7fd5..d9a321b4 100644
--- a/docs/howtos/gke-gitlab-runners/register-a-gke-gitlab-runner.md
+++ b/docs/howtos/gke-gitlab-runners/register-a-gke-gitlab-runner.md
@@ -10,7 +10,7 @@ for products deployed by the
 repository.
 
 For more information on the GKE runner configuration, see
-[gke-gitlab-runners](site:reference/cloud-platform/gke-gitlab-runners.md) in the
+[gke-gitlab-runners](site:reference/cloud-platform/gke-gitlab-runners) in the
 reference section.
 
 ## Prerequisites
@@ -30,7 +30,7 @@ The following information will be required to complete the steps in this guide.
 1. Clone the
    [`gitlab-runner-infrastructure`](https://gitlab.developers.cam.ac.uk/uis/devops/devhub/gitlab-runner-infrastructure)
    repository to your local machine.
-2. Create a [new feature branch](site:explanations/git-gitlab/git.md#feature-branches) for your changes.
+2. Create a [new feature branch](site:explanations/git-gitlab/git#feature-branches) for your changes.
 3. In `locals.tf`, add your new product to the `product_runners.production` map using the
    information from the prerequisites section above. For example, if you are adding a new product
    called `test-product` you might do the following.
@@ -52,7 +52,7 @@ The following information will be required to complete the steps in this guide.
     }
     ```
 
-4. [Commit](site:explanations/git-gitlab/git.md#commits) your changes,
+4. [Commit](site:explanations/git-gitlab/git#commits) your changes,
    push your branch to the remote, and open a merge request.
 5. The merge request should be reviewed, merged, and deployed by a member of the Cloud Team.
    Deployment steps can be found in the
diff --git a/docs/howtos/gke-gitlab-runners/run-ci-jobs-on-a-gke-gitlab-runner.md b/docs/howtos/gke-gitlab-runners/run-ci-jobs-on-a-gke-gitlab-runner.md
index efaab37e..dca3cccb 100644
--- a/docs/howtos/gke-gitlab-runners/run-ci-jobs-on-a-gke-gitlab-runner.md
+++ b/docs/howtos/gke-gitlab-runners/run-ci-jobs-on-a-gke-gitlab-runner.md
@@ -11,7 +11,7 @@ this see the **explanation on GKE-hosted runners**.
 ## Prerequisites
 
 - Ensure that the product in question has been configured with a GKE-hosted GitLab runner. See [GKE
-  GitLab Runners](site:reference/cloud-platform/gke-gitlab-runners.md) for more information.
+  GitLab Runners](site:reference/cloud-platform/gke-gitlab-runners) for more information.
 
 ## Steps
 
diff --git a/docs/howtos/java/add-common-pipeline-and-precommit-to-java.md b/docs/howtos/java/add-common-pipeline-and-precommit-to-java.md
index 427e147d..86fe0365 100644
--- a/docs/howtos/java/add-common-pipeline-and-precommit-to-java.md
+++ b/docs/howtos/java/add-common-pipeline-and-precommit-to-java.md
@@ -139,7 +139,7 @@ retrieve secrets from Secrets Manager.
 ## Add the google-java-format pre-commit plugin
 
 The google-java-format pre-commit plugin should also be
-[added to the project](site:howtos/development/setup-pre-commit-hooks.md#java).
+[added to the project](site:howtos/development/setup-pre-commit-hooks#java).
 
 ## IDE formatter configuration
 
diff --git a/docs/howtos/products/bootstrap-a-product.md b/docs/howtos/products/bootstrap-a-product.md
index 03c9a883..eb347c7e 100644
--- a/docs/howtos/products/bootstrap-a-product.md
+++ b/docs/howtos/products/bootstrap-a-product.md
@@ -14,14 +14,14 @@ This guide is intentionally brief. If you have questions when reading, see the f
 for additional context:
 
 * Tutorials
-    * [Bootstrapping a new web-application product](site:tutorials/bootstrapping-a-new-application.md)
+    * [Bootstrapping a new web-application product](site:tutorials/bootstrapping-a-new-application)
 * Explainers
-    * [How our service infrastructure is configured](site:explanations/cloud-platform/service-infrastructure.md)
-    * [GitLab CI runners](site:explanations/cloud-platform/gke-gitlab-runners.md)
+    * [How our service infrastructure is configured](site:explanations/cloud-platform/service-infrastructure)
+    * [GitLab CI runners](site:explanations/cloud-platform/gke-gitlab-runners)
 * Reference
     * [How we deploy to Google Cloud](site:reference/deployment)
     * [Google Cloud projects and folders](site:reference/cloud-platform)
-    * [How GitLab CI runners are deployed](site:reference/cloud-platform/gke-gitlab-runners.md)
+    * [How GitLab CI runners are deployed](site:reference/cloud-platform/gke-gitlab-runners)
 
 ## Decide on the development team
 
@@ -70,7 +70,7 @@ Optionally, there are other fields you can provide:
 
 * msteams_channel_webhook_urls: allows you to specify a Microsoft Teams channel to receive
   notifications from Google Cloud. This is useful for monitoring and alerting purposes.
-  See [MS Teams Workflows Webhooks](site:howtos/msteams/workflows-webhooks.md)
+  See [MS Teams Workflows Webhooks](site:howtos/msteams/workflows-webhooks)
 
 Open an issue in
 [gcp-product-factory](https://gitlab.developers.cam.ac.uk/uis/devops/infra/gcp-product-factory/) and
@@ -152,7 +152,7 @@ Usually you'll want to create two projects to start with:
 * a `webapp` project which holds Python code based on our [web application
   boilerplate](https://gitlab.developers.cam.ac.uk/uis/devops/webapp-boilerplate/).
 
-We are [open by default](site:reference/workflow/gitlab.md#open-by-default) and so
+We are [open by default](site:reference/workflow/gitlab#open-by-default) and so
 the visibility of `webapp` can be `public` and should not be less than `internal`.
 As the infrastructure project can be externally sensitive, we recommend having
 the visibility of `infrastructure` be at most `internal`.
@@ -201,9 +201,9 @@ projects = {
 
 ??? "What is `container_expiration_policy`?"
 
-    Our [common CI pipeline](site:howtos/python/add-common-pipeline-to-python.md) will
+    Our [common CI pipeline](site:howtos/python/add-common-pipeline-to-python) will
     automatically build container images. If you are using [release
-    automation](site:howtos/git-gitlab/enable-automated-gitlab-releases.md),
+    automation](site:howtos/git-gitlab/enable-automated-gitlab-releases),
     images corresponding to released versions will be tagged with names of the form
     `{x}.{y}.{z}` and automatically pushed to Google Cloud for later deployment.
 
@@ -264,7 +264,7 @@ locals {
 ```
 
 Once {{ gitlab_label("team::Cloud") }} have addressed your issue, you can [create a new
-application](site:howtos/development/create-a-new-app.md).
+application](site:howtos/development/create-a-new-app).
 
 ## Summary
 
@@ -274,5 +274,5 @@ product in all three places ready for development to start.
 
 ## Next steps
 
-* [Bootstrap a new web application](site:howtos/development/create-a-new-app.md) from our boilerplate.
+* [Bootstrap a new web application](site:howtos/development/create-a-new-app) from our boilerplate.
 * [Deploy the empty application to Google Cloud](site:reference/deployment).
diff --git a/docs/howtos/products/check-product-configuration.md b/docs/howtos/products/check-product-configuration.md
index fce4fdec..67796fb3 100644
--- a/docs/howtos/products/check-product-configuration.md
+++ b/docs/howtos/products/check-product-configuration.md
@@ -13,7 +13,7 @@ scratch.
 The word "product" can mean many things in the DevOps division. In particular what a "product" means
 from a GitLab perspective may be different than from a "Google Cloud" perspective. We have a
 dedicated explainer covering [products and service
-infrastructure](site:explanations/cloud-platform/service-infrastructure.md).
+infrastructure](site:explanations/cloud-platform/service-infrastructure).
 
 The following sections cover the checks you should make.
 
diff --git a/docs/howtos/products/delete-product-infrastructure.md b/docs/howtos/products/delete-product-infrastructure.md
index 413fd88f..066e144e 100644
--- a/docs/howtos/products/delete-product-infrastructure.md
+++ b/docs/howtos/products/delete-product-infrastructure.md
@@ -26,7 +26,7 @@ information illustrates the right order.
 First, it is needed to delete the top-level infrastructure, i.e. resources that are used
 by the product's deployment (Cloud SQL instances, Cloud Run instances, so on).
 
-Almost all infrastructure projects were created from [the template](site:reference/deployment/templates.md).
+Almost all infrastructure projects were created from [the template](site:reference/deployment/templates).
 However, the set of resources may vary from product to product (e.g. some products use the MySQL
 database and others use the PostgreSQL database), so there is no universal solution.
 The general steps are as follows:
diff --git a/docs/howtos/python/publish-a-python-package.md b/docs/howtos/python/publish-a-python-package.md
index 4a594966..14af9011 100644
--- a/docs/howtos/python/publish-a-python-package.md
+++ b/docs/howtos/python/publish-a-python-package.md
@@ -9,10 +9,10 @@ title: Publish a package
     This page assumes that you are working with an *existing* Python package
     which has been configured for auto-publishing via our common pipeline.
     See [how to add the common pipeline to a Python
-    package](site:howtos/python/add-common-pipeline-to-python.md) if this has not been done.
+    package](site:howtos/python/add-common-pipeline-to-python) if this has not been done.
 
     If you want to learn more about how we structure Python packages, follow
-    [our Python package tutorial](site:tutorials/creating-a-python-package.md).
+    [our Python package tutorial](site:tutorials/creating-a-python-package).
 
 Python packages which make use of our common pipeline are set up to auto-publish
 packages when a new git tag is pushed.
@@ -78,4 +78,4 @@ project.
 ## Next steps
 
 * See [how to add the common pipeline to an existing Python
-  package](site:howtos/python/add-common-pipeline-to-python.md).
+  package](site:howtos/python/add-common-pipeline-to-python).
diff --git a/docs/howtos/python/pypi.md b/docs/howtos/python/pypi.md
index a948b3d6..8ccbdba2 100644
--- a/docs/howtos/python/pypi.md
+++ b/docs/howtos/python/pypi.md
@@ -10,7 +10,7 @@ Python package to the public PyPI repository.
 !!! info
 
     This document is a goal-oriented "how-to" guide. We have a separate
-    [explainer page](site:reference/workflow/pypi.md) which goes into more details on
+    [explainer page](site:reference/workflow/pypi) which goes into more details on
     the "why" of this process.
 
 ## Sign in to PyPI
diff --git a/docs/howtos/renovatebot/deploy-releases-with-renovatebot.md b/docs/howtos/renovatebot/deploy-releases-with-renovatebot.md
index f729eea1..26d8db94 100644
--- a/docs/howtos/renovatebot/deploy-releases-with-renovatebot.md
+++ b/docs/howtos/renovatebot/deploy-releases-with-renovatebot.md
@@ -29,10 +29,10 @@ deployment projects when new releases of your web app are made in GitLab.
 ## Prerequisites
 
 Your upstream web app projects must have [release automation
-enabled](site:howtos/git-gitlab/enable-automated-gitlab-releases.md)
+enabled](site:howtos/git-gitlab/enable-automated-gitlab-releases)
 and use [semver](https://semver.org/) versioning.
 
-You must have [enabled renovatebot](site:howtos/renovatebot/start-using-renovatebot.md)
+You must have [enabled renovatebot](site:howtos/renovatebot/start-using-renovatebot)
 in the deployment project holding your terraform.
 
 ## Enable the terraformWebappRelease preset
@@ -101,6 +101,6 @@ automatically open Merge Requests when new versions of the deployed web apps are
 
 ## Next steps
 
-* [How to configure release automation](site:howtos/git-gitlab/enable-automated-gitlab-releases.md)
+* [How to configure release automation](site:howtos/git-gitlab/enable-automated-gitlab-releases)
 * [Manually triggering renovatebot](./trigger-renovatebot-from-gitlab-ui.md)
 * [Triggering renovatebot from CI](./trigger-renovatebot-from-ci.md)
diff --git a/docs/howtos/renovatebot/trigger-renovatebot-from-ci.md b/docs/howtos/renovatebot/trigger-renovatebot-from-ci.md
index c58c2cb6..106a7a58 100644
--- a/docs/howtos/renovatebot/trigger-renovatebot-from-ci.md
+++ b/docs/howtos/renovatebot/trigger-renovatebot-from-ci.md
@@ -32,7 +32,7 @@ the project containing the CI pipeline.
 ## Triggering runs in other projects
 
 Suppose you have two projects `uis/devops/puntbooking/infra` and `uis/devops/puntbooking/webapp`.
-You have [release automation](site:howtos/git-gitlab/enable-automated-gitlab-releases.md)
+You have [release automation](site:howtos/git-gitlab/enable-automated-gitlab-releases)
 enabled for the `webapp`.
 You have [added configuration](https://gitlab.developers.cam.ac.uk/uis/devops/renovate-config#keeping-terraform-configurations-up-to-date-with-latest-release-of-a-web-app)
 in `uis/devops/puntbooking/infra` to open Merge Requests when new releases of `webapp` are made.
diff --git a/docs/howtos/renovatebot/trigger-renovatebot-from-cli.md b/docs/howtos/renovatebot/trigger-renovatebot-from-cli.md
index 91624251..d6f0b31a 100644
--- a/docs/howtos/renovatebot/trigger-renovatebot-from-cli.md
+++ b/docs/howtos/renovatebot/trigger-renovatebot-from-cli.md
@@ -13,9 +13,9 @@ This guide covers how you can trigger a renovatebot run yourself from the comman
 ## Prerequisites
 
 * The `gcloud` CLI tool must be installed as per the guide on [preparing your
-  system](site:howtos/development/prepare-your-system.md).
+  system](site:howtos/development/prepare-your-system).
 * You must be authenticated via `gcloud auth login` with a [gcloudadmin
-  account](site:howtos/cloud-platform/create-gcloudadmin-account.md).
+  account](site:howtos/cloud-platform/create-gcloudadmin-account).
 * You must have the [httpie command line tool](https://httpie.io/) installed.
 
 ## Triggering a run
diff --git a/docs/libraries-tools/gcp-terraform.md b/docs/libraries-tools/gcp-terraform.md
index 2dd10da0..e3c3c1f7 100644
--- a/docs/libraries-tools/gcp-terraform.md
+++ b/docs/libraries-tools/gcp-terraform.md
@@ -7,15 +7,15 @@ Our adopted & recommended tools & services for Google Cloud Platform (GCP) and T
 <!-- markdownlint-disable MD013 -->
 | Title                                                           | Summary                                                  | Our Docs                                                                                                          |
 |-----------------------------------------------------------------|----------------------------------------------------------|-------------------------------------------------------------------------------------------------------------------|
-| [Cloud Run](https://cloud.google.com/run)                       | Serverless container platform for stateless applications | [Reference](site:reference/cloud-platform), [Migration](site:explanations/cloud-platform/gcp-cloud-run-app-module.md) |
-| [Cloud SQL](https://cloud.google.com/sql)                       | Fully managed relational database service                | [Backups](site:reference/cloud-platform/backups.md)                                                              |
+| [Cloud Run](https://cloud.google.com/run)                       | Serverless container platform for stateless applications | [Reference](site:reference/cloud-platform), [Migration](site:explanations/cloud-platform/gcp-cloud-run-app-module) |
+| [Cloud SQL](https://cloud.google.com/sql)                       | Fully managed relational database service                | [Backups](site:reference/cloud-platform/backups)                                                              |
 | [Cloud Storage](https://cloud.google.com/storage)               | Object storage service                                   | [Reference](site:reference/cloud-platform)                                                              |
-| [Cloud Load Balancing](https://cloud.google.com/load-balancing) | Scalable load distribution service                       | [Architecture](site:standards/standard-architecture-diagrams.md)                                  |
-| [Cloud DNS](https://cloud.google.com/dns)                       | Managed DNS service                                      | [DNS Guide](site:reference/cloud-platform/dns.md)                                                                |
-| [Secret Manager](https://cloud.google.com/secret-manager)       | Secure secret storage service                            | [CI Access](site:howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation.md)                     |
+| [Cloud Load Balancing](https://cloud.google.com/load-balancing) | Scalable load distribution service                       | [Architecture](site:standards/standard-architecture-diagrams)                                  |
+| [Cloud DNS](https://cloud.google.com/dns)                       | Managed DNS service                                      | [DNS Guide](site:reference/cloud-platform/dns)                                                                |
+| [Secret Manager](https://cloud.google.com/secret-manager)       | Secure secret storage service                            | [CI Access](site:howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation)                     |
 | [Cloud Monitoring](https://cloud.google.com/monitoring)         | Infrastructure and application monitoring service        | [Reference](site:reference/cloud-platform)                                                              |
 | [Cloud Logging](https://cloud.google.com/logging)               | Centralized log management service                       | [Reference](site:reference/cloud-platform)                                                              |
-| [gcloud CLI](https://cloud.google.com/sdk/gcloud)               | Command-line interface for GCP services                  | [System Setup](site:howtos/development/prepare-your-system.md)                                                               |
+| [gcloud CLI](https://cloud.google.com/sdk/gcloud)               | Command-line interface for GCP services                  | [System Setup](site:howtos/development/prepare-your-system)                                                               |
 <!-- markdownlint-enable MD013 -->
 
 ## Terraform & Infrastructure Tools
@@ -25,7 +25,7 @@ Our adopted & recommended tools & services for Google Cloud Platform (GCP) and T
 |------------------------------------------------------------------------------------------------|----------------------------------------------|--------------------------------------------------------------|
 | [Terraform](https://www.terraform.io/)                                                         | Infrastructure as Code tool                  | [Reference](site:reference/cloud-platform)         |
 | [terraform-provider-google](https://registry.terraform.io/providers/hashicorp/google/latest)   | Google Cloud Platform provider for Terraform | [Reference](site:reference/cloud-platform)         |
-| [terraform-provider-aws](https://registry.terraform.io/providers/hashicorp/aws/latest)         | Amazon Web Services provider for Terraform   | [AWS Guide](site:explanations/cloud-platform/aws.md)                       |
-| [terraform-provider-azurerm](https://registry.terraform.io/providers/hashicorp/azurerm/latest) | Microsoft Azure provider for Terraform       | [Azure Guide](site:explanations/cloud-platform/azure-and-entra-id-apps.md) |
+| [terraform-provider-aws](https://registry.terraform.io/providers/hashicorp/aws/latest)         | Amazon Web Services provider for Terraform   | [AWS Guide](site:explanations/cloud-platform/aws)                       |
+| [terraform-provider-azurerm](https://registry.terraform.io/providers/hashicorp/azurerm/latest) | Microsoft Azure provider for Terraform       | [Azure Guide](site:explanations/cloud-platform/azure-and-entra-id-apps) |
 | [tflint](https://github.com/terraform-linters/tflint)                                          | Terraform linter                             | [Reference](site:reference/cloud-platform)         |
 <!-- markdownlint-enable MD013 -->
diff --git a/docs/libraries-tools/git-ci-docker.md b/docs/libraries-tools/git-ci-docker.md
index f5366205..2e038a34 100644
--- a/docs/libraries-tools/git-ci-docker.md
+++ b/docs/libraries-tools/git-ci-docker.md
@@ -5,10 +5,10 @@ Our adopted & recommended development tools & services.
 <!-- markdownlint-disable MD013 -->
 | Title                                                         | Summary                                        | Our Docs                                                 |
 |---------------------------------------------------------------|------------------------------------------------|----------------------------------------------------------|
-| [Docker](https://www.docker.com/)                             | Container platform                             | [System Setup](site:howtos/development/prepare-your-system.md)      |
-| [GitLab CI/CD](https://docs.gitlab.com/ee/ci/)                | Continuous Integration and Deployment platform | [Tutorial](site:tutorials/creating-a-python-package.md) |
+| [Docker](https://www.docker.com/)                             | Container platform                             | [System Setup](site:howtos/development/prepare-your-system)      |
+| [GitLab CI/CD](https://docs.gitlab.com/ee/ci/)                | Continuous Integration and Deployment platform | [Tutorial](site:tutorials/creating-a-python-package) |
 | [GitLab CI Local](https://github.com/firecow/gitlab-ci-local) | Local debugging of GitLab pipelines.           |                                                          |
-| [GitLab Runner](https://docs.gitlab.com/runner/)              | CI/CD job execution agent                      | [GKE Guide](site:explanations/cloud-platform/gke-gitlab-runners.md)    |
+| [GitLab Runner](https://docs.gitlab.com/runner/)              | CI/CD job execution agent                      | [GKE Guide](site:explanations/cloud-platform/gke-gitlab-runners)    |
 | [renovatebot](https://www.mend.io/renovate/)                  | Automated dependency updates                   | [Guide](site:explanations/renovatebot)               |
-| [pre-commit](https://pre-commit.com/)                         | Git hook framework                             | [Setup](site:howtos/development/setup-pre-commit-hooks.md)          |
+| [pre-commit](https://pre-commit.com/)                         | Git hook framework                             | [Setup](site:howtos/development/setup-pre-commit-hooks)          |
 <!-- markdownlint-enable MD013 -->
diff --git a/docs/libraries-tools/python.md b/docs/libraries-tools/python.md
index f75dd80d..168ca5ba 100644
--- a/docs/libraries-tools/python.md
+++ b/docs/libraries-tools/python.md
@@ -7,26 +7,26 @@ Our adopted & recommended Python libraries, snippets & tools.
 <!-- markdownlint-disable MD013 -->
 | Title                                                                           | Summary                                                 | Our Docs                                                                                                                  |
 |---------------------------------------------------------------------------------|---------------------------------------------------------|---------------------------------------------------------------------------------------------------------------------------|
-| [black](https://github.com/psf/black)                                           | Code formatter that enforces a consistent style         | [Setup](site:howtos/development/setup-pre-commit-hooks.md), [Tutorial](site:tutorials/creating-a-python-package.md)                 |
-| [coverage](https://coverage.readthedocs.io/)                                    | Tool for measuring code coverage of Python programs     | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [docopt](http://docopt.org/)                                                    | Command-line interface description language and parser  | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [faker](https://faker.readthedocs.io/)                                          | Library for generating fake data for testing            | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [flake8](https://flake8.pycqa.org/)                                             | Tool for style guide enforcement and linting            | [Setup](site:howtos/development/setup-pre-commit-hooks.md), [Tutorial](site:tutorials/creating-a-python-package.md)                 |
-| [furo](https://pradyunsg.me/furo/)                                              | Clean customizable Sphinx documentation theme           | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [geddit](https://gitlab.developers.cam.ac.uk/uis/devops/lib/geddit)             | UIS library for fetching data from URLs                 | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [isort](https://pycqa.github.io/isort/)                                         | Library for sorting Python imports                      | [Setup](site:howtos/development/setup-pre-commit-hooks.md), [Tutorial](site:tutorials/creating-a-python-package.md)                 |
-| [jsonpath-ng](https://github.com/h2non/jsonpath-ng)                             | Library for extracting data using JSONPath expressions  | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [mypy](https://mypy.readthedocs.io/)                                            | Static type checker for Python                          | [Setup](site:howtos/development/setup-pre-commit-hooks.md), [Tutorial](site:tutorials/creating-a-python-package.md)                 |
-| [pre-commit](https://pre-commit.com/)                                           | Framework for managing git pre-commit hooks             | [Setup](site:howtos/development/setup-pre-commit-hooks.md), [Tutorial](site:tutorials/creating-a-python-package.md)                 |
-| [PyYAML](https://pyyaml.org/)                                                   | YAML parser and emitter for Python                      | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [pytest](https://docs.pytest.org/)                                              | Testing framework                                       | [Tutorial](site:tutorials/creating-a-python-package.md), [Boilerplate](site:explanations/development/webapp-boilerplate.md#testing) |
-| [pytest-cov](https://pytest-cov.readthedocs.io/)                                | Coverage plugin for pytest                              | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [pytest-mock](https://pytest-mock.readthedocs.io/)                              | Thin-wrapper around mock package for pytest             | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [python-social-auth](https://python-social-auth.readthedocs.io/)                | Authentication framework for Python web frameworks      | [SSO Guide](site:howtos/entra-azure/configure-django-for-sso.md)                                                                     |
-| [sphinx](https://www.sphinx-doc.org/)                                           | Documentation generator                                 | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) | Type hints support for Sphinx                           | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [structlog](https://www.structlog.org/)                                         | Structured logging for Python                           | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
-| [tox](https://tox.wiki/)                                                        | Test automation and virtual environment management tool | [Tutorial](site:tutorials/creating-a-python-package.md)                                                                  |
+| [black](https://github.com/psf/black)                                           | Code formatter that enforces a consistent style         | [Setup](site:howtos/development/setup-pre-commit-hooks), [Tutorial](site:tutorials/creating-a-python-package)                 |
+| [coverage](https://coverage.readthedocs.io/)                                    | Tool for measuring code coverage of Python programs     | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [docopt](http://docopt.org/)                                                    | Command-line interface description language and parser  | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [faker](https://faker.readthedocs.io/)                                          | Library for generating fake data for testing            | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [flake8](https://flake8.pycqa.org/)                                             | Tool for style guide enforcement and linting            | [Setup](site:howtos/development/setup-pre-commit-hooks), [Tutorial](site:tutorials/creating-a-python-package)                 |
+| [furo](https://pradyunsg.me/furo/)                                              | Clean customizable Sphinx documentation theme           | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [geddit](https://gitlab.developers.cam.ac.uk/uis/devops/lib/geddit)             | UIS library for fetching data from URLs                 | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [isort](https://pycqa.github.io/isort/)                                         | Library for sorting Python imports                      | [Setup](site:howtos/development/setup-pre-commit-hooks), [Tutorial](site:tutorials/creating-a-python-package)                 |
+| [jsonpath-ng](https://github.com/h2non/jsonpath-ng)                             | Library for extracting data using JSONPath expressions  | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [mypy](https://mypy.readthedocs.io/)                                            | Static type checker for Python                          | [Setup](site:howtos/development/setup-pre-commit-hooks), [Tutorial](site:tutorials/creating-a-python-package)                 |
+| [pre-commit](https://pre-commit.com/)                                           | Framework for managing git pre-commit hooks             | [Setup](site:howtos/development/setup-pre-commit-hooks), [Tutorial](site:tutorials/creating-a-python-package)                 |
+| [PyYAML](https://pyyaml.org/)                                                   | YAML parser and emitter for Python                      | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [pytest](https://docs.pytest.org/)                                              | Testing framework                                       | [Tutorial](site:tutorials/creating-a-python-package), [Boilerplate](site:explanations/development/webapp-boilerplate#testing) |
+| [pytest-cov](https://pytest-cov.readthedocs.io/)                                | Coverage plugin for pytest                              | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [pytest-mock](https://pytest-mock.readthedocs.io/)                              | Thin-wrapper around mock package for pytest             | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [python-social-auth](https://python-social-auth.readthedocs.io/)                | Authentication framework for Python web frameworks      | [SSO Guide](site:howtos/entra-azure/configure-django-for-sso)                                                                     |
+| [sphinx](https://www.sphinx-doc.org/)                                           | Documentation generator                                 | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [sphinx-autodoc-typehints](https://github.com/tox-dev/sphinx-autodoc-typehints) | Type hints support for Sphinx                           | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [structlog](https://www.structlog.org/)                                         | Structured logging for Python                           | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
+| [tox](https://tox.wiki/)                                                        | Test automation and virtual environment management tool | [Tutorial](site:tutorials/creating-a-python-package)                                                                  |
 <!-- markdownlint-enable MD013 -->
 
 ## Snippets
@@ -45,9 +45,9 @@ Our adopted & recommended Python libraries, snippets & tools.
 <!-- markdownlint-disable MD013 -->
 | Title                                    | Summary                                                              | Our Docs                                                                                                                    |
 |------------------------------------------|----------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
-| [copier](https://copier.readthedocs.io/) | Tool for rendering project templates                                 | [Create](site:howtos/development/copier/create.md), [Update](site:howtos/development/copier/update.md), [Migrate](site:howtos/development/copier/migrate.md) |
-| [pip](https://pip.pypa.io/)              | Package installer for Python                                         | [System Setup](site:howtos/development/prepare-your-system.md)                                                                         |
-| [pipx](https://pypa.github.io/pipx/)     | Tool to install and run Python applications in isolated environments | [System Setup](site:howtos/development/prepare-your-system.md)                                                                         |
-| [poetry](https://python-poetry.org/)     | Python dependency management and packaging tool                      | [Tutorial](site:tutorials/creating-a-python-package.md), [Boilerplate](site:explanations/development/webapp-boilerplate.md#poetry)    |
-| [poe](https://poethepoet.natn.io/)       | Task runner that works well with poetry                              | [Tutorial](site:tutorials/creating-a-python-package.md), [Boilerplate](site:explanations/development/webapp-boilerplate.md#poe)       |
+| [copier](https://copier.readthedocs.io/) | Tool for rendering project templates                                 | [Create](site:howtos/development/copier/create), [Update](site:howtos/development/copier/update), [Migrate](site:howtos/development/copier/migrate) |
+| [pip](https://pip.pypa.io/)              | Package installer for Python                                         | [System Setup](site:howtos/development/prepare-your-system)                                                                         |
+| [pipx](https://pypa.github.io/pipx/)     | Tool to install and run Python applications in isolated environments | [System Setup](site:howtos/development/prepare-your-system)                                                                         |
+| [poetry](https://python-poetry.org/)     | Python dependency management and packaging tool                      | [Tutorial](site:tutorials/creating-a-python-package), [Boilerplate](site:explanations/development/webapp-boilerplate#poetry)    |
+| [poe](https://poethepoet.natn.io/)       | Task runner that works well with poetry                              | [Tutorial](site:tutorials/creating-a-python-package), [Boilerplate](site:explanations/development/webapp-boilerplate#poe)       |
 <!-- markdownlint-enable MD013 -->
diff --git a/docs/reference/best-practice/ourtools.md b/docs/reference/best-practice/ourtools.md
index a7899680..cc13ecb7 100644
--- a/docs/reference/best-practice/ourtools.md
+++ b/docs/reference/best-practice/ourtools.md
@@ -23,7 +23,7 @@ We host many of our databases in Google's Cloud SQL product. We have written a
 scan all of our Google Cloud Projects and back any Cloud SQL databases found to
 a Google Cloud Storage bucket in a central backup project.
 
-See [the tool's service page](site:services/data-backup.md) page for more information.
+See [the tool's service page](site:services/data-backup) page for more information.
 
 ## Mailtrap
 
@@ -45,7 +45,7 @@ or [their API documentation](https://api-docs.mailtrap.io/docs/mailtrap-api-docs
 !!! warning
     This service is being decommissioned. Please use [Mailtrap](#mailtrap).
     Mailhog may still be used as part of a docker compose environment.
-    More information on this is available in the [tour of our development environment](site:notes/webapp-dev-environment.md#a-tour-of-our-setup).
+    More information on this is available in the [tour of our development environment](site:notes/webapp-dev-environment#a-tour-of-our-setup).
 
 For testing applications which deliver email, we have a
 [Mailhog](https://github.com/mailhog/MailHog) instance
diff --git a/docs/reference/best-practice/python.md b/docs/reference/best-practice/python.md
index c51688f7..31310501 100644
--- a/docs/reference/best-practice/python.md
+++ b/docs/reference/best-practice/python.md
@@ -5,13 +5,13 @@ for backend work.
 
 ## Code style
 
-We have a number of [templates](site:reference/deployment/templates.md) which configures
+We have a number of [templates](site:reference/deployment/templates) which configures
 automated code style checks using [flake8](https://flake8.pycqa.org/en/latest/) and
 [black](https://black.readthedocs.io/en/stable/). The checks are enforced locally
 via pre-commit hooks and in CI via a pre-commit job.
 
 A step-by-step explanation of how to configure the checks added by our standard templates can be
 found in the [the Python package
-tutorial](site:tutorials/creating-a-python-package.md#catching-and-fixing-style-issues). A deeper
+tutorial](site:tutorials/creating-a-python-package#catching-and-fixing-style-issues). A deeper
 explanation of other concepts like Tests, Logging, Packaging, etc, can also be found on the [same
-page](site:tutorials/creating-a-python-package.md).
+page](site:tutorials/creating-a-python-package).
diff --git a/docs/reference/cloud-platform/dns.md b/docs/reference/cloud-platform/dns.md
index 7aee74bf..fa940a42 100644
--- a/docs/reference/cloud-platform/dns.md
+++ b/docs/reference/cloud-platform/dns.md
@@ -149,10 +149,10 @@ Google Chat.
 
 ## Example - Lab Allocator
 
-The [Lab Allocator](site:services/lab-allocator.md) product required a custom domain. A tutorial
+The [Lab Allocator](site:services/lab-allocator) product required a custom domain. A tutorial
 walkthrough of the process is available:
 
-* [Tutorial: Custom DNS for Cloud Platform Service](site:tutorials/gcp-custom-dns.md)
+* [Tutorial: Custom DNS for Cloud Platform Service](site:tutorials/gcp-custom-dns)
 
 ## Summary
 
diff --git a/docs/reference/cloud-platform/gke-gitlab-runners.md b/docs/reference/cloud-platform/gke-gitlab-runners.md
index 719b7f96..dd4d4abc 100644
--- a/docs/reference/cloud-platform/gke-gitlab-runners.md
+++ b/docs/reference/cloud-platform/gke-gitlab-runners.md
@@ -74,7 +74,7 @@ configuration:
 ### Per-product configuration
 
 Each product has the following resources created by the Terraform configuration (see the
-[how-to](site:howtos/gke-gitlab-runners/register-a-gke-gitlab-runner.md) for steps on adding a
+[how-to](site:howtos/gke-gitlab-runners/register-a-gke-gitlab-runner) for steps on adding a
 product to the Terraform deployment).
 
 - A unique Kubernetes namespace for the product's runners.
@@ -109,8 +109,8 @@ to respond to support requests or incidents:
 ## See also
 
 - [How to register GKE-hosted GitLab
-  runners](site:howtos/gke-gitlab-runners/register-a-gke-gitlab-runner.md)
+  runners](site:howtos/gke-gitlab-runners/register-a-gke-gitlab-runner)
 - [How to run CI/CD jobs on a GKE-hosted GitLab
-  runner](site:howtos/gke-gitlab-runners/run-ci-jobs-on-a-gke-gitlab-runner.md)
+  runner](site:howtos/gke-gitlab-runners/run-ci-jobs-on-a-gke-gitlab-runner)
 - [How to access a Google Secret Manager secret using service account
-  impersonation](site:howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation.md)
+  impersonation](site:howtos/gke-gitlab-runners/access-secrets-in-ci-jobs-using-impersonation)
diff --git a/docs/reference/cloud-platform/index.md b/docs/reference/cloud-platform/index.md
index 3cc950fc..e82d483d 100644
--- a/docs/reference/cloud-platform/index.md
+++ b/docs/reference/cloud-platform/index.md
@@ -81,6 +81,6 @@ For more information on the configuration of these runners see [here](./gke-gitl
 ## Further information
 
 The rest of the pages in this section go into more detail on the specifics of our cloud platform
-environment. However, the [how-to](site:howtos/index.md) and [tutorial](site:tutorials)
+environment. However, the [how-to](site:howtos/index) and [tutorial](site:tutorials)
 sections are often a better place to start as they contain short, focussed, articles that are more
 relevant to day-to-day tasks.
diff --git a/docs/reference/deployment/index.md b/docs/reference/deployment/index.md
index 7b8d914e..96601bb2 100644
--- a/docs/reference/deployment/index.md
+++ b/docs/reference/deployment/index.md
@@ -41,9 +41,9 @@ config](https://gitlab.developers.cam.ac.uk/uis/devops/gcp-deploy-boilerplate).
    [webapp-boilerplate](https://gitlab.developers.cam.ac.uk/uis/devops/webapp-boilerplate)
    copier template and push the `main` branch to a new Gitlab project.
     * Additional information on the Webapp Developer Environment can be found
-      [here](site:notes/webapp-dev-environment.md).
+      [here](site:notes/webapp-dev-environment).
     * Pushing the `main` branch to Gitlab will ensure that the default
-      [AutoDevops](site:reference/workflow/pipelines.md) CI/CD pipeline runs
+      [AutoDevops](site:reference/workflow/pipelines) CI/CD pipeline runs
       which builds the container image and stores it in the Gitlab container registry.
       This is required by the gcp-deploy-boilerplate.
 
@@ -52,7 +52,7 @@ config](https://gitlab.developers.cam.ac.uk/uis/devops/gcp-deploy-boilerplate).
    copier template.
     * This template generates the Terraform config required to deploy the webapp and related
     * infrastructure to Google Cloud.
-    * Additional information on our Terraform deployments can be found [here](site:reference/deployment/terraform.md).
+    * Additional information on our Terraform deployments can be found [here](site:reference/deployment/terraform).
 
 ## The 10,000 foot view
 
diff --git a/docs/reference/deployment/secrets.md b/docs/reference/deployment/secrets.md
index 75b523ae..5cefcd0d 100644
--- a/docs/reference/deployment/secrets.md
+++ b/docs/reference/deployment/secrets.md
@@ -69,7 +69,7 @@ it clear which types of secret a particular technology is best at dealing with.
 
 We make use of a team 1Password instance which can be found at
 [https://uis-devops.1Password.eu/](https://uis-devops.1Password.eu/). As part of
-the [onboarding process](site:reference/workflow/onboarding.md), all team members should have a
+the [onboarding process](site:reference/workflow/onboarding), all team members should have a
 1Password account.
 
 !!! important
@@ -180,7 +180,7 @@ Google's [Secret Manager](https://cloud.google.com/secret-manager) is our
 default choice for where secrets will need to be accessed at runtime by
 applications. This is the case for most database and API credentials.
 
-For example, with [serverless web applications](site:reference/deployment/web-applications.md) we
+For example, with [serverless web applications](site:reference/deployment/web-applications) we
 store Django settings in a Secret Manager secret as a YAML-formatted document.
 This document is read at runtime by the web application.
 
@@ -250,8 +250,8 @@ To avoid sensitive values appearing in the environment, we have re-architected
 our applications to load some configuration at runtime from secrets.
 
 More information can be found in pages detailing
-[serverless](site:reference/deployment/web-applications.md) and
-[kubernetes](site:reference/deployment/k8s-clusters.md) web application deployment.
+[serverless](site:reference/deployment/web-applications) and
+[kubernetes](site:reference/deployment/k8s-clusters) web application deployment.
 
 ## Summary
 
diff --git a/docs/reference/deployment/sql-instances.md b/docs/reference/deployment/sql-instances.md
index 1d6840df..39363912 100644
--- a/docs/reference/deployment/sql-instances.md
+++ b/docs/reference/deployment/sql-instances.md
@@ -83,7 +83,7 @@ maintenance window to start at 2AM on Sunday mornings.
 
 ## "Off-site" backups
 
-We have [a custom tool](site:services/data-backup.md) which
+We have [a custom tool](site:services/data-backup) which
 runs nightly to backup our production databases to a Google Cloud Storage
 bucket. This bucket is hosted in a Google project dedicated to this purpose. As
 such we have a degree of resilience against deleting the SQL instance or the
@@ -108,7 +108,7 @@ independently from service account users. We use the term _database user_ to
 mean a user created in PostgreSQL and _service account_ to mean an identity
 which is created within Cloud IAM.
 
-Usually our [web applications](site:reference/deployment/web-applications.md) are deployed
+Usually our [web applications](site:reference/deployment/web-applications) are deployed
 with a dedicated service account for that application. In order for the web
 application to be able to use the database a separate database user must be
 created for it.
@@ -158,7 +158,7 @@ account must have the [`cloudsql.client`
 role](https://cloud.google.com/sql/docs/postgres/roles-and-permissions).
 
 This role is often granted to the service account representing the [web
-application](site:reference/deployment/web-applications.md).
+application](site:reference/deployment/web-applications).
 
 !!! important
 
@@ -174,7 +174,7 @@ application](site:reference/deployment/web-applications.md).
 ### Cloud Run
 
 Cloud Run is used for [deploying web
-applications](site:reference/deployment/web-applications.md). It has native support for
+applications](site:reference/deployment/web-applications). It has native support for
 connecting to Cloud SQL instances and causes the Cloud SQL instance to [appear
 as a UNIX socket within the
 container](https://cloud.google.com/sql/docs/postgres/connect-run).
@@ -186,7 +186,7 @@ is easy to create a [sidecar
 container](https://docs.microsoft.com/en-us/azure/architecture/patterns/sidecar)
 which runs the proxy making the instance available within the cluster. More
 information is available on the [kubernetes deployment
-page](site:reference/deployment/k8s-clusters.md).
+page](site:reference/deployment/k8s-clusters).
 
 ## Summary
 
diff --git a/docs/reference/deployment/templates.md b/docs/reference/deployment/templates.md
index d74259c1..c3aee3b6 100644
--- a/docs/reference/deployment/templates.md
+++ b/docs/reference/deployment/templates.md
@@ -37,6 +37,6 @@ In the UIS DevOps Division we use Copier for two boilerplate projects:
 More information on how to use Copier to perform specific tasks can be found in the following
 how-to guides:
 
-- [Creating a new project from Copier template](site:howtos/development/copier/create.md)
-- [Updating a project created with Copier to the newer version](site:howtos/development/copier/update.md)
-- [Migrating a project created with Cookiecutter to Copier](site:howtos/development/copier/migrate.md)
+- [Creating a new project from Copier template](site:howtos/development/copier/create)
+- [Updating a project created with Copier to the newer version](site:howtos/development/copier/update)
+- [Migrating a project created with Cookiecutter to Copier](site:howtos/development/copier/migrate)
diff --git a/docs/reference/deployment/terraform.md b/docs/reference/deployment/terraform.md
index 585622d2..ff406ad6 100644
--- a/docs/reference/deployment/terraform.md
+++ b/docs/reference/deployment/terraform.md
@@ -4,7 +4,7 @@ This page discusses how we use terraform to configure our deployments.
 
 Our standard terraform configurations assume that we have a *product folder*, *meta project*,
 multiple *environment projects*, and a *product configuration* Cloud Storage bucket created for us.
-See the [Google Cloud projects and folders page](site:reference/cloud-platform/gcp-folders.md) for
+See the [Google Cloud projects and folders page](site:reference/cloud-platform/gcp-folders) for
 information on these.
 
 A live example of a service configured using terraform is the [API Gateway
diff --git a/docs/reference/deployment/traffic-ingress.md b/docs/reference/deployment/traffic-ingress.md
index 5a2cc043..142c5044 100644
--- a/docs/reference/deployment/traffic-ingress.md
+++ b/docs/reference/deployment/traffic-ingress.md
@@ -39,7 +39,7 @@ instances.
 
 The Cloud Run domain mapping ingress is simple to configure:
 
-1. Verify [a DNS domain](site:reference/cloud-platform/dns.md) for the application.
+1. Verify [a DNS domain](site:reference/cloud-platform/dns) for the application.
 2. Specify the DNS domain via our standard module's `dns_names` variable.
 3. Add DNS records for that domain according to the `dns_resource_records`
    output from our standard module.
diff --git a/docs/reference/deployment/web-applications.md b/docs/reference/deployment/web-applications.md
index a76c69d1..6f16c2c5 100644
--- a/docs/reference/deployment/web-applications.md
+++ b/docs/reference/deployment/web-applications.md
@@ -90,15 +90,15 @@ This service account is granted the following permissions:
 * reading the non-sensitive settings storage object.
 
 DNS records are created for the application within the [project's DNS
-zone](site:reference/cloud-platform/dns.md). TLS certificates are provisioned automatically but
+zone](site:reference/cloud-platform/dns). TLS certificates are provisioned automatically but
 the domain must first have been
-[verified](site:reference/cloud-platform/dns.md#domain-verification).
+[verified](site:reference/cloud-platform/dns#domain-verification).
 
 TLS certificates will also be provisioned for any domain specified in
 `local.webapp_custom_dns_name` but records will *not* be created. Usually this
 local is used to host the "friendly" `.cam.ac.uk` domain for the service and
 records under `.cam.ac.uk` must be created by [other
-means](site:reference/cloud-platform/dns.md#domains-under-camacuk). Similarly the *project admin*
+means](site:reference/cloud-platform/dns#domains-under-camacuk). Similarly the *project admin*
 terraform service account must be verified as an owner of the domain with
 Google.
 
@@ -139,7 +139,7 @@ application startup delays.
 
 ### Application configuration
 
-To avoid [secrets](site:reference/deployment/secrets.md) appearing in the environment, we have
+To avoid [secrets](site:reference/deployment/secrets) appearing in the environment, we have
 re-architected our applications to load some configuration at runtime. For our
 Django projects, we make use of the
 [externalsettings](https://gitlab.developers.cam.ac.uk/uis/devops/django/externalsettings)
diff --git a/docs/reference/misc/identifiers.md b/docs/reference/misc/identifiers.md
index 7e602c49..f702ab0a 100644
--- a/docs/reference/misc/identifiers.md
+++ b/docs/reference/misc/identifiers.md
@@ -9,7 +9,7 @@ scopes may be used. Those which have been approved by the UIS Technical Design A
 interoperability with systems outside of DevOps are so indicated.
 
 There is a separate page providing an [explanation of how we use identifiers in
-DevOps](site:explanations/misc/identifiers.md).
+DevOps](site:explanations/misc/identifiers).
 
 This table is generate automatically from our [identity
 library](https://gitlab.developers.cam.ac.uk/uis/devops/iam/identity-lib).
diff --git a/docs/reference/misc/openapi-client-generation.md b/docs/reference/misc/openapi-client-generation.md
index 451ecff8..059349b4 100644
--- a/docs/reference/misc/openapi-client-generation.md
+++ b/docs/reference/misc/openapi-client-generation.md
@@ -5,7 +5,7 @@ title: API client generation from OpenAPI specifications
 
 This page provides more in-depth reference on customising the OpenAPI-based client generation
 described in the [how to automatically generate API clients
-guide](site:howtos/development/generate-api-clients.md).
+guide](site:howtos/development/generate-api-clients).
 
 ## Customising the generated clients
 
diff --git a/docs/reference/misc/tech-lead-forum.md b/docs/reference/misc/tech-lead-forum.md
index 61e43cd3..e160e1ed 100644
--- a/docs/reference/misc/tech-lead-forum.md
+++ b/docs/reference/misc/tech-lead-forum.md
@@ -6,7 +6,7 @@ title: The Tech Lead Forum
 
 This page lists the purpose, the composition and the processes for the Tech Lead Forum. An
 explanation of why the Tech Lead Forum exists and how it helps us is available on [a separate
-page](site:standards/tech-lead-forum.md).
+page](site:standards/tech-lead-forum).
 
 ## Purpose
 
diff --git a/docs/reference/misc/webapp-developer-environment.md b/docs/reference/misc/webapp-developer-environment.md
index ebb6d2ac..6554e516 100644
--- a/docs/reference/misc/webapp-developer-environment.md
+++ b/docs/reference/misc/webapp-developer-environment.md
@@ -8,11 +8,11 @@ title: Local app development
 
     This document describes our "new-style" developer environment. If your project has a
     `compose.sh` file present in the root, look at the [original
-    documentation](site:notes/webapp-dev-environment.md).
+    documentation](site:notes/webapp-dev-environment).
 
 This page lists common tasks which a developer may want to perform when working with our standard
 webapp developer environment. Read more about the philosophy behind the design of this environment
-in our [explainer guide](site:explanations/development/webapp-boilerplate.md).
+in our [explainer guide](site:explanations/development/webapp-boilerplate).
 
 Unless otherwise stated, commands in this guide should be run from the project's root directory.
 
@@ -22,7 +22,7 @@ shortened to `poe ...`.
 ## Bootstrapping
 
 Make sure that you have `docker`, `docker compose`, `poetry` and `poe` installed. Instructions for
-this can be found in the [guide on how-to prepare your system](site:howtos/development/prepare-your-system.md).
+this can be found in the [guide on how-to prepare your system](site:howtos/development/prepare-your-system).
 
 Install application dependencies via:
 
diff --git a/docs/reference/notes/google-domain-verification.md b/docs/reference/notes/google-domain-verification.md
index 0ec9e8ff..c2fa8857 100644
--- a/docs/reference/notes/google-domain-verification.md
+++ b/docs/reference/notes/google-domain-verification.md
@@ -13,4 +13,4 @@ them accessible as "friendly" names under `cam.ac.uk`.
 
 !!! important
     The contents of this note have moved to our [description of deployments to
-    Google Cloud](site:reference/cloud-platform/dns.md).
+    Google Cloud](site:reference/cloud-platform/dns).
diff --git a/docs/reference/notes/ucs-dev-group-services.md b/docs/reference/notes/ucs-dev-group-services.md
index fd471b0e..06a81794 100644
--- a/docs/reference/notes/ucs-dev-group-services.md
+++ b/docs/reference/notes/ucs-dev-group-services.md
@@ -8,12 +8,12 @@ dev group no longer exist, responsibility for running these has been transferred
 
 The services run by DevOps currently includes:
 
-* [Lookup](site:services/lookup.md)
-* [Password Changing Application](site:services/passwords.md)
-* [Human Tissue Tracking Application](site:services/hta.md)
-* [Network Access Tokens Application](site:services/eduroam-tokens.md)
-* [Streaming Media Service](site:services/streaming-media.md)
-* [University Training Booking System](site:services/utbs.md)
+* [Lookup](site:services/lookup)
+* [Password Changing Application](site:services/passwords)
+* [Human Tissue Tracking Application](site:services/hta)
+* [Network Access Tokens Application](site:services/eduroam-tokens)
+* [Streaming Media Service](site:services/streaming-media)
+* [University Training Booking System](site:services/utbs)
 
 ## Deploying changes to UCS development group services
 
@@ -25,12 +25,12 @@ The services run by DevOps currently includes:
 
 | Application | Operating System | HA provider |
 | ----------- | ---------------- | ----------- |
-| [Lookup](site:services/lookup.md) | RedHat 8 | Keepalived |
-| [Password Changing Application](site:services/passwords.md) | Red Hat 8 | Traffic Manager |
-| [Human Tissue Tracking Application](site:services/hta.md) | Red Hat 8 | Traffic Manager |
-| [Network Access Tokens Application](site:services/eduroam-tokens.md) | Red Hat 8| Traffic Manager |
-| [Streaming Media Service](site:services/streaming-media.md) | SLES 11 | Manual |
-| [University Training Booking System](site:services/utbs.md) | Red Hat 8 | Traffic Manager |
+| [Lookup](site:services/lookup) | RedHat 8 | Keepalived |
+| [Password Changing Application](site:services/passwords) | Red Hat 8 | Traffic Manager |
+| [Human Tissue Tracking Application](site:services/hta) | Red Hat 8 | Traffic Manager |
+| [Network Access Tokens Application](site:services/eduroam-tokens) | Red Hat 8| Traffic Manager |
+| [Streaming Media Service](site:services/streaming-media) | SLES 11 | Manual |
+| [University Training Booking System](site:services/utbs) | Red Hat 8 | Traffic Manager |
 
 ## RedHat Deployments
 
diff --git a/docs/reference/notes/webapp-dev-environment.md b/docs/reference/notes/webapp-dev-environment.md
index 6a2c5bf0..130b89cd 100644
--- a/docs/reference/notes/webapp-dev-environment.md
+++ b/docs/reference/notes/webapp-dev-environment.md
@@ -4,7 +4,7 @@
 
     This document describes an older variant of our standard webapp developer environment. If your
     project does **not** include a `compose.sh` in the root, read our [newer
-    guide](site:reference/misc/webapp-developer-environment.md).
+    guide](site:reference/misc/webapp-developer-environment).
 
 The majority of our web applications make use of the same method to automate the
 developer experience. Our aim is to get developers up an running in the shortest
diff --git a/docs/reference/workflow/flows.md b/docs/reference/workflow/flows.md
index 3e52205c..464422f2 100644
--- a/docs/reference/workflow/flows.md
+++ b/docs/reference/workflow/flows.md
@@ -163,7 +163,7 @@ add an iteration to the issue using either the menu or the `/iteration` quick ac
 ### Creating an issue for the Cloud Team
 
 Issues should be created using the [Issue lifecyle](gitlab.md#the-issue-lifecycle). In summary,
-issues should be [tagged](site:reference/git-gitlab/gitlab-labels.md#labels-in-gitlab)
+issues should be [tagged](site:reference/git-gitlab/gitlab-labels#labels-in-gitlab)
 with `workflow: Need Refinement` and `team: Cloud`. Do not add an iteration at this point. During our
 refinement session, we will use [our refinement queue](https://gitlab.developers.cam.ac.uk/groups/uis/devops/-/issues/?sort=updated_desc&state=opened&label_name%5B%5D=team%3A%3ACloud&label_name%5B%5D=workflow%3A%3ANeeds%20Refinement&iteration_id=None&first_page_size=100)
 to see these ticket, refine, and move to `sprint ready`.
diff --git a/docs/reference/workflow/gitlab.md b/docs/reference/workflow/gitlab.md
index 05631d65..460fa4a5 100644
--- a/docs/reference/workflow/gitlab.md
+++ b/docs/reference/workflow/gitlab.md
@@ -166,7 +166,7 @@ the issue is refined.
 ### Needs sizing
 
 There is a weekly opportunity for team members to help sizing issues. The process for sizing issues
-is described in a dedicated [how-to guide](site:howtos/git-gitlab/size-issues.md).
+is described in a dedicated [how-to guide](site:howtos/git-gitlab/size-issues).
 
 Once sized and refined, an issue gets the "workflow::sprint ready" label.
 
@@ -203,7 +203,7 @@ the assignee.
 ### Review required and Needs deployment
 
 !!! info
-    This section has moved to [a dedicated page](site:explanations/git-gitlab/reviewing-issues.md).
+    This section has moved to [a dedicated page](site:explanations/git-gitlab/reviewing-issues).
 
 ### Rework
 
@@ -229,7 +229,7 @@ intention to complete, the "resolution::DevNotPlanned" label can also be applied
 ## Labels
 
 !!! note
-    This section has moved to a [separate page](site:reference/git-gitlab/gitlab-labels.md).
+    This section has moved to a [separate page](site:reference/git-gitlab/gitlab-labels).
 
 ## Groups and projects
 
diff --git a/docs/reference/workflow/pypi.md b/docs/reference/workflow/pypi.md
index 486dd0a0..1320c261 100644
--- a/docs/reference/workflow/pypi.md
+++ b/docs/reference/workflow/pypi.md
@@ -19,10 +19,10 @@ Task-focussed and reference documentation for creating and publishing Python
 packages can be found in the following places:
 
 * [How to add the common pipeline to a Python
-  project](site:howtos/python/add-common-pipeline-to-python.md)
+  project](site:howtos/python/add-common-pipeline-to-python)
 * [How to make a new release of a Python
-  package](site:howtos/python/publish-a-python-package.md)
-* [How to create PyPI API tokens](site:howtos/python/pypi.md)
+  package](site:howtos/python/publish-a-python-package)
+* [How to create PyPI API tokens](site:howtos/python/pypi)
 * [Reference
   documentation](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-templates/-/blob/master/auto-devops/python.md)
   for the Python-specific portions of the common CI/CD pipeline
@@ -67,7 +67,7 @@ project we're releasing but we can't *select* that scope until we've published
 the project.
 
 We have to do a bit of token gymnastics to get around this issue. As documented
-in the [how-to guide](site:howtos/python/pypi.md), we firstly create a temporary token
+in the [how-to guide](site:howtos/python/pypi), we firstly create a temporary token
 with the ability to work with *all* projects. This scope is required to create
 *new* projects which will happen implicitly on the first release.
 
@@ -93,4 +93,4 @@ project for the first time. You should include:
 * where to find out more, for example a link to any API documentation.
 
 Include a `LICENSE.txt` file. See [how to add the MIT licence to a
-project](site:howtos/git-gitlab/add-the-mit-licence.md) for more.
+project](site:howtos/git-gitlab/add-the-mit-licence) for more.
diff --git a/docs/services/caias.md b/docs/services/caias.md
index 91f45fb3..96ab9fc4 100644
--- a/docs/services/caias.md
+++ b/docs/services/caias.md
@@ -80,7 +80,7 @@ pipeline](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-
 ### Deploying a new release
 
 Making a new release of the application is done via [release
-automation](site:explanations/git-gitlab/gitlab-release-automation.md).
+automation](site:explanations/git-gitlab/gitlab-release-automation).
 In short: each commit to the web app's main branch builds and pushes a Docker image to GCR.
 An MR can then be raised within the infrastructure repository to deploy a given image by SHA.
 Once merged, the main GitLab pipeline will allow deployment to production via the "play" buttons
diff --git a/docs/services/data-backup.md b/docs/services/data-backup.md
index d6a13cf2..5dad3594 100644
--- a/docs/services/data-backup.md
+++ b/docs/services/data-backup.md
@@ -82,7 +82,7 @@ pipeline](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-
 ### Deploying a new release
 
 Making a new release of the application is done via [release
-automation](site:explanations/git-gitlab/gitlab-release-automation.md).
+automation](site:explanations/git-gitlab/gitlab-release-automation).
 In short: merged commits are collected together into a draft "next release" Merge Request.
 When merged, a new release tag is pushed to the repository
 along with a Docker image being pushed to Google's Artefact registry.
diff --git a/docs/services/integrated-reward-system.md b/docs/services/integrated-reward-system.md
index 8f03fbaa..4e431cc3 100644
--- a/docs/services/integrated-reward-system.md
+++ b/docs/services/integrated-reward-system.md
@@ -100,7 +100,7 @@ pipeline](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-
 ### Deploying a new release
 
 Making a new release of the application is done via [release
-automation](site:explanations/git-gitlab/gitlab-release-automation.md).
+automation](site:explanations/git-gitlab/gitlab-release-automation).
 
 Deployment is done by:
 
diff --git a/docs/services/job-opportunities.md b/docs/services/job-opportunities.md
index 9c94b187..80e9a7ad 100644
--- a/docs/services/job-opportunities.md
+++ b/docs/services/job-opportunities.md
@@ -62,7 +62,7 @@ pipeline](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-
 ### Deploying a new release
 
 Making a new release of the application is done via [release
-automation](site:explanations/git-gitlab/gitlab-release-automation.md).
+automation](site:explanations/git-gitlab/gitlab-release-automation).
 In short: each commit to the web app's main branch builds and pushes a Docker image to GCR.
 An MR can then be raised within the infrastructure repository to deploy a given image by SHA.
 Once merged, the main GitLab pipeline will allow deployment to production via the "play" buttons
diff --git a/docs/services/lookup-gitlab-sync.md b/docs/services/lookup-gitlab-sync.md
index 4d7bb5e0..0ca3b54a 100644
--- a/docs/services/lookup-gitlab-sync.md
+++ b/docs/services/lookup-gitlab-sync.md
@@ -69,7 +69,7 @@ pipeline](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-
 ### Deploying a new release
 
 Making a new release of the application is done via [release
-automation](site:explanations/git-gitlab/gitlab-release-automation.md).
+automation](site:explanations/git-gitlab/gitlab-release-automation).
 In short: merged commits are collected together into a draft "next release" Merge Request.
 When merged, a new release tag is pushed to the repository along with a Docker image
 being pushed to Google's Artefact registry.
diff --git a/docs/services/postbox.md b/docs/services/postbox.md
index 4e5588c5..76a03400 100644
--- a/docs/services/postbox.md
+++ b/docs/services/postbox.md
@@ -68,7 +68,7 @@ pipeline](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-
 ### Deploying a new release
 
 Making a new release of the application is done via [release
-automation](site:explanations/git-gitlab/gitlab-release-automation.md).
+automation](site:explanations/git-gitlab/gitlab-release-automation).
 In short: each commit to the web app's main branch builds and pushes a Docker image to GCR.
 An MR can then be raised within the infrastructure repository to deploy a given image by SHA.
 Once merged, the main GitLab pipeline will allow deployment to production via the "play" buttons
diff --git a/docs/services/regent-house-ballots.md b/docs/services/regent-house-ballots.md
index 717f1902..99bb9f7e 100644
--- a/docs/services/regent-house-ballots.md
+++ b/docs/services/regent-house-ballots.md
@@ -125,7 +125,7 @@ pipeline](https://gitlab.developers.cam.ac.uk/uis/devops/continuous-delivery/ci-
 ### Deploying a new release
 
 Making a new release of the application is done via [release
-automation](site:explanations/git-gitlab/gitlab-release-automation.md).
+automation](site:explanations/git-gitlab/gitlab-release-automation).
 In short: merged commits are collected together into a draft "next release" Merge Request.
 When merged, a new release tag is pushed to the repository along with a Docker image
 being pushed to Google's Artefact registry.
diff --git a/docs/standards/change-management.md b/docs/standards/change-management.md
index 6dc0feb8..32bf39ff 100644
--- a/docs/standards/change-management.md
+++ b/docs/standards/change-management.md
@@ -275,7 +275,7 @@ version of the software deployed to our staging environment will be bit-for-bit
 subsequently deployed to production.
 
 Our release management process has recently been completely
-[automated](site:explanations/git-gitlab/gitlab-release-automation.md). Now, as changes are merged
+[automated](site:explanations/git-gitlab/gitlab-release-automation). Now, as changes are merged
 in GitLab, a “next release” Merge Request is maintained automatically. Once approved and merged,
 this will automatically generate a Changelog, build and test a packaged version of the software and
 upload it to Google Cloud ready for deployment.
@@ -560,13 +560,13 @@ DevOps change management best practices described in this document.
 Those interested in more details of our workflows, processes and use of technology may find the
 following pages from our guidebook useful.
 
-- [DevOps’ approach to release automation](site:explanations/git-gitlab/gitlab-release-automation.md).
-- [The use of GitLab labels for project management](site:reference/git-gitlab/gitlab-labels.md).
+- [DevOps’ approach to release automation](site:explanations/git-gitlab/gitlab-release-automation).
+- [The use of GitLab labels for project management](site:reference/git-gitlab/gitlab-labels).
 - [DevOps’ culture and values](../environment/culture.md).
-- [How we encourage peer review of changes](site:explanations/git-gitlab/reviewing-issues.md).
-- [Day-to-day working in DevOps](site:reference/workflow/flows.md).
-- [The lifecycle of a feature in GitLab](site:reference/workflow/gitlab.md).
-- [Technical process for proposing and integrating changes](site:reference/workflow/merge-requests.md).
-- [The use in DevOps of terraform for deployment automation](site:reference/deployment/terraform.md).
+- [How we encourage peer review of changes](site:explanations/git-gitlab/reviewing-issues).
+- [Day-to-day working in DevOps](site:reference/workflow/flows).
+- [The lifecycle of a feature in GitLab](site:reference/workflow/gitlab).
+- [Technical process for proposing and integrating changes](site:reference/workflow/merge-requests).
+- [The use in DevOps of terraform for deployment automation](site:reference/deployment/terraform).
 - [A tutorial on creating a Python package which demonstrates some of DevOps’ automated quality
   assurance processes](https://gitlab.com/gitlab-org/gitlab/-/issues/31575).
diff --git a/docs/standards/devsecops-cicd.md b/docs/standards/devsecops-cicd.md
index ce852085..b4e95747 100644
--- a/docs/standards/devsecops-cicd.md
+++ b/docs/standards/devsecops-cicd.md
@@ -29,8 +29,8 @@ they exist, for example, by generating templates that are compatible with multip
 
 This document describes CI/CD standards at a high-level. Specifics and implementation details may be
 found elsewhere. For
-example, [our guidebook has a page on how to add CI/CD to a Python project](site:howtos/python/add-common-pipeline-to-python.md)
-and [a page on configuring release automation via CI/CD](site:howtos/git-gitlab/enable-automated-gitlab-releases.md).
+example, [our guidebook has a page on how to add CI/CD to a Python project](site:howtos/python/add-common-pipeline-to-python)
+and [a page on configuring release automation via CI/CD](site:howtos/git-gitlab/enable-automated-gitlab-releases).
 Our existing [web application](https://gitlab.developers.cam.ac.uk/uis/devops/webapp-boilerplate/)
 and [terraform deployment](https://gitlab.developers.cam.ac.uk/uis/devops/gcp-deploy-boilerplate)
 boilerplates already include the standards described below.
@@ -74,7 +74,7 @@ have deployed to an environment can be seen in the “Environments” tab in Git
   ![](./images/devsecops-cicd-7.png)
   <figcaption markdown>
     Figure taken from our
-Guidebook [tutorial on creating a Python package](site:tutorials/creating-a-python-package.md).
+Guidebook [tutorial on creating a Python package](site:tutorials/creating-a-python-package).
   </figcaption>
 </figure>
 
diff --git a/docs/standards/devsecops-dev.md b/docs/standards/devsecops-dev.md
index 30088546..13b81732 100644
--- a/docs/standards/devsecops-dev.md
+++ b/docs/standards/devsecops-dev.md
@@ -72,7 +72,7 @@ each software component. In this case, we tend to use a version identifier assig
 called the commit SHA. For the purposes of this document, the commit SHA is considered to act like a
 version number. The version number of a deployment uniquely identifies both the way that the
 components are deployed and the components themselves. For deployments which use [GitLab’s inbuilt
-automation to deploy](site:explanations/git-gitlab/gitlab-release-automation.md), once
+automation to deploy](site:explanations/git-gitlab/gitlab-release-automation), once
 changes from a MR are merged track which version is deployed to each of the production, staging and
 development environments. This information is available from a dedicated “environments” page in
 GitLab.
@@ -115,7 +115,7 @@ Request (MR) which should contains the following information:
 
 * the changes they wish to make, split into separately reviewable chunks known as *commits*,
 * a description of each commit which [focuses on the *why* rather than the
-  *what* of the change](site:explanations/git-gitlab/git.md#commits), and
+  *what* of the change](site:explanations/git-gitlab/git#commits), and
 * an overall description of the change which may make reference to existing *issues* which describe
   the agreed objectives of the change.
 
@@ -137,7 +137,7 @@ GitLab allows automated tasks to be triggered when changes are merged or propose
 are called *continuous integration (CI) pipelines*. We have a common pipeline configuration which
 runs a number of security-related tasks, most of them inherited from GitLab’s AutoDevOps.
 
-Some processes below require the [common CI pipeline](site:howtos/python/add-common-pipeline-to-python.md)
+Some processes below require the [common CI pipeline](site:howtos/python/add-common-pipeline-to-python)
 be enabled for repositories and to
 follow [Continuous Integration and Continuous Delivery (CI/CD) standards](./devsecops-cicd.md).
 
@@ -212,7 +212,7 @@ and applied, if deemed necessary, periodically.
 Our goal of being able to state with confidence whether a given deployed environment of a service
 contains a given vulnerability requires that we be consistent in how we release, version and package
 our software. UIS DevOps has developed
-a [release automation](site:tutorials/automating-gitlab-releases.md) process which takes away much
+a [release automation](site:tutorials/automating-gitlab-releases) process which takes away much
 of the manual process of versioning new releases. This removes opportunities for human error. All
 services must adopt this practice.
 
@@ -388,7 +388,7 @@ recently we have had no way of enforcing it; GitLab project creation and configu
 process.
 
 We have
-now [automated the provisioning of GitLab projects](site:howtos/products/bootstrap-a-product.md#create-the-gitlab-projects)
+now [automated the provisioning of GitLab projects](site:howtos/products/bootstrap-a-product#create-the-gitlab-projects)
 and have begun importing existing projects into this automation. This allows us to centralise and
 standardise the configuration of GitLab projects. **At a minimum GitLab projects are now created
 with mandatory MR approval and branch protection.** Deviations from this policy are detected and
diff --git a/docs/standards/non-functional-requirements/availability.md b/docs/standards/non-functional-requirements/availability.md
index 4980ffd7..82603774 100644
--- a/docs/standards/non-functional-requirements/availability.md
+++ b/docs/standards/non-functional-requirements/availability.md
@@ -44,7 +44,7 @@ system, etc.) and is multi-zonal. See
 
 Backups are performed daily. Backups can be used to recover state to datastores
 in the event of ransomware attack from before the point off attack. See
-[Data Backup Service](site:services/data-backup.md).
+[Data Backup Service](site:services/data-backup).
 
 DevOps change practices are followed:
 <https://docs.google.com/document/d/1tGIYU-11l7G7byz1IZw-mhDHjJMPRnS_rIrAX5esyTM/edit?usp=sharing>.
diff --git a/docs/standards/tech-lead-forum.md b/docs/standards/tech-lead-forum.md
index 1154bcb2..ce0bef78 100644
--- a/docs/standards/tech-lead-forum.md
+++ b/docs/standards/tech-lead-forum.md
@@ -21,7 +21,7 @@ delivery. The forum is then born with the goal of continue to follow and promote
 division when more coordination is required due of its size and complexity.
 
 The Tech Lead Forum is defined in formal language by its [terms of
-reference](site:reference/misc/tech-lead-forum.md).
+reference](site:reference/misc/tech-lead-forum).
 
 ## Standards and recommendations
 
@@ -58,4 +58,4 @@ guidebook.
 
 ## Read more
 
-* [Tech Lead Forum Terms of Reference](site:reference/misc/tech-lead-forum.md).
+* [Tech Lead Forum Terms of Reference](site:reference/misc/tech-lead-forum).
diff --git a/docs/tutorials/automating-gitlab-releases.md b/docs/tutorials/automating-gitlab-releases.md
index 89a7a899..b0e1edaf 100644
--- a/docs/tutorials/automating-gitlab-releases.md
+++ b/docs/tutorials/automating-gitlab-releases.md
@@ -18,7 +18,7 @@ available workflows.
   [gitlab-runner-infrastructure](https://gitlab.developers.cam.ac.uk/uis/devops/devhub/gitlab-runner-infrastructure)
   Terraform configuration.
 - You must have followed the steps in [How to enable automated GitLab
-  releases](site:howtos/git-gitlab/enable-automated-gitlab-releases.md) to enable the release
+  releases](site:howtos/git-gitlab/enable-automated-gitlab-releases) to enable the release
   pipeline and create a `.release-it.json` config file in your repository.
 
 ## Default workflow
@@ -26,7 +26,7 @@ available workflows.
 The default workflow for the `release-it.yml` GitLab template is based on the
 [Conventional Commit](https://www.conventionalcommits.org/en/v1.0.0/)
 specification, as recommended in the [Git
-Commits](site:explanations/git-gitlab/git.md#commits) section of this guidebook. Each time
+Commits](site:explanations/git-gitlab/git#commits) section of this guidebook. Each time
 commits are merged to the default branch the `release` job analyses each new
 commit message and determines what the next version of the code should be.
 
@@ -59,7 +59,7 @@ release for your project.
    job in the triggered pipeline. This job will invoke the `release-it` command
    to perform the tasks configured in your project's `.release-it.json` config
    file. If you used the example `.release-it.json` file from the [Enable
-   automated GitLab releases](site:howtos/git-gitlab/enable-automated-gitlab-releases.md)
+   automated GitLab releases](site:howtos/git-gitlab/enable-automated-gitlab-releases)
    how-to, the following tasks will be performed.
 
       - Calculate the next version of your project based on the commit messages
@@ -73,7 +73,7 @@ release for your project.
 ## Alternate workflow
 
 The `release-it.yml` GitLab template has an [alternate
-workflow](site:explanations/git-gitlab/gitlab-release-automation.md#alternate-workflow) mode
+workflow](site:explanations/git-gitlab/gitlab-release-automation#alternate-workflow) mode
 which queues unreleased changes in a draft release merge request.
 
 The following steps show you how to use this workflow to create a new minor
@@ -176,5 +176,5 @@ bug in the original version `1.0.0` code you could do the following.
 ## See also
 
 For more information on how this process works see the [GitLab release
-automation](site:explanations/git-gitlab/gitlab-release-automation.md) page in the
+automation](site:explanations/git-gitlab/gitlab-release-automation) page in the
 Explanations section.
diff --git a/docs/tutorials/bootstrapping-a-new-application.md b/docs/tutorials/bootstrapping-a-new-application.md
index a3bd31c8..27042710 100644
--- a/docs/tutorials/bootstrapping-a-new-application.md
+++ b/docs/tutorials/bootstrapping-a-new-application.md
@@ -27,14 +27,14 @@ indicated.
 You may also be interested in the following sections after reading the tutorial:
 
 * How to:
-    * [create a new application](site:howtos/development/create-a-new-app.md),
-    * [run applications locally](site:howtos/development/run-an-existing-app.md),
+    * [create a new application](site:howtos/development/create-a-new-app),
+    * [run applications locally](site:howtos/development/run-an-existing-app),
     * [register Google Cloud-hosted GitLab
-    runners](site:howtos/gke-gitlab-runners/register-a-gke-gitlab-runner.md), and
-    * [run database migrations at deploy-time](site:howtos/development/run-database-migrations-when-deploying.md).
-* [Learn about our webapp boilerplate](site:explanations/development/webapp-boilerplate.md).
+    runners](site:howtos/gke-gitlab-runners/register-a-gke-gitlab-runner), and
+    * [run database migrations at deploy-time](site:howtos/development/run-database-migrations-when-deploying).
+* [Learn about our webapp boilerplate](site:explanations/development/webapp-boilerplate).
 * Reference guides:
-    * [local application development](site:reference/misc/webapp-developer-environment.md), and
+    * [local application development](site:reference/misc/webapp-developer-environment), and
     * [terraform deployment](site:reference/deployment).
 
 ## The general plan
@@ -55,7 +55,7 @@ requests.
 As of November 2023 the most recent version of our development and deployment process is as follows:
 
 * Releases are managed using our [release automation CI
-  template](site:explanations/git-gitlab/gitlab-release-automation.md).
+  template](site:explanations/git-gitlab/gitlab-release-automation).
   As features/fixes are merged, a Merge Request representing the "next" release is
   automatically maintained. Merging this Merge Request causes a new release to be made.
   See, as an example, [the 0.7.0 release Merge
@@ -70,7 +70,7 @@ pipeline](https://gitlab.developers.cam.ac.uk/uis/devops/regent-house-ballots/ba
 * Releases of the web application code itself are versioned using semantic versioning. The version
   number is present in the `pyproject.toml` file and is automatically incremented by the release
   automation.
-* [Conventional commits](site:explanations/git-gitlab/git.md#commits) are used to indicate
+* [Conventional commits](site:explanations/git-gitlab/git#commits) are used to indicate
   which commits add new features, fix bugs or introduce backwards compatibility changes
   necessitating a new major version.
 * The [terraform configuration for
@@ -122,7 +122,7 @@ purpose of the application, b) it being a webapp and so belonging under .apps.ca
 being a cross-University application.
 
 DNS within the University is a complex topic. There is a [dedicated section of this
-guidebook](site:reference/cloud-platform/dns.md) devoted to it.
+guidebook](site:reference/cloud-platform/dns) devoted to it.
 
 ### Creating GitLab runners
 
diff --git a/docs/tutorials/creating-a-python-package.md b/docs/tutorials/creating-a-python-package.md
index f14c545e..f9005d3a 100644
--- a/docs/tutorials/creating-a-python-package.md
+++ b/docs/tutorials/creating-a-python-package.md
@@ -1695,7 +1695,7 @@ tests.
 We're happy with our project now. Let's publish it.
 
 We have a dedicated [how-to document for publishing
-packages](site:howtos/python/publish-a-python-package.md) but the short version is: "we
+packages](site:howtos/python/publish-a-python-package) but the short version is: "we
 publish packages when we tag a commit".
 
 Do this now by creating a tag with the same name as the package version:
diff --git a/docs/tutorials/gcp-custom-dns.md b/docs/tutorials/gcp-custom-dns.md
index 12416ab2..99fd8baa 100644
--- a/docs/tutorials/gcp-custom-dns.md
+++ b/docs/tutorials/gcp-custom-dns.md
@@ -4,12 +4,12 @@ title: Custom DNS for Cloud Platform Service
 
 # Custom DNS for Cloud Platform Service
 
-We have a [Cloud Platform DNS](site:reference/cloud-platform/dns.md) guide, which gives an overview of
+We have a [Cloud Platform DNS](site:reference/cloud-platform/dns) guide, which gives an overview of
 the different aspects of DNS that can be used as part of the Cloud Platform. This doesn't go into
 the specifics of setting up a custom domain for a GCP service, however.
 
 In this tutorial, we'll walk through a recent implementation of a custom domain for the
-[Lab Allocator](site:services/lab-allocator.md) product.
+[Lab Allocator](site:services/lab-allocator) product.
 
 These were the requirements for the custom domain:
 
@@ -26,7 +26,7 @@ Therefore, the custom domain would be `laballocator.apps.cam.ac.uk`, which needs
 In order to use a custom DNS name using the standard UIS [GCP Deploy Boilerplate](https://gitlab.developers.cam.ac.uk/uis/devops/gcp-deploy-boilerplate),
 the web app DNS must be verified.
 
-Following [Domain verification instructions](site:reference/cloud-platform/dns.md#domain-verification):
+Following [Domain verification instructions](site:reference/cloud-platform/dns#domain-verification):
 e.g.:
 
 ```console
-- 
GitLab