Hosting Statamic on Cloudflare Pages

In this article we explore how we moved Swiftmade.co, our Statamic powered website to Cloudflare Pages
Ahmet Özışık · Founder · February 26th, 2025

At Swiftmade, we recently migrated our Statamic-powered website to Cloudflare Pages for improved performance and simplified hosting. Here's how we set up our deployment workflow to make it seamless and secure.

How Everything Connects: The Big Picture

Our setup works like this:

  • We develop our website locally using Statamic, a flat-file CMS built on Laravel
  • When we're ready to deploy, we push changes to our GitHub repository's main branch
  • A GitHub Action automatically runs Statamic's static site generator (ssg:generate)
  • The generated static files are committed to a separate live branch
  • Cloudflare Pages watches this live branch and deploys the static content to its global CDN

This workflow allows us to maintain a dynamic CMS for content management while serving blazing-fast static pages to our visitors—without managing any server infrastructure.

Automating Deployments with GitHub Actions

Our solution was to use Statamic's static site generation capabilities along with GitHub Actions to automate deployments. This way, we can keep our build workflow & configuration in our repository, and don't have to worry about internal changes to Cloudflare's own build system.

Here's how our Github Actions yaml looks:

# .github/workflows/cloudflare.yaml
name: Deploy to Cloudflare Pages

on:
  push:
    branches:
      - main

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
    
      - uses: actions/setup-node@v2
        with:
          node-version: 20
      
      - name: Setup PHP
        uses: shivammathur/setup-php@v2
        with:
          php-version: '8.2'

      - name: Install Dependencies
        run: composer install --no-dev --optimize-autoloader
        
      - name: Generate Static Site
        run: |
          npm ci
          npm run production
          php please ssg:generate
          rm storage/app/static/css/.gitignore
          cp resources/cloudflare/_headers storage/app/static/_headers

      - name: Setup Git Config
        run: |
          git config user.name "GitHub Actions Bot"
          git config user.email "<[email protected]>"
          
      - name: Push
        uses: s0/git-publish-subdir-action@develop
        env:
          REPO: self
          BRANCH: live
          FOLDER: storage/app/static
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          MESSAGE: "Build: ({sha}) {msg}"

This workflow runs whenever we push to the main branch. It generates a static version of our site using Statamic's ssg:generate command and then pushes the compiled files to a live branch. Our Cloudflare Pages project is configured to watch this branch for changes, triggering a new deployment whenever updates occur.

Obtaining GITHUB_TOKEN for Your Deployment Workflow

Good news! You don't need to manually create a token for your GitHub Actions workflow. GitHub automatically provides a GITHUB_TOKEN secret that has permissions to push to branches within the same repository.

You can learn more about this built-in secret here.

Security Headers

Turns out, Cloudflare Pages allows us to add custom headers through a simple _headers file at the root of our deployment. Here's what our configuration looks like:

https://swiftmade.co/*
  X-Frame-Options: SAMEORIGIN
  X-Content-Type-Options: nosniff
  Permissions-Policy: document-domain=()
  Strict-Transport-Security: max-age=31536000; includeSubDomains

https://swiftmade.pages.dev/*
  X-Robots-Tag: noindex
  X-Frame-Options: DENY
  X-Content-Type-Options: nosniff
  Permissions-Policy: document-domain=()
  Strict-Transport-Security: max-age=31536000; includeSubDomains

We stored this file under resources/cloudflare/_headers and in our Github actions, we copy it to the root of our static output folder.

The Results

This setup has given us the best of both worlds: the user-friendly experience of Statamic's CMS with the performance of Cloudflare's global edge network.

This approach won't suit websites that have dynamic content, or sites that have features like login. If you're running a Statamic site and use Static Site Generator before hosting it, then moving to Cloudflare might make sense.

At the time of writing, Cloudflare Pages has a very generous free tier, so it also means that not paying for a server and not worrying about things like server maintenance / security updates / weak passwords.

If you need support with taking your Statamic project live, you can always contact us at [email protected].