Skip to main content

Migrating Docusaurus — Self-Hosted to GitHub + Cloudflare Pages

Learning Focus

This module walks you through the complete, hands-on migration from a self-hosted Docusaurus installation to a GitHub + Cloudflare Pages deployment — the exact workflow the author has personally tested and runs in production.

Migration Overview

flowchart LR
A["Self-Hosted Docusaurus\n(Docker on VPS)"] -->|"Step 1: Init Git"| B["Local Git Repo\n(existing files)"]
B -->|"Step 2: Push to GitHub"| C["GitHub Repository\n(private or public)"]
C -->|"Step 3: Connect"| D["Cloudflare Pages\n(dashboard)"]
D -->|"Step 4: Configure"| E["Build Settings\n(npm run build / build/)"]
E -->|"Step 5: Deploy"| F["Live on\nyour-project.pages.dev"]
F -->|"Step 6: Custom domain"| G["docs.yourdomain.com\n(HTTPS, DDoS, global CDN)"]

style A fill:#6b7280,color:#fff,stroke:#4b5563
style C fill:#24292e,color:#fff,stroke:#555
style D fill:#f6821f,color:#fff,stroke:#e5711e
style G fill:#16a34a,color:#fff,stroke:#15803d

Pre-Migration Checklist

Before you start, confirm:

  • You have a GitHub account (free tier is fine)
  • You have a Cloudflare account (free tier is fine)
  • Your domain is managed in Cloudflare DNS (for custom domain setup)
  • Your Docusaurus project builds successfully (npm run build produces a build/ directory)
  • git is installed on your local machine

Step 1 — Prepare Your Docusaurus Repository

1a. Initialize Git (if not already a repo)

If your Docusaurus files are not yet in a Git repository:

Initialize Git in your Docusaurus project
# Navigate to your Docusaurus root
cd /path/to/your/docusaurus/site

# Initialize
git init

# Create .gitignore
cat > .gitignore << 'EOF'
node_modules/
build/
.docusaurus/
.cache-loader/
.env
.env.local
EOF

# Stage all files
git add .

# Initial commit
git commit -m "chore: initial commit — Docusaurus site"

1b. Verify Your Build Works

Test the build locally before pushing
# Install dependencies
npm install

# Build the site
npm run build

# Expected output:
# [SUCCESS] Generated static files in "build".
# [INFO] Use `npm run serve` to test your build locally.

# Optional: serve locally to verify
npm run serve
# → http://localhost:3000
important

The build/ directory is what Cloudflare Pages will serve. Ensure it generates correctly without errors before proceeding.

1c. Check docusaurus.config.js

For Cloudflare Pages deployment, the url and baseUrl must be set correctly:

docusaurus.config.js — key fields
const config = {
// Set to your custom domain (or pages.dev URL during initial setup)
url: 'https://docs.yourdomain.com',

// If deploying at root, use '/'
// If deploying to a subdirectory (rare on Pages), use '/subdirectory/'
baseUrl: '/',

// ... rest of config
};

Step 2 — Create a GitHub Repository

Via GitHub Web UI

  1. Go to github.com/new
  2. Name your repository (e.g., my-docs)
  3. Choose Private or Public — Cloudflare Pages supports both
  4. Do NOT initialize with README (your repo already has files)
  5. Click Create repository

Via GitHub CLI

Create repo with GitHub CLI (gh)
# Install gh CLI if not present
# https://cli.github.com/

# Authenticate
gh auth login

# Create private repository
gh repo create my-docs --private --source=. --remote=origin --push

# Or create public repository
gh repo create my-docs --public --source=. --remote=origin --push

Push Existing Repository

Add remote and push
# Add GitHub as the remote origin
git remote add origin https://github.com/your-username/my-docs.git

# Rename branch to main (if needed)
git branch -M main

# Push
git push -u origin main

Step 3 — Connect to Cloudflare Pages

Via Cloudflare Dashboard

  1. Log in to dash.cloudflare.com
  2. Go to Workers & PagesCreatePages tab
  3. Click Connect to Git
  4. Authorize the Cloudflare Pages GitHub App (first time only)
  5. Select your repository (my-docs)
  6. Click Begin setup

Build Configuration

FieldValue for Docusaurus
Project namemy-docs (becomes my-docs.pages.dev)
Production branchmain
Framework presetDocusaurus (auto-detected)
Build commandnpm run build
Build output directorybuild
Root directory/ (leave blank unless monorepo)
Framework Preset

Select Docusaurus from the framework dropdown and Cloudflare will automatically fill in the build command and output directory. You can override them manually if needed.

