If you’ve been waiting for a clean way to run Next.js 15 on AWS without wiring up a custom adapter or bespoke infra, Amplify Hosting’s compute platform is the happy path. You get SSR, ISR, the App Router (including generateMetadata), and next/image optimization out of the box—no adapter, no Lambda packaging tricks.
Table of Contents
Why Amplify Hosting compute for Next.js 15?
- Native support for Next.js 12 → 15, including SSR, SSG, ISR, dynamic routes, API routes, middleware, i18n, and image optimization.
- No adapter required: Connect your repository; Amplify detects Next.js and provisions compute automatically.
- Next.js 15 brings React 19 prep, caching improvements, and quality-of-life updates—Amplify supports it.
Project prerequisites
- Node 18+ (recommended for Next 15)
- A Next.js 15 app using the App Router
- A Git provider (GitHub/GitLab/Bitbucket/CodeCommit)
- An AWS account with Amplify Hosting enabled
1) Connect and deploy (no adapter)
- Open Amplify Console → Create new app → select your repository/branch.
- Amplify auto-detects Next.js and sets the platform to Web Compute.
- Choose or create the service role → Save and deploy. AWS Documentation+1
That’s it. For most apps, you don’t need an amplify.yml at all—the default detection works. If you do need to manage secrets or tweak the build, see the next section.
2) Environment variables (server & client), the safe way
By default, server components can’t see Amplify environment vars at runtime. The supported pattern is to pipe selected variables into a .env.production file during the build. Example amplify.yml
version: 1
frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
# send specific secure vars + any NEXT_PUBLIC_ vars to .env.production
- env | grep -e API_BASE_URL -e APP_ENV >> .env.production
- env | grep -e NEXT_PUBLIC_ >> .env.production
- npm run build
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- node_modules/**/*
- .next/cache/**/*
This is the recommended approach from the Amplify docs for SSR runtimes. Prefer IAM roles for AWS service access; keep secrets minimal.
3) SSR on Amplify compute (App Router)
With the App Router, SSR is the default for Server Components. A simple page that fetches data on the server:
// app/products/[id]/page.tsx
import React from 'react';
async function getProduct(id: string) {
// SSR fetch (no cache)
const res = await fetch(`${process.env.API_BASE_URL}/products/${id}`, {
cache: 'no-store',
});
if (!res.ok) throw new Error('Failed to load');
return res.json();
}
export default async function ProductPage({
params,
}: {
params: Promise<{ id: string }>
}) {
const { id } = await params;
const product = await getProduct(id);
return <pre>{JSON.stringify(product, null, 2)}</pre>;
}
4) ISR on Amplify (time-based revalidation)
Incremental Static Regeneration works via standard, time-based revalidation. You can set it per route:
// app/blog/[slug]/page.tsx
export const revalidate = 60; // re-generate at most once per minute
export default async function BlogPost({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const res = await fetch(`https://cms.example.com/posts/${slug}`, {
next: { revalidate: 60 },
});
const post = await res.json();
return <article dangerouslySetInnerHTML={{ __html: post.html }} />;
}
Note: On-Demand ISR (programmatic revalidation) is not supported on Amplify Hosting compute at this time—use time-based revalidation instead.
5) generateMetadata (SEO, social cards, canonical URLs)
Next.js 15’s generateMetadata It is fully compatible with Amplify Compute. You can fetch data and generate per-page SEO at build or request time:
// app/blog/[slug]/page.tsx
import type { Metadata, ResolvingMetadata } from 'next';
type Props = {
params: Promise<{ slug: string }>
};
export async function generateMetadata(
{ params }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
const { slug } = await params;
const res = await fetch(`https://cms.example.com/seo/${slug}`, { cache: 'force-cache' });
const data = await res.json();
const previous = await parent;
const title = `${data.title} | ${previous.title?.absolute ?? 'My Blog'}`;
return {
title,
description: data.description,
alternates: { canonical: `https://example.com/blog/${slug}` },
openGraph: {
title,
description: data.description,
images: [{ url: data.ogImageUrl, width: 1200, height: 630 }],
type: 'article',
},
};
}
6) Image optimization (next/image) on Amplify
Amplify Compute provides a built-in image optimization service for Next.js. In production, Amplify supplies Sharp for you (no extra install), and there’s a practical output size limit (~4.3 MB per optimized image). Configure remote sources via next.config.js:
// next.config.js
/** @type {import('next').NextConfig} */
module.exports = {
images: {
// allow remote images (e.g., S3 or a headless CMS)
remotePatterns: [
{ protocol: 'https', hostname: 'images.example.com' },
{ protocol: 'https', hostname: 'my-bucket.s3.amazonaws.com' },
],
},
};
You must declare external image hostnames (security + performance).
Don’t set images.unoptimized: true unless you intentionally want to skip optimization.
Amplify handles the optimization endpoint; no adapter required.
Example
import Image from 'next/image';
export default function Hero() {
return (
<Image
src="https://images.example.com/hero.jpg"
alt="Hero"
width={1600}
height={900}
priority
/>
);
}
7) Middleware & routing notes
- Middleware is supported for routing, auth checks, and locale handling.
- Edge API routes streaming and
unstable_afterare not supported on Amplify compute as of today. Design for standard Node runtime SSR
8) Monorepo, subpaths, and build tips
- Monorepo? Use
applications[0].appRootinamplify.ymland pipe env vars to the app’s own.env.production. AWS Documentation - Amplify auto-detects the framework and build settings from
package.json; you rarely need custom artifacts config for compute. AWS Documentation - For faster cold-starts, prefer ISR and caching where acceptable; use
cache: 'no-store'only when you truly need it.
9) Troubleshooting checklist
- Blank page after “successful” deploy: ensure Amplify detected Web Compute and “Next.js — SSR” (reconnect the branch if needed).
- Env vars not appearing at runtime: pipe them to
.env.productioninamplify.ymlas shown above. AWS Documentation - Images 404 / warning about unconfigured host: add the host to
images.remotePatternsinnext.config.js. Next.js - On-demand revalidation: not supported—switch to time-based ISR (
revalidate).
10) Minimal starter scripts
package.json (scripts)
{
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
}
}
Optional amplify.yml (only if you need to wire env vars or customize the build):
version: 1
frontend:
phases:
preBuild:
commands:
- npm ci
build:
commands:
- env | grep -e API_BASE_URL -e APP_ENV >> .env.production
- env | grep -e NEXT_PUBLIC_ >> .env.production
- npm run build
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- node_modules/**/*
- .next/cache/**/*
Final thoughts
With Next.js 15 + Amplify Hosting compute, you can ship SSR, ISR, generateMetadata, and image optimization without maintaining your own adapter or infrastructure. Keep revalidation time-based, declare your image domains, and pipe only the env vars you truly need. The rest is just push → build → global.
