Cloudflare offers free hosting for static pages with Cloudflare pages. I use it to host my Docusaurus documentation. I could have used GitHub pages, since my documentation is hosted on GitHub. I hadn’t considered it initially. I thought it was only available for public repositories, but after some research, I discovered that it can indeed be used for private repos too.
That said, Cloudflare Pages has an advantage that kept me from switching. With Cloudflare Pages, you can set up preview deployments, which GitHub Pages lacks. These features allow me to test changes in a separate environment before pushing them live, giving me more control over my deployment process.
But to be honest, I didn't feel like switching after finding out about GitHub pages.
In this article, I’ll walk you through two methods for setting up deployments on Cloudflare Pages. The first uses Cloudflare's built-in automatic deployments, and the second uses automatic deployment with GitHub Actions.
How to Set Up Cloudflare Pages
Method 1: Automatic Deployment with Cloudflare
Cloudflare Pages’ default setup allows you to deploy automatically from your GitHub repository. If you don't need more control, stick with it.
- login to Cloudflare and navigate to Workers & Pages
- choose Create and authorize Cloudflare to access your GitHub account (or GitLab)
- select the repository that you want to deploy
- configure the build settings - select a template or enter the build command. If your site is in a subdirectory, select a root directory in advanced settings.
- leave the deployment branch as main, and click on Save and Deploy.
- your website will be built in short time and you'll get your projects domain.
For example, docusaurus in a monorepo might look like this:
If you happen to get an error like This site can’t provide a secure connection, I believe this is something related to Cloudflare DNS. Try reaching it in a few minutes, try without the https, and then https.
Point a custom domain to your site
I'd usually add a CNAME record for root and www to point to a domain. But it doesn't work like that for this case. To point, choose Custom domains tab, add a root domain and www. Like in this picture:
Method 2: Automatic deployment with GitHub Actions
Using GitHub Actions to deploy to Cloudflare Pages gives you more control over when and how deployments are triggered. With this method, you can specify deployment conditions, such as only deploying on changes to certain files or triggering deployments from specific branches.
- Create a new workflow in your github repository e.g. `.github/workflows/my-website.yml`
name: Docusaurus Website
on:
# this is just for manual invoking of deploy, optional
workflow_dispatch:
push:
branches:
- main
paths:
- ".github/workflows/my-website.yml"
- "my-website/**"
jobs:
build-and-deploy:
runs-on: ubuntu-latest
name: Build and Deploy
steps:
- name: Checkout Code
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
- name: Install Dependencies
working-directory: my-website
run: |
npm install
- name: Build
working-directory: my-website
run: |
npm run build
- name: Deploy
uses: cloudflare/wrangler-action@v3
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
command: pages deploy website/build --project-name=effective-octo-doodle
This will trigger a new deployment whenever I trigger it, or whenever a change is made to main branch in website directory or in my workflow file.
Provide Cloudflare api token
You need to provide 2 secrets, CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID.
Find your account id by going to Cloudflare pages and it should be visible in the right sidebar.
Get api token from https://dash.cloudflare.com/profile/api-tokens, create api token and select create a custom token. Select edit cloudflare pages and read user details.
Any method you choose is a one time configuration only. Cloudflare's automatic method is easier to setup, just a few clicks and you're ready to go. GitHub requires a bit more work, but is good when you don't want to trigger a build on each file change in a monorepo where you version api, app, docs etc.