Standalone Static Site on Cloudflare Pages
Guidelines
Section titled “Guidelines”Use this guide for a site that builds to static files, such as HTML, CSS, and JavaScript. Cloudflare Pages serves these files; The site does not need an application server.
Use Cloudflare Pages Direct Upload when GitLab runs the build and deploy jobs. Set the production branch when you create the Pages project.
Local Development
Section titled “Local Development”For local work, install from the lockfile, run the checks, then build and preview the site. This project uses:
npm cinpm run devnpm run lint:docsnpm run checknpm run buildnpm run previewThe build output is dist/. Keep deployment settings in step with the local
build. Check the production URL, page links, assets, and access rules after each
deploy. Keep a known-good commit so you can redeploy it if a release fails.
Treat all built files as public. Never put secrets or private content in the
site. If the site is private, protect each hostname with Cloudflare Access. Check
the custom domain, pages.dev address, and preview URLs. Use identity login for
people and Access service tokens for agents. Store tokens in GitLab or an
approved secret store. Set an expiry and rotate them.
Docker build
Section titled “Docker build”No Docker image is required to build the static site. The build creates files that are uploaded to Cloudflare Pages. A Node.js image with npm may be useful in the GitLab deploy job to run Cloudflare’s Wrangler tool.
Docker Compose
Section titled “Docker Compose”Docker Compose is not required. Use it only if local development needs other services, such as a mock API. Do not use Compose to deploy the site.
GitLab CI/CD
Section titled “GitLab CI/CD”Run lint, tests, and the production build for merge requests and branches. Save
dist/ as a GitLab artifact. The deploy job must use this artifact; it must not
build the site again.
This project’s build checks are:
npm cinpm run lint:docsnpm run checknpm run buildDeploy
Section titled “Deploy”Deploy to production only from the protected main branch. Store these
variables in GitLab CI/CD settings:
| Variable | Purpose |
|---|---|
CLOUDFLARE_API_TOKEN |
Cloudflare API token with Account → Cloudflare Pages → Edit access. Mask and protect it. |
CLOUDFLARE_ACCOUNT_ID |
Cloudflare account ID. |
CF_PAGES_PROJECT_NAME |
Cloudflare Pages project name. |
CF_PAGES_PROJECT_DENV |
GitLab environment name, such as production. |
CF_PAGES_URL |
Site URL used by the build and GitLab environment. |
Use a GitLab resource_group to prevent two production deploys from running at
the same time. Protect the production environment and prevent older pipelines
from replacing newer releases.
Example
Section titled “Example”This is the complete pipeline used by this project in order to build a static
Starlight site, using nodejs in both a
validate and deploy stages Other examples may not require a build stage if
the static assets are pre-existing.
Keep the example in sync with .gitlab-ci.yml:
stages: - quality - deploy
image: gitlab-reg.atech.host/operations/ops-oci-images/base/nodejs:24-alpine
variables: ASTRO_TELEMETRY_DISABLED: "1" NPM_CONFIG_CACHE: "$CI_PROJECT_DIR/.npm" WRANGLER_LOG_PATH: "$CI_PROJECT_DIR/.wrangler/logs"
cache: key: files: - package-lock.json paths: - .npm/
validate: stage: quality script: - npm ci --prefer-offline - npm run lint:docs - npm run check - npm run build artifacts: paths: - dist/ expire_in: 1 week
deploy-to-cloudflare: stage: deploy resource_group: cloudflare-pages-production needs: - job: validate artifacts: true script: - npm ci --prefer-offline - test -n "$CLOUDFLARE_API_TOKEN" || (echo "Set CLOUDFLARE_API_TOKEN in GitLab CI/CD variables" && exit 1) - test -n "$CLOUDFLARE_ACCOUNT_ID" || (echo "Set CLOUDFLARE_ACCOUNT_ID in GitLab CI/CD variables" && exit 1) - test -n "$CF_PAGES_PROJECT_NAME" || (echo "Set CF_PAGES_PROJECT_NAME in GitLab CI/CD variables" && exit 1) - test -n "$CF_PAGES_PROJECT_DENV" || (echo "Set CF_PAGES_PROJECT_DENV in GitLab CI/CD variables" && exit 1) - test -n "$CF_PAGES_URL" || (echo "Set CF_PAGES_URL in GitLab CI/CD variables" && exit 1) - | sed -i "s|</body>|<div style='text-align: center; padding: 1rem; color: #666;'>Deployed $(date -u +'%Y-%m-%dT%H:%M:%SZ') - $CI_COMMIT_SHORT_SHA</div></body>|" dist/index.html - npx wrangler pages deploy ./dist --project-name="$CF_PAGES_PROJECT_NAME" --branch="$CI_COMMIT_BRANCH" --commit-hash="$CI_COMMIT_SHA" environment: name: $CF_PAGES_PROJECT_DENV url: $CF_PAGES_URL rules: - if: '$CI_COMMIT_BRANCH == "main"'Note: The deploy job adds the time and commit ID to the home page before upload.