Environment Variables (Optional)

If your build needs env variables (e.g., Algolia keys, custom API endpoints):

VariableExample
NODE_VERSION20
ALGOLIA_APP_IDyour-algolia-app-id
ALGOLIA_API_KEYyour-algolia-api-key

Set these under Settings → Environment variables in the Pages project.

Save and Deploy

Click Save and Deploy. Cloudflare will:

  1. Clone your repository
  2. Run npm run build
  3. Deploy the build/ directory to the edge

First build typically takes 2–4 minutes.


Step 4 — Monitor the Build

Watch the build in real-time:

Workers & Pages → your-project → Deployments → (latest)

Build log example (what to expect for Docusaurus):

12:00:01 [INFO] Cloning repository...
12:00:05 [INFO] Installing dependencies from package-lock.json
12:01:20 [INFO] Running build command: npm run build
12:01:21 [INFO] [docusaurus] Starting the production build...
12:02:45 [SUCCESS] Generated static files in "build".
12:02:45 [INFO] Generated 147 pages in 84.621 seconds.
12:02:50 [INFO] Uploading 147 files to Cloudflare edge...
12:03:02 [SUCCESS] Deployment live at: https://abc123.my-docs.pages.dev

If the build fails, see Troubleshooting below.


Step 5 — Add a Custom Domain

Automatic DNS (Cloudflare-managed domain)

If your domain's DNS is already in Cloudflare:

  1. Go to your Pages project → Custom domains tab
  2. Click Set up a custom domain
  3. Enter docs.yourdomain.com
  4. Click Continue — Cloudflare automatically creates the CNAME record:
docs.yourdomain.com  CNAME  my-docs.pages.dev

SSL is provisioned within ~60 seconds.

Manual DNS (External registrar)

If your DNS is NOT managed by Cloudflare, add this CNAME manually at your registrar:

Host:  docs
Type: CNAME
Value: my-docs.pages.dev
TTL: Auto

Then add the domain in Cloudflare Pages dashboard and verify ownership.


Step 6 — Set Up Automatic Deployments

Once connected, the workflow is entirely automatic:

Your daily workflow after migration
# Edit your docs
vim docs/getting-started.md

# Commit
git add docs/getting-started.md
git commit -m "docs: update getting started guide"

# Push — this triggers a Cloudflare Pages build
git push origin main

# Within ~2-3 minutes, your changes are live globally

Branch Deployments

Every non-main branch also gets a preview URL:

Working with feature branches
# Create a feature branch
git checkout -b feature/new-section

# Make changes and push
git push origin feature/new-section

# Preview URL is automatically created:
# https://<commit-hash>.my-docs.pages.dev
# or
# https://feature-new-section.my-docs.pages.dev

Troubleshooting Common Build Failures

Error: Cannot find module 'X'

# Cause: Dependencies not in package.json
# Fix: ensure devDependencies are committed
npm install some-package
git add package.json package-lock.json
git commit -m "fix: add missing dependency"
git push

Build timeout (20 minutes exceeded)

# Cause: Too many pages, very large build
# Fix 1: Increase Node.js memory
# In Environment Variables:
NODE_OPTIONS=--max-old-space-size=4096

# Fix 2: Disable some slow plugins during CI
# In docusaurus.config.js:
process.env.CF_PAGES && /* disable plugin */

Error: baseUrl mismatch

Fix baseUrl in docusaurus.config.js
// Wrong (causes 404 on assets)
baseUrl: '/my-docs/',

// Correct for root deployment
baseUrl: '/',

Build succeeds but site shows 404

# Check your build output directory
# Docusaurus outputs to: build/
# NOT: dist/, public/, out/

# In Cloudflare Pages dashboard:
# Build output directory: build (no leading slash)

Post-Migration Checklist

After successful deployment, verify:

  • Site loads at your-project.pages.dev
  • Custom domain resolves and shows valid HTTPS
  • All internal links work (no broken navigation)
  • Search works (if using Algolia or Docusaurus search)
  • Images and assets load correctly
  • Sitemap is accessible at /sitemap.xml
  • git push triggers a new build automatically

Key Takeaways

  • The migration from self-hosted Docker Docusaurus → GitHub + Cloudflare Pages takes under 30 minutes.
  • The workflow is: git push → automatic build → global edge deployment.
  • Cloudflare Pages handles SSL, CDN, DDoS protection, and preview deployments for free.
  • Custom domains are configured with a single CNAME record and SSL is automatic.

What's Next