diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index f74b7b4d01d7f4d0c7b9745b96e47317994acafa..01896641d862279c9e83fa800b366d36e73b5d08 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -13,7 +13,7 @@ stages:
 
 image: $DOCKER_IMAGE
 
-germinate-output:
+.render:
   stage: germinate
   before_script:
     - export DEBIAN_FRONTEND=noninteractive
@@ -27,11 +27,26 @@ germinate-output:
     - germinate -S file://$GERMINATE_SEED -s $PLATFORM -m $DEBIAN_MIRROR -d $RELEASE -a $ARCHITECTURE -c $COMPONENTS
     - cd ..
     - ./extract-list.sh
+    - mkdir public/
+    - mv $GERMINATE_OUTPUT_DIR all development target sdk public/
+    - cd public/
+    - rm $GERMINATE_OUTPUT_DIR/*_{Installer,}Packages $GERMINATE_OUTPUT_DIR/*_Sources
+    - find -type d | xargs -IDIR sh -c '../htmlindex "DIR" > "DIR/index.html"'
   artifacts:
     when: always
     paths:
-      - $GERMINATE_OUTPUT_DIR
-      - all
-      - development
-      - target
-      - sdk
+      - public/
+
+render:
+  extends: .render
+  rules:
+    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+      when: never
+    - if: $CI_COMMIT_BRANCH != $CI_DEFAULT_BRANCH
+
+pages:
+  extends: .render
+  rules:
+    - if: $CI_PIPELINE_SOURCE == "merge_request_event"
+      when: never
+    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
diff --git a/htmlindex b/htmlindex
new file mode 100755
index 0000000000000000000000000000000000000000..358651eba27912c7fa2e09740c3742f6a5f24f45
--- /dev/null
+++ b/htmlindex
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+set -eu
+DIR=$1
+
+cd "$DIR"
+
+echo '<!DOCTYPE html><html><head><title>Apertis Germinate</title><body><ul>'
+test "$DIR" != . && echo '<li><a href="../">🗀 ../</a>'
+find * -maxdepth 0 -type d | xargs -ISUBDIR echo '<li><a href="SUBDIR/">🗀 SUBDIR/</a>'
+find * -maxdepth 0 -type f | xargs -IFILE echo '<li><a href="FILE">🗎 FILE</a>'
+echo '</ul>'