diff --git a/.cloud_build/specification/cloudbuild.yaml b/.cloud_build/specification/cloudbuild.yaml
new file mode 100644
index 000000000..156f0f585
--- /dev/null
+++ b/.cloud_build/specification/cloudbuild.yaml
@@ -0,0 +1,11 @@
+steps:
+- name: 'ubuntu'
+  args: ['specification/scripts/build_pdf']
+  env:
+  - 'BRANCH_NAME=$BRANCH_NAME'
+  - '_PR_NUMBER=$_PR_NUMBER'
+- name: 'gcr.io/cloud-builders/gsutil'
+  args: [ '-m', 'cp', '-r', 'specification/artifacts/*', 'gs://dart-specification']
+options:
+  automapSubstitutions: true
+  logging: CLOUD_LOGGING_ONLY
diff --git a/specification/.gitignore b/specification/.gitignore
index 7ab97f235..1c343ff35 100644
--- a/specification/.gitignore
+++ b/specification/.gitignore
@@ -11,3 +11,4 @@ dartLangSpec-terse.tex
 *-list.txt
 .dart_tool/
 .packages
+firebase/
diff --git a/specification/scripts/build_pdf b/specification/scripts/build_pdf
new file mode 100755
index 000000000..7efed9e2e
--- /dev/null
+++ b/specification/scripts/build_pdf
@@ -0,0 +1,21 @@
+#!/usr/bin/env -S bash --norc
+
+set -ex
+
+apt-get update -qq
+apt-get install -y --no-install-recommends \
+    build-essential \
+    texlive-latex-base \
+    texlive-latex-extra \
+    texlive-fonts-recommended \
+    lmodern
+cd specification
+make
+mkdir -p artifacts
+if [ "$BRANCH_NAME" == "main" ]; then
+  cp dartLangSpec.pdf artifacts/DartLangSpecDraft.pdf
+elif [ "$_PR_NUMBER" != "" ]; then
+  mkdir -p artifacts/pr/$_PR_NUMBER
+  cp dartLangSpec.pdf artifacts/pr/$_PR_NUMBER/DartLangSpecDraft.pdf
+fi
+