Multi-Subdomain Cloudflare Deployment Guide

Step-by-step production blueprint for deploying Hugo-Carbon with multiple subdomains on Cloudflare Pages and DNS completely for free.

This guide provides a comprehensive, production-ready blueprint for deploying the Hugo-Carbon Modular Engine across multiple isolated subdomains using Cloudflare Pages and Cloudflare DNS at zero monthly hosting cost ($0/mo).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
                    ┌────────────────────────┐
                    │  Cloudflare Anycast    │
                    │      Edge Network      │
                    └───────────┬────────────┘
        ┌───────────────┬───────┴───────┬───────────────┐
        ▼               ▼               ▼               ▼
┌──────────────┐┌──────────────┐┌──────────────┐┌──────────────┐
│    cesar     ││     blog     ││     apps     ││    carbon    │
│  .caldeira.cc││  .caldeira.cc││  .caldeira.cc││  .caldeira.cc│
│ (Personal)   ││ (Publication)││ (Interactive)││ (Engine/Docs)│
└──────────────┘└──────────────┘└──────────────┘└──────────────┘
        │               │               │               │
        └───────────────┴───────┬───────┴───────────────┘
                    ┌────────────────────────┐
                    │   assets.caldeira.cc   │
                    │   (Shared Static CDN)  │
                    └────────────────────────┘

1. Multi-Target Build Strategy

The Hugo-Carbon project compiles into 5 discrete public directories:

1
2
3
4
5
6
# Compile each environment into its respective target directory
hugo --environment cesar  -d public/cesar  --cleanDestinationDir
hugo --environment blog   -d public/blog   --cleanDestinationDir
hugo --environment apps   -d public/apps   --cleanDestinationDir
hugo --environment carbon -d public/carbon --cleanDestinationDir
hugo --environment assets -d public/assets --cleanDestinationDir

Automation Shell Script (scripts/build-all.sh)

Create an executable build script in your repository root:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
#!/usr/bin/env bash
set -euo pipefail

echo "=================================================="
echo "Compiling all Hugo-Carbon Subdomains..."
echo "=================================================="

export HUGO_ENV="production"

for env in cesar blog apps carbon assets; do
  echo "--> Building target: ${env}..."
  hugo --environment "${env}" -d "public/${env}" --cleanDestinationDir --minify
done

echo "--> Running dependency and license audit..."
python3 scripts/verify-dependencies.py

echo "--> Auditing internal link integrity..."
python3 scripts/test_public_html.py

echo "🎉 ALL SUBDOMAINS COMPILED AND VERIFIED SUCCESSFULLY!"

Make it executable:

1
chmod +x scripts/build-all.sh

2. Cloudflare Pages Project Configuration

Cloudflare Pages provides unlimited bandwidth, global SSD edge CDN, automatic SSL certificates, and 500 build operations per month on the Free tier.

Create 5 distinct Pages projects linked to the same GitHub repository:

Pages Project NameCustom SubdomainBuild CommandOutput Directory
caldeira-cesarcesar.caldeira.cchugo --environment cesar -d public/cesarpublic/cesar
caldeira-blogblog.caldeira.cchugo --environment blog -d public/blogpublic/blog
caldeira-appsapps.caldeira.cchugo --environment apps -d public/appspublic/apps
caldeira-carboncarbon.caldeira.cchugo --environment carbon -d public/carbonpublic/carbon
caldeira-assetsassets.caldeira.cchugo --environment assets -d public/assetspublic/assets

Environment Variables in Cloudflare Pages Dashboard

For each project, navigate to Settings > Environment Variables and add:

  • HUGO_VERSION: 0.149.0 (or latest extended)
  • NODE_VERSION: 20.x

3. GitHub Actions Automated Deployment Workflow

Instead of relying on Cloudflare’s native build limits, you can use GitHub Actions to build all 5 subdomains in parallel and deploy them directly using Wrangler.

Create .github/workflows/deploy.yml:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
name: Deploy Multi-Subdomain Hugo-Carbon to Cloudflare Pages

on:
  push:
    branches:
      - main
  workflow_dispatch:

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    strategy:
      matrix:
        include:
          - env: "cesar"
            project: "caldeira-cesar"
          - env: "blog"
            project: "caldeira-blog"
          - env: "apps"
            project: "caldeira-apps"
          - env: "carbon"
            project: "caldeira-carbon"
          - env: "assets"
            project: "caldeira-assets"

    steps:
      - name: Checkout Code
        uses: actions/checkout@v4
        with:
          submodules: recursive
          fetch-depth: 0

      - name: Setup Hugo Extended
        uses: peaceiris/actions-hugo@v3
        with:
          hugo-version: "0.149.0"
          extended: true

      - name: Setup Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Build Hugo Target
        run: |
          hugo --environment ${{ matrix.env }} -d public/${{ matrix.env }} --minify --cleanDestinationDir

      - name: Verify Link Integrity & Dependencies
        run: |
          python3 scripts/verify-dependencies.py

      - name: Deploy to Cloudflare Pages
        uses: cloudflare/wrangler-action@v3
        with:
          apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
          accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
          command: pages deploy public/${{ matrix.env }} --project-name=${{ matrix.project }} --commit-dirty=true

4. Cloudflare DNS & Custom Domains

In your Cloudflare Dashboard for your domain (caldeira.cc):

1. DNS Records Setup

Add CNAME records with the Proxy status: Proxied (Orange Cloud):

TypeNameTargetProxy Status
CNAMEcesarcaldeira-cesar.pages.dev🟠 Proxied
CNAMEblogcaldeira-blog.pages.dev🟠 Proxied
CNAMEappscaldeira-apps.pages.dev🟠 Proxied
CNAMEcarboncaldeira-carbon.pages.dev🟠 Proxied
CNAMEassetscaldeira-assets.pages.dev🟠 Proxied
CNAME@ (apex)caldeira-cesar.pages.dev🟠 Proxied

2. Apex Domain Redirection (Page Rules)

To redirect caldeira.cc to https://cesar.caldeira.cc/:

  • Rule URL: caldeira.cc/*
  • Setting: Forwarding URL (301 Permanent Redirect)
  • Destination: https://cesar.caldeira.cc/$1

5. Security Headers, CORS & Performance Optimization

1. CORS Headers for assets.caldeira.cc

Because fonts (IBM Plex WOFF2) and scripts are shared from assets.caldeira.cc, Cloudflare must serve appropriate CORS headers.

In the Cloudflare Dashboard, go to Rules > Transform Rules > Modify Response Header:

  • Rule Name: Allow Cross-Origin Asset CDN
  • If Incoming Request: Hostname eq "assets.caldeira.cc"
  • Response Headers:
    • Access-Control-Allow-Origin: *
    • Access-Control-Allow-Methods: GET, HEAD, OPTIONS
    • Timing-Allow-Origin: *

2. Security Headers (Transform Rules)

Add a Response Header rule applied across all subdomains:

  • X-Frame-Options: SAMEORIGIN
  • X-Content-Type-Options: nosniff
  • Referrer-Policy: strict-origin-when-cross-origin
  • Permissions-Policy: camera=(), microphone=(), geolocation=()

3. SSL/TLS and Edge Optimization

In the Cloudflare Dashboard:

  1. SSL/TLS: Set encryption mode to Full (Strict).
  2. Speed > Optimization:
    • Enable Brotli compression.
    • Enable Early Hints (103 Early Hints).
    • Enable HTTP/3 (with QUIC) and 0-RTT Connection Resumption.
  3. Caching > Cache Rules:
    • Add a rule for *.woff2, *.css, and *.js: Edge TTL 1 Month, Browser TTL 1 Year.