Files
chill.social/themes/chill-theme/docs/DEPLOYMENT.md
2026-01-28 09:40:37 +01:00

17 KiB

Deployment Guide

Complete guide to deploying your Hugo Saasify Theme site to production. Learn how to deploy to popular platforms and optimize for performance.

Table of Contents

Building for Production

Before deploying, build your site for production.

Build Command

# Basic build
hugo

# Build with minification
hugo --minify

# Build with specific environment
hugo --environment production

Build Output

The build creates a public/ directory containing:

public/
├── index.html
├── css/
│   └── main.min.[hash].css
├── js/
│   └── main.min.[hash].js
├── images/
├── blog/
├── docs/
└── ...

Pre-Deployment Checklist

  • Update baseURL in hugo.toml to production URL
  • Remove draft posts (draft: false or remove drafts)
  • Test build locally: hugo && hugo server -s public
  • Verify all links work
  • Check image paths and assets
  • Test responsive design
  • Validate HTML/CSS
  • Check analytics integration
  • Review SEO meta tags
  • Test performance with Lighthouse

Environment Configuration

Development:

# hugo.toml
baseURL = "http://localhost:1313/"

Production (update before deploying):

# hugo.toml
baseURL = "https://yourdomain.com/"

Platform Deployment Guides

Netlify

Netlify offers automatic deployments from Git with continuous deployment.

Quick Deploy

  1. Push to Git:
git add .
git commit -m "Ready for deployment"
git push origin main
  1. Connect to Netlify:

    • Visit netlify.com
    • Click "Add new site" → "Import an existing project"
    • Choose Git provider (GitHub, GitLab, Bitbucket)
    • Select your repository
  2. Configure Build Settings:

    • Build command: hugo --minify
    • Publish directory: public
    • Production branch: main
  3. Environment Variables (click "Show advanced"):

    HUGO_VERSION = 0.120.0
    HUGO_ENV = production
    
  4. Deploy: Click "Deploy site"

Netlify Configuration File

Create netlify.toml in project root:

[build]
  publish = "public"
  command = "hugo --minify"

[build.environment]
  HUGO_VERSION = "0.120.0"
  HUGO_ENV = "production"
  HUGO_ENABLEGITINFO = "true"

[context.production.environment]
  HUGO_ENV = "production"

[context.deploy-preview]
  command = "hugo --minify --buildFuture -b $DEPLOY_PRIME_URL"

[context.branch-deploy]
  command = "hugo --minify -b $DEPLOY_PRIME_URL"

[[redirects]]
  from = "/old-page"
  to = "/new-page"
  status = 301

[[headers]]
  for = "/*"
  [headers.values]
    X-Frame-Options = "DENY"
    X-XSS-Protection = "1; mode=block"
    X-Content-Type-Options = "nosniff"

