# 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](#building-for-production) - [Platform Deployment Guides](#platform-deployment-guides) - [Netlify](#netlify) - [Vercel](#vercel) - [GitHub Pages](#github-pages) - [Cloudflare Pages](#cloudflare-pages) - [AWS S3 + CloudFront](#aws-s3--cloudfront) - [Custom Server Deployment](#custom-server-deployment) - [Environment Variables](#environment-variables) - [Performance Optimization](#performance-optimization) - [CI/CD Setup](#cicd-setup) - [Post-Deployment](#post-deployment) ## Building for Production Before deploying, build your site for production. ### Build Command ```bash # 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**: ```toml # hugo.toml baseURL = "http://localhost:1313/" ``` **Production** (update before deploying): ```toml # 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**: ```bash git add . git commit -m "Ready for deployment" git push origin main ``` 2. **Connect to Netlify**: - Visit [netlify.com](https://netlify.com) - Click "Add new site" → "Import an existing project" - Choose Git provider (GitHub, GitLab, Bitbucket) - Select your repository 3. **Configure Build Settings**: - **Build command**: `hugo --minify` - **Publish directory**: `public` - **Production branch**: `main` 4. **Environment Variables** (click "Show advanced"): ``` HUGO_VERSION = 0.120.0 HUGO_ENV = production ``` 5. **Deploy**: Click "Deploy site" #### Netlify Configuration File Create `netlify.toml` in project root: ```toml [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 settings** → **Domain 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): ```bash npm install -g vercel ``` 2. **Deploy via CLI**: ```bash vercel ``` Or deploy via web interface: 3. **Connect Repository**: - Visit [vercel.com](https://vercel.com) - Click "Add New" → "Project" - Import your Git repository 4. **Configure Project**: - **Framework Preset**: Hugo - **Build Command**: `hugo --minify` - **Output Directory**: `public` - **Install Command**: Leave empty 5. **Environment Variables**: ``` HUGO_VERSION=0.120.0 ``` 6. **Deploy**: Click "Deploy" #### Vercel Configuration Create `vercel.json`: ```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**: ```toml # hugo.toml baseURL = "https://username.github.io/" # or for project site: baseURL = "https://username.github.io/repository-name/" ``` 3. **Create GitHub Action**: `.github/workflows/hugo.yml`: ```yaml 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 ``` 4. **Enable GitHub Pages**: - Go to repository **Settings** → **Pages** - **Source**: GitHub Actions - Save 5. **Push and Deploy**: ```bash 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**: - Visit [pages.cloudflare.com](https://pages.cloudflare.com) - Click "Create a project" - Connect your Git account - Select 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 ``` 4. **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**: ```bash aws s3 mb s3://your-bucket-name --region us-east-1 ``` 2. **Enable Static Website Hosting**: ```bash aws s3 website s3://your-bucket-name \ --index-document index.html \ --error-document 404.html ``` 3. **Set Bucket Policy**: Create `bucket-policy.json`: ```json { "Version": "2012-10-17", "Statement": [ { "Sid": "PublicReadGetObject", "Effect": "Allow", "Principal": "*", "Action": "s3:GetObject", "Resource": "arn:aws:s3:::your-bucket-name/*" } ] } ``` Apply: ```bash aws s3api put-bucket-policy \ --bucket your-bucket-name \ --policy file://bucket-policy.json ``` 4. **Deploy Site**: ```bash 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**: ```bash aws cloudfront create-invalidation \ --distribution-id YOUR_DISTRIBUTION_ID \ --paths "/*" ``` #### Deployment Script Create `deploy.sh`: ```bash #!/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: ```bash chmod +x deploy.sh ./deploy.sh ``` ## Custom Server Deployment ### Nginx 1. **Build Site**: ```bash hugo --minify ``` 2. **Upload to Server**: ```bash rsync -avz --delete public/ user@server:/var/www/html/ ``` 3. **Nginx Configuration**: `/etc/nginx/sites-available/yoursite`: ```nginx 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; } ``` 4. **Enable Site**: ```bash 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`: ```apache ServerName yourdomain.com ServerAlias www.yourdomain.com Redirect permanent / https://yourdomain.com/ ServerName yourdomain.com ServerAlias www.yourdomain.com DocumentRoot /var/www/html SSLEngine on SSLCertificateFile /path/to/cert.pem SSLCertificateKeyFile /path/to/key.pem Options -Indexes +FollowSymLinks AllowOverride All Require all granted # Cache static files Header set Cache-Control "max-age=31536000, public, immutable" # Compression AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript ``` ## Environment Variables ### Common Variables ```bash # 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**: ```bash hugo --minify ``` 2. **Enable Caching**: ```toml [caches] [caches.images] dir = ":resourceDir/_gen" maxAge = "1440h" ``` 3. **Optimize Images**: - Compress before uploading - Use WebP format - Implement lazy loading ### CDN Configuration **Cache Headers**: ```nginx # 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**: ```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](#github-pages) section. ### GitLab CI/CD `.gitlab-ci.yml`: ```yaml 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`: ```yaml 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 ## Related Documentation - [INSTALLATION.md](INSTALLATION.md) - Installation guide - [CONFIGURATION.md](CONFIGURATION.md) - Configuration options - [TROUBLESHOOTING.md](TROUBLESHOOTING.md) - Common issues - [Performance Optimization](https://gohugo.io/troubleshooting/build-performance/) ## Additional Resources - [Netlify Docs](https://docs.netlify.com/) - [Vercel Docs](https://vercel.com/docs) - [GitHub Pages Docs](https://docs.github.com/en/pages) - [Cloudflare Pages Docs](https://developers.cloudflare.com/pages) - [AWS S3 Static Hosting](https://docs.aws.amazon.com/AmazonS3/latest/userguide/WebsiteHosting.html)