Next.js 15 on Amplify Hosting compute: SSR/ISR, generateMetadata, images — no adapter needed

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.

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)

  1. Open Amplify ConsoleCreate new app → select your repository/branch.
  2. Amplify auto-detects Next.js and sets the platform to Web Compute.
  3. 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_after are not supported on Amplify compute as of today. Design for standard Node runtime SSR

8) Monorepo, subpaths, and build tips

  • Monorepo? Use applications[0].appRoot in amplify.yml and 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.production in amplify.yml as shown above. AWS Documentation
  • Images 404 / warning about unconfigured host: add the host to images.remotePatterns in next.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.

Atiqur Rahman

I am MD. Atiqur Rahman graduated from BUET and is an AWS-certified solutions architect. I have successfully achieved 6 certifications from AWS including Cloud Practitioner, Solutions Architect, SysOps Administrator, and Developer Associate. I have more than 8 years of working experience as a DevOps engineer designing complex SAAS applications.

Leave a Reply