Michał Miler
Michał Miler
Senior Software Engineer

Next.js 16 SSG on AWS Amplify: A Practical, Cost-Effective Deployment Guide

Jan 30, 20265 min read

Deploying Next.js Static Site Generation (SSG) applications to AWS Amplify can be challenging without the right configuration. While Vercel offers a seamless experience, AWS Amplify may provide a cost-effective alternative with up to 96% savings for smaller sites and 20-30% for medium-traffic applications. In this comprehensive guide, we'll walk through the exact steps to successfully deploy your Next.js 16 SSG site to AWS Amplify.

Why AWS Amplify for SSG?

AWS Amplify is particularly attractive for SSG deployments because:

  • Lower costs than Vercel, especially for commercial use (see our detailed cost comparison)
  • No per-seat pricing for team collaboration
  • Generous free tier for the first 12 months
  • Standard AWS infrastructure (S3 + CloudFront) with no vendor lock-in

Note on static export limitations: Static Site Generation pre-generates all pages at build time. This means no server-side rendering (SSR), no Incremental Static Regeneration (ISR), and no API routes. If you need these features, you'll need a different deployment strategy.

Prerequisites

Before we begin, ensure you have:

  • Node.js 22.x or later installed
  • Next.js 16 project using App Router
  • An AWS account (free tier eligible for 12 months)
  • Git repository (GitHub, GitLab, Bitbucket, or AWS CodeCommit)
  • Basic familiarity with Next.js App Router

Step 1: Configure Next.js 16 for SSG

Update next.config.ts

Create or modify your next.config.ts file to enable static export:

import type { NextConfig } from "next"; const nextConfig: NextConfig = { output: "export", images: { unoptimized: true, }, }; export default nextConfig;

Key Points:

  • output: 'export' disables the Next.js runtime and enforces a full static export. This ensures your site can be deployed as plain static HTML/CSS/JS.
  • images.unoptimized: true disables Next.js Image Optimization API (required for static export)

Handle Image Optimization

Since Next.js Image Optimization doesn't work with static exports, choose one of these options:

Option 1: Unoptimized images (simplest for testing)

import Image from "next/image"; <Image src="/images/photo.jpg" width={500} height={300} alt="Description" />;

Option 2: Standard HTML img tags

<img src="/images/photo.jpg" width={500} height={300} alt="Description" />

Option 3: Third-party CDN (recommended for production)

Use services like Cloudflare Images, Cloudinary, or imgix. See our guide on optimizing S3 images with Cloudflare Images.

const imageLoader = ({ src, width, quality, }: { src: string; width: number; quality?: number; }) => { return `https://your-cdn.com/${src}?w=${width}&q=${quality || 75}`; }; <Image loader={imageLoader} src="photo.jpg" width={500} height={300} alt="Description" />;

Verify SSG Compatibility

Ensure your project doesn't use these incompatible features:

Cannot use:

  • Route Handlers (API Routes) - require server runtime
  • Server-Side Rendering (SSR) - e.g., cache: 'no-store' in fetches
  • Incremental Static Regeneration (ISR) - revalidate property
  • Dynamic data without generateStaticParams — including any data fetched from “dynamic APIs” that depend on runtime values (see Next.js guide on dynamic rendering)

Must implement:

  • All dynamic routes need generateStaticParams to pre-generate pages
  • Use cache: 'force-cache' for data fetching at build time

Example for dynamic routes:

// app/blog/[slug]/page.tsx export async function generateStaticParams() { return [{ slug: "first-post" }, { slug: "second-post" }]; } export default async function BlogPost({ params, }: { params: Promise<{ slug: string }>; }) { const { slug } = await params; return <h1>Blog Post: {slug}</h1>; }

Test Locally

Verify your static export works:

npm run build npx serve out

Visit http://localhost:3000 to ensure everything renders correctly.

Step 2: Deploy to AWS Amplify

Push to Git

git add . git commit -m "Configure Next.js for SSG deployment" git push origin main

Access AWS Amplify Console

  1. Log into AWS Console
  2. Search for "Amplify" in the services search bar
  3. Click "Get Started" under "Amplify Hosting"

Connect Your Repository

  1. Select your Git provider (GitHub, GitLab, Bitbucket, or AWS CodeCommit)
  2. Authorize AWS Amplify to access your repositories
  3. Choose the repository and branch to deploy
  4. Click "Next"

Configure Build Settings

Amplify should auto-detect Next.js, but verify your amplify.yml:

version: 1 frontend: phases: preBuild: commands: - npm ci build: commands: - npm run build artifacts: baseDirectory: out files: - "**/*" cache: paths: - node_modules/**/*

Critical settings:

  • baseDirectory: out - Next.js static export directory
  • npm ci - Consistent, reproducible builds
  • Cache node_modules for faster builds