Custom Domain

  1. Go to Site settingsDomain management
  2. Click "Add custom domain"
  3. Enter your domain: yourdomain.com
  4. Configure DNS:
    • A Record: Point to Netlify's load balancer IP
    • CNAME: Point www to [your-site].netlify.app
  5. Enable HTTPS (automatic with Let's Encrypt)

Vercel

Vercel provides zero-configuration deployments with global CDN.

Deploy to Vercel

  1. Install Vercel CLI (optional):
npm install -g vercel
  1. Deploy via CLI:
vercel

Or deploy via web interface:

  1. Connect Repository:

    • Visit vercel.com
    • Click "Add New" → "Project"
    • Import your Git repository
  2. Configure Project:

    • Framework Preset: Hugo
    • Build Command: hugo --minify
    • Output Directory: public
    • Install Command: Leave empty
  3. Environment Variables:

HUGO_VERSION=0.120.0
  1. Deploy: Click "Deploy"

Vercel Configuration

Create vercel.json:

{
  "build": {
    "env": {
      "HUGO_VERSION": "0.120.0"
    }
  },
  "redirects": [
    {
      "source": "/old-page",
      "destination": "/new-page",
      "permanent": true
    }
  ],
  "headers": [
    {
      "source": "/(.*)",
      "headers": [
        {
          "key": "X-Frame-Options",
          "value": "DENY"
        },
        {
          "key": "X-Content-Type-Options",
          "value": "nosniff"
        }
      ]
    }
  ]
}

GitHub Pages

Free hosting directly from your GitHub repository.

Setup GitHub Pages

  1. Create Repository:

    • Name: username.github.io (user site)
    • Or: repository-name (project site)
  2. Update Base URL:

# hugo.toml
baseURL = "https://username.github.io/"
# or for project site:
baseURL = "https://username.github.io/repository-name/"
  1. Create GitHub Action:

.github/workflows/hugo.yml:

name: Deploy Hugo site to Pages

on:
  push:
    branches: ["main"]
  workflow_dispatch:

permissions:
  contents: read
  pages: write
  id-token: write

concurrency:
  group: "pages"
  cancel-in-progress: false

defaults:
  run:
    shell: bash

jobs:
  build:
    runs-on: ubuntu-latest
    env:
      HUGO_VERSION: 0.120.0
    steps:
      - name: Install Hugo CLI
        run: |
          wget -O ${{ runner.temp }}/hugo.deb https://github.com/gohugoio/hugo/releases/download/v${HUGO_VERSION}/hugo_extended_${HUGO_VERSION}_linux-amd64.deb \
          && sudo dpkg -i ${{ runner.temp }}/hugo.deb

      - name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: recursive

      - name: Setup Pages
        id: pages
        uses: actions/configure-pages@v4

      - name: Install Node.js dependencies
        run: |
          cp themes/chill-theme/package.json .
          cp themes/chill-theme/postcss.config.js .
          cp themes/chill-theme/tailwind.config.copy.js ./tailwind.config.js
          npm install

      - name: Build with Hugo
        env:
          HUGO_ENVIRONMENT: production
          HUGO_ENV: production
        run: |
          hugo \
            --minify \
            --baseURL "${{ steps.pages.outputs.base_url }}/"

      - name: Upload artifact
        uses: actions/upload-pages-artifact@v2
        with:
          path: ./public

  deploy:
    environment:
      name: github-pages
      url: ${{ steps.deployment.outputs.page_url }}
    runs-on: ubuntu-latest
    needs: build
    steps:
      - name: Deploy to GitHub Pages
        id: deployment
        uses: actions/deploy-pages@v3
  1. Enable GitHub Pages:

    • Go to repository SettingsPages
    • Source: GitHub Actions
    • Save
  2. Push and Deploy:

git add .
git commit -m "Deploy to GitHub Pages"
git push origin main

Cloudflare Pages

Fast, global CDN with automatic deployments.

Deploy to Cloudflare Pages

  1. Connect Repository:

  2. Configure Build:

    • Framework preset: Hugo
    • Build command: hugo --minify
    • Build output directory: public
    • Root directory: Leave blank
  3. Environment Variables:

HUGO_VERSION=0.120.0
  1. Deploy: Click "Save and Deploy"

Custom Domain

  1. Go to project → Custom domains
  2. Add your domain
  3. Configure DNS (Cloudflare handles this automatically)
  4. SSL/TLS is automatic

AWS S3 + CloudFront

Enterprise-grade hosting with AWS infrastructure.

S3 Setup

  1. Create S3 Bucket:
aws s3 mb s3://your-bucket-name --region us-east-1
  1. Enable Static Website Hosting:
aws s3 website s3://your-bucket-name \
  --index-document index.html \
  --error-document 404.html
  1. Set Bucket Policy:

Create bucket-policy.json:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "PublicReadGetObject",
      "Effect": "Allow",
      "Principal": "*",
      "Action": "s3:GetObject",
      "Resource": "arn:aws:s3:::your-bucket-name/*"
    }
  ]
}

Apply:

aws s3api put-bucket-policy \
  --bucket your-bucket-name \
  --policy file://bucket-policy.json
  1. Deploy Site:
hugo --minify
aws s3 sync public/ s3://your-bucket-name --delete

CloudFront Setup

  1. Create Distribution:

    • Origin: Your S3 bucket
    • Viewer protocol: Redirect HTTP to HTTPS
    • Price class: Choose based on needs
    • Alternate domain names: your-domain.com
    • SSL certificate: Request from ACM
  2. Configure DNS:

    • Add CNAME record pointing to CloudFront distribution
  3. Invalidate Cache After Deployment:

aws cloudfront create-invalidation \
  --distribution-id YOUR_DISTRIBUTION_ID \
  --paths "/*"

Deployment Script

Create deploy.sh:

#!/bin/bash

# Build site
echo "Building site..."
hugo --minify

# Sync to S3
echo "Uploading to S3..."
aws s3 sync public/ s3://your-bucket-name \
  --delete \
  --cache-control "max-age=3600"

# Invalidate CloudFront cache
echo "Invalidating CloudFront cache..."
aws cloudfront create-invalidation \
  --distribution-id YOUR_DISTRIBUTION_ID \
  --paths "/*"

echo "Deployment complete!"

Make executable:

chmod +x deploy.sh
./deploy.sh

Custom Server Deployment

Nginx

  1. Build Site:
hugo --minify
  1. Upload to Server:
rsync -avz --delete public/ user@server:/var/www/html/
  1. Nginx Configuration:

/etc/nginx/sites-available/yoursite:

server {
    listen 80;
    listen [::]:80;
    server_name yourdomain.com www.yourdomain.com;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name yourdomain.com www.yourdomain.com;

    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;

    root /var/www/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }

    # Cache static assets
    location ~* \.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }

    # Security headers
    add_header X-Frame-Options "DENY" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header X-XSS-Protection "1; mode=block" always;

    # Gzip compression
    gzip on;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
}
  1. Enable Site:
sudo ln -s /etc/nginx/sites-available/yoursite /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Apache

Apache Configuration:

/etc/apache2/sites-available/yoursite.conf:

<VirtualHost *:80>
    ServerName yourdomain.com
    ServerAlias www.yourdomain.com
    Redirect permanent / https://yourdomain.com/
</VirtualHost>

