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
- Platform Deployment Guides
- Custom Server Deployment
- Environment Variables
- Performance Optimization
- CI/CD Setup
- Post-Deployment
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
baseURLinhugo.tomlto production URL - Remove draft posts (
draft: falseor 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
- Push to Git:
git add .
git commit -m "Ready for deployment"
git push origin main
-
Connect to Netlify:
- Visit netlify.com
- Click "Add new site" → "Import an existing project"
- Choose Git provider (GitHub, GitLab, Bitbucket)
- Select your repository
-
Configure Build Settings:
- Build command:
hugo --minify - Publish directory:
public - Production branch:
main
- Build command:
-
Environment Variables (click "Show advanced"):
HUGO_VERSION = 0.120.0 HUGO_ENV = production -
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
- Go to Site settings → Domain management
- Click "Add custom domain"
- Enter your domain:
yourdomain.com - Configure DNS:
- A Record: Point to Netlify's load balancer IP
- CNAME: Point
wwwto[your-site].netlify.app
- Enable HTTPS (automatic with Let's Encrypt)
Vercel
Vercel provides zero-configuration deployments with global CDN.
Deploy to Vercel
- Install Vercel CLI (optional):
npm install -g vercel
- Deploy via CLI:
vercel
Or deploy via web interface:
-
Connect Repository:
- Visit vercel.com
- Click "Add New" → "Project"
- Import your Git repository
-
Configure Project:
- Framework Preset: Hugo
- Build Command:
hugo --minify - Output Directory:
public - Install Command: Leave empty
-
Environment Variables:
HUGO_VERSION=0.120.0
- 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
-
Create Repository:
- Name:
username.github.io(user site) - Or:
repository-name(project site)
- Name:
-
Update Base URL:
# hugo.toml
baseURL = "https://username.github.io/"
# or for project site:
baseURL = "https://username.github.io/repository-name/"
- 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
-
Enable GitHub Pages:
- Go to repository Settings → Pages
- Source: GitHub Actions
- Save
-
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
-
Connect Repository:
- Visit pages.cloudflare.com
- Click "Create a project"
- Connect your Git account
- Select repository
-
Configure Build:
- Framework preset: Hugo
- Build command:
hugo --minify - Build output directory:
public - Root directory: Leave blank
-
Environment Variables:
HUGO_VERSION=0.120.0
- Deploy: Click "Save and Deploy"
Custom Domain
- Go to project → Custom domains
- Add your domain
- Configure DNS (Cloudflare handles this automatically)
- SSL/TLS is automatic
AWS S3 + CloudFront
Enterprise-grade hosting with AWS infrastructure.
S3 Setup
- Create S3 Bucket:
aws s3 mb s3://your-bucket-name --region us-east-1
- Enable Static Website Hosting:
aws s3 website s3://your-bucket-name \
--index-document index.html \
--error-document 404.html
- 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
- Deploy Site:
hugo --minify
aws s3 sync public/ s3://your-bucket-name --delete
CloudFront Setup
-
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
-
Configure DNS:
- Add CNAME record pointing to CloudFront distribution
-
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
- Build Site:
hugo --minify
- Upload to Server:
rsync -avz --delete public/ user@server:/var/www/html/
- 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;
}
- 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
- Minify Output:
hugo --minify
- Enable Caching:
[caches]
[caches.images]
dir = ":resourceDir/_gen"
maxAge = "1440h"
- 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
- Check Site Loads: Visit your domain
- Test Navigation: Click through all pages
- Verify Assets: Images, CSS, JS loading
- Check Forms: Test contact/signup forms
- Test Mobile: Responsive design working
- Check Analytics: Tracking installed correctly
- SSL Certificate: HTTPS working
- Performance: Run Lighthouse audit
Monitoring
- Uptime Monitoring: UptimeRobot, Pingdom
- Analytics: Google Analytics, Plausible
- Error Tracking: Sentry, Rollbar
- Performance: Lighthouse CI, SpeedCurve
Maintenance
- Regular Updates: Keep Hugo and dependencies updated
- Content Review: Update outdated content
- Backup: Regular backups of content and config
- Security: Monitor for vulnerabilities
- 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
baseURLis 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
Related Documentation
- INSTALLATION.md - Installation guide
- CONFIGURATION.md - Configuration options
- TROUBLESHOOTING.md - Common issues
- Performance Optimization