Add Environment Variables (Optional)

If your app needs environment variables, add them in "Advanced settings":

NEXT_PUBLIC_API_URL=https://api.example.com NEXT_PUBLIC_ANALYTICS_ID=G-XXXXXXXXXX

Remember: Only NEXT_PUBLIC_* variables are accessible in the browser. Server-side variables are available during build time only.

Deploy

  1. Review settings
  2. Click "Save and deploy"
  3. Monitor the build progress (typically 3-5 minutes)

Once complete, you'll get a URL like: https://[branch].[app-id].amplifyapp.com

Step 3: Configure Redirects & Routing

Fix 404 Pages

Configure redirects in Amplify console under "Rewrites and redirects":

Rule 1: Custom 404 page

Source: </^[^.]+$|\\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|woff2|ttf|map|json|webp)$)([^.]+$)/> Target: /404.html Status: 404

Rule 2: Client-side routing fallback

Source: /<*> Target: /index.html Status: 200 (Rewrite)

Important: Place Rule 2 last - Amplify processes rules in order.

Step 4: Handle Common Considerations

Environment Variables

Client Components (with "use client"):

  • Can only access NEXT_PUBLIC_* variables
  • Variables are embedded in the build output

Server Components (default):

  • Can access all environment variables at build time
  • Never expose secrets in NEXT_PUBLIC_* variables

Forms and Interactive Features

SSG sites need external services for dynamic functionality:

  • Forms: Formspree, Web3Forms, AWS Lambda
  • Search: FlexSearch, Fuse.js, Algolia, Meilisearch
  • Comments: Giscus, Utterances, Disqus
  • Authentication: Clerk, Auth0, AWS Cognito

Next.js 16 App Router Features

Works perfectly with SSG:

  • Metadata API
  • Route Groups
  • Loading and Error UI
  • Server Components (data fetched at build time)

Requires pre-generation:

  • Dynamic routes (use generateStaticParams)
  • Parallel and Intercepting Routes (all combinations must be pre-generated)

Troubleshooting Common Issues

Build Fails: "Output directory not found"

Fix: Verify amplify.yml has baseDirectory: out and next.config.ts has output: 'export'

Images Not Loading

Fix: Ensure images.unoptimized: true in config. Images should be in public/ directory and referenced without the public prefix.

Blank Page After Deployment

Fix: Check browser console for errors. Usually means:

  • Missing NEXT_PUBLIC_ prefix on environment variables
  • Client-side JavaScript error
  • Incorrect build output

Dynamic Routes Return 404

Fix:

  1. Implement generateStaticParams for all dynamic routes
  2. Configure redirect rules in Amplify console

Environment Variables Not Working

Fix:

  • Client-side variables must use NEXT_PUBLIC_ prefix
  • Set in Amplify Console under "Environment variables"
  • Rebuild after adding new variables

When NOT to Use This Approach

Consider alternatives if you need:

  • Incremental Static Regeneration (ISR): Requires Node.js server
  • Server-Side Rendering (SSR): Real-time, per-request rendering
  • API Routes: Need serverless functions
  • On-demand Revalidation: Dynamic content updates without rebuilds
  • Edge Middleware: Complex routing logic at the edge

For these use cases, consider Vercel, AWS Amplify with SSR configuration, or AWS App Runner/ECS.

Next Steps

After deployment:

  1. Add custom domain: In Amplify console under "Domain management"
  2. Set up monitoring: Use CloudWatch for build and deployment alerts
  3. Configure preview deployments: For pull requests and feature branches
  4. Optimize costs: Review bandwidth usage and optimize images
  5. Test thoroughly: Verify all pages and features work as expected

Conclusion

AWS Amplify provides a cost-effective platform for deploying Next.js 16 SSG applications with proper configuration. The key is understanding SSG limitations, configuring Next.js correctly, and setting up Amplify's build and routing properly.

While the setup requires more configuration than Vercel, the cost savings (up to 96% for small sites) and lack of per-seat pricing make it an excellent choice for businesses looking to optimize their hosting costs without sacrificing performance or reliability.

RELATED POSTS
Bartłomiej Gałęzowski
Bartłomiej Gałęzowski
Senior Software Engineer

Secure RDS Access Without Bastion Hosts: Using ECS Containers and SSM

Feb 04, 20264 min read
Article image
Daniel Kraszewski
Daniel Kraszewski
Head of Engineering

Architecting and Operating Geospatial Workflows with Dagster

Jan 27, 20269 min read
Article image
Paweł Swiridow
Paweł Swiridow
Senior Software Engineer

Decoupling Ingress with TargetGroupBinding in EKS

Jan 07, 20264 min read
Article image