<VirtualHost *:443>
    ServerName yourdomain.com
    ServerAlias www.yourdomain.com

    DocumentRoot /var/www/html

    SSLEngine on
    SSLCertificateFile /path/to/cert.pem
    SSLCertificateKeyFile /path/to/key.pem

    <Directory /var/www/html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>

    # Cache static files
    <FilesMatch "\.(jpg|jpeg|png|gif|ico|css|js|svg|woff|woff2)$">
        Header set Cache-Control "max-age=31536000, public, immutable"
    </FilesMatch>

    # Compression
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript
    </IfModule>
</VirtualHost>

Environment Variables

Common Variables

# Hugo version
HUGO_VERSION=0.120.0

# Environment
HUGO_ENV=production

# Enable Git info
HUGO_ENABLEGITINFO=true

# Google Analytics
HUGO_GOOGLE_ANALYTICS=G-XXXXXXXXXX

# Google Tag Manager
HUGO_GOOGLE_TAG_MANAGER=GTM-XXXXXXX

Platform-Specific

Netlify - Set in UI or netlify.toml Vercel - Set in UI or vercel.json GitHub Actions - Use secrets AWS - Use Parameter Store or Secrets Manager

Performance Optimization

Build Optimization

  1. Minify Output:
hugo --minify
  1. Enable Caching:
[caches]
  [caches.images]
    dir = ":resourceDir/_gen"
    maxAge = "1440h"
  1. Optimize Images:
    • Compress before uploading
    • Use WebP format
    • Implement lazy loading

CDN Configuration

Cache Headers:

# Static assets - 1 year
location ~* \.(jpg|png|css|js|woff2)$ {
    expires 1y;
    add_header Cache-Control "public, immutable";
}

# HTML - short cache
location ~* \.html$ {
    expires 1h;
    add_header Cache-Control "public, must-revalidate";
}

Compression

Enable gzip/brotli compression on server or CDN.

Nginx:

gzip on;
gzip_types text/plain text/css application/json application/javascript;
gzip_min_length 1000;

Performance Checklist

  • Enable minification
  • Optimize images (compress, WebP)
  • Use CDN for static assets
  • Enable HTTP/2
  • Configure caching headers
  • Enable gzip/brotli compression
  • Lazy load images
  • Minimize CSS/JS
  • Use resource hints (preload, prefetch)
  • Test with Lighthouse/PageSpeed

CI/CD Setup

GitHub Actions

Already covered in GitHub Pages section.

GitLab CI/CD

.gitlab-ci.yml:

image: registry.gitlab.com/pages/hugo/hugo_extended:latest

variables:
  GIT_SUBMODULE_STRATEGY: recursive

pages:
  script:
    - cp themes/chill-theme/package.json .
    - cp themes/chill-theme/postcss.config.js .
    - cp themes/chill-theme/tailwind.config.copy.js ./tailwind.config.js
    - npm install
    - hugo --minify
  artifacts:
    paths:
      - public
  only:
    - main

CircleCI

.circleci/config.yml:

version: 2.1

jobs:
  build:
    docker:
      - image: cibuilds/hugo:latest
    steps:
      - checkout
      - run:
          name: Install theme dependencies
          command: |
            cp themes/chill-theme/package.json .
            cp themes/chill-theme/postcss.config.js .
            cp themes/chill-theme/tailwind.config.copy.js ./tailwind.config.js
            npm install
      - run:
          name: Build site
          command: hugo --minify
      - run:
          name: Deploy
          command: |
            # Your deployment command

Post-Deployment

Verification

  1. Check Site Loads: Visit your domain
  2. Test Navigation: Click through all pages
  3. Verify Assets: Images, CSS, JS loading
  4. Check Forms: Test contact/signup forms
  5. Test Mobile: Responsive design working
  6. Check Analytics: Tracking installed correctly
  7. SSL Certificate: HTTPS working
  8. Performance: Run Lighthouse audit

Monitoring

  • Uptime Monitoring: UptimeRobot, Pingdom
  • Analytics: Google Analytics, Plausible
  • Error Tracking: Sentry, Rollbar
  • Performance: Lighthouse CI, SpeedCurve

Maintenance

  1. Regular Updates: Keep Hugo and dependencies updated
  2. Content Review: Update outdated content
  3. Backup: Regular backups of content and config
  4. Security: Monitor for vulnerabilities
  5. Performance: Regular performance audits

Troubleshooting Deployment

Build Fails

Problem: Build fails with errors

Solutions:

  • Check Hugo version matches local
  • Verify all dependencies installed
  • Check for syntax errors in config
  • Review build logs for specific errors

Assets Not Loading

Problem: CSS/JS/Images not loading

Solutions:

  • Verify baseURL is correct
  • Check asset paths are absolute (/images/...)
  • Clear browser cache
  • Check CDN/server configuration

404 Errors

Problem: Pages return 404

Solutions:

  • Verify content files exist
  • Check front matter is correct
  • Ensure draft: false
  • Check URL structure

Slow Build Times

Problem: Builds taking too long

Solutions:

  • Enable caching
  • Optimize images before build
  • Remove unused content
  • Check for infinite loops in templates

Additional Resources