diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 43390fcfa3958e9c2439cbb57ef79670851100d3..847812d606e91c7f4f384b158d57a27942f607c7 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -1,13 +1,22 @@
 image: alpine:latest
 
+# Only run pipelines for pushes on branches
 workflow:
   rules:
     - if: $CI_COMMIT_BRANCH
 
-deploy-docs:
+# We can't deploy multiple different variants of GitLab Pages sites (e.g. one
+# per branch), so we use this quick instead. GitLab has a special browsable URL
+# for job artifacts on public projects, and we can create an Environment that
+# points to that URL so it's easy for devs to know what the current Environment
+# URL for their branch is.
+.deploy:
   stage: deploy
   tags:
     - docker
+  rules:
+    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+      when: never
   script:
     - sed -i "s/%%BRANCH%%/$CI_COMMIT_BRANCH/g" src/index.html
     - mv src public
@@ -15,5 +24,18 @@ deploy-docs:
     paths:
       - public/
   environment:
-    name: $CI_COMMIT_BRANCH
+    name: review/$CI_COMMIT_BRANCH
     url: "https://$CI_PROJECT_NAMESPACE.$CI_PAGES_DOMAIN/-/$CI_PROJECT_NAME/-/jobs/$CI_JOB_ID/artifacts/public/index.html"
+
+# Deploy a review environment for any push to a branch that is not the default
+# branch
+review:
+  extends: .deploy
+
+# Deploy to GitLab Pages for pushes on the default branch
+pages:
+  extends: .deploy
+  rules:
+    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
+
+# vi: set ts=2 sw=2 et ft=yaml: