diff --git a/.gitlab-ci/build-libcamera-docs.sh b/.gitlab-ci/build-libcamera-docs.sh
new file mode 100755
index 000000000000..26aec0813007
--- /dev/null
+++ b/.gitlab-ci/build-libcamera-docs.sh
@@ -0,0 +1,42 @@
+#!/bin/bash
+
+# SPDX-License-Identifier: GPL-2.0-or-later
+# SPDX-FileCopyrightText: © 2026 Ideas on Board
+#
+# Build libcamera docs and collect them in ./docs
+
+set -e
+
+source "$(dirname "$0")/lib.sh"
+source "$(dirname "$0")/build-libcamera-common.sh"
+
+libcamera_build_docs() {
+	echo "Building libcamera docs"
+
+	meson compile -C build -j$BUILD_CONCURRENT_JOBS documentation
+
+	echo "Installing docs"
+	rm -rf build/install
+
+	meson install -C build \
+		--destdir install \
+		--no-rebuild \
+		--tags doc,doc-internal
+
+	local doc_dir=(build/install/usr/local/share/doc/libcamera-*)
+
+	rm -rf docs
+	mv "${doc_dir}/html" docs
+
+	# Move the internal and public API directories to the correct location
+	# in case the libcamera documentation post-install script has not run.
+	for api in internal-api public-api ; do
+		if [[ -d "${doc_dir}/${api}" ]] ; then
+			rm -rf "docs/${api}"
+			mv "${doc_dir}/${api}" docs/
+		fi
+	done
+}
+
+run libcamera_setup
+run libcamera_build_docs collapsed
diff --git a/gitlab-ci.yml b/gitlab-ci.yml
index 2b376c5da1ee..278e69079c15 100644
--- a/gitlab-ci.yml
+++ b/gitlab-ci.yml
@@ -209,10 +209,6 @@ build-full:debian:13:
       - ARCH: amd64
         CC: gcc-14
         CXX: g++-14
-        MESON_OPTIONS: >-
-          ${MESON_ALL_OPTIONS}
-          -D documentation=enabled
-          -D doc_werror=true
       - ARCH: amd64
         BUILD_TYPE: release
         CC: gcc-14
@@ -301,6 +297,35 @@ build-package:debug:
       - ARCH: amd64
       - ARCH: arm64
 
+# Build documentation.
+build-docs:
+  extends:
+    - .fdo.distribution-image@debian
+    - .libcamera-ci.debian:13
+    - .libcamera-ci.scripts
+  stage: build
+  needs:
+    - job: container-debian:13
+      artifacts: false
+  script:
+    - $CI_PROJECT_DIR/.gitlab-ci/build-libcamera-docs.sh
+  artifacts:
+    name: libcamera-docs-${CI_COMMIT_SHA}
+    when: always
+    expire_in: 1 week
+    paths:
+      - build/meson-logs/
+      - build/build.ninja
+      - docs
+  variables:
+    BUILD_TYPE: release
+    MESON_OPTIONS: >-
+      --auto-features disabled
+      -D pipelines=[]
+      -D test=false
+      -D documentation=enabled
+      -D doc_werror=true
+
 # ------------------------------------------------------------------------------
 # Lint stage - Run checkstyle.py and check merge suitability
 # ------------------------------------------------------------------------------
