aws-amplify / aws-amplify/amplify-hosting

Incorrect Redirect Behavior for Dynamic Routes in Next.js 14 (Pages Router) App on AWS Amplify

Open
#4,072 1 comment 0 reactions 0 assignees View on GitHub
pending-triage
Dominant language
Dockerfile
Stars
481
Forks
123
PR merge metrics
No merged PRs in 30d

Description

### Environment information

```plain text
Framework: Next.js 14

Routing system: Pages Router (not App Router)

Build output: .next directory, no index.html

Hosting: AWS Amplify

Build commands:

version: 1
applications:
- appRoot: .
frontend:
phases:
preBuild:
commands:
- nvm install 20.9.0
- nvm use 20.9.0
- node -v
- npm ci
build:
commands:
- npm ci
- npm run build
- rm -rf node_modules/canvas
- node scripts/generate-amplify-rewrites.js
- echo "AMPLIFY_APP_ID=$AMPLIFY_APP_ID"
- node scripts/update-amplify-rewrites.js
- npm run postbuild || echo "no postbuild"
- rm -rf .next/cache
artifacts:
baseDirectory: .next
files:
- '**/*'
cache:
paths:
- node_modules/**/*
customHeaders:
- pattern: '**/*'
headers:
- key: 'Cache-Control'
value: 'public, max-age=0, must-revalidate'
```

### Describe the bug

Hi,

I’m experiencing an issue with dynamic routes not resolving correctly in my Next.js 14 app hosted on AWS Amplify.

For example:

✅ Expected behavior:
Visiting the short link

https://abc.amplifyapp.com/share?id=E2EBAF72ED0

should redirect to

https://abc.amplifyapp.com/proposals/8f723ad7-e14f-4ca9-ad58-6fa4b60abcec/preview?insurance_type=comprehensive

❌ Actual behavior:
Instead, it redirects to

https://abc.amplifyapp.com/proposals?insurance_type=comprehensive

The dynamic route segment (/8f723ad7-e14f-4ca9-ad58-6fa4b60abcec/preview) is being truncated or dropped by Amplify’s static hosting layer, even though the route exists and works perfectly in local Next.js development.

**What I’ve already tried:**

Explicitly added rewrite rules like:

{
"source": "/proposals/:proposal_id/preview",
"status": "200",
"target": "/proposals/:proposal_id/preview"
},
{
"source": "/proposals/:proposal_id/preview/index",
"status": "200",
"target": "/proposals/:proposal_id/preview/index"
}

Verified that the dynamic route /pages/proposals/[proposal_id]/preview/index.js exists.

Confirmed that the same route structure works correctly in local dev and static export builds.

**Issue Summary:**
Even after adding specific rewrites, Amplify Hosting appears to interpret /proposals/:proposal_id/preview as /proposals, discarding the dynamic segments and query parameters.

**Additional Concern:**

Currently, I’m forced to manually generate and include rewrites for every static and nested path in the app.
This includes dozens of entries like:

{
"source": "/car-insurance",
"status": "200",
"target": "/car-insurance"
},
{
"source": "/life-insurance",
"status": "200",
"target": "/life-insurance"
},
...

This seems unnecessary because:

My app uses **Next.js 14 with the Pages Router** — it doesn’t generate a traditional index.html per page.

Next.js automatically handles routing via pages/ structure and dynamic route segments like [proposal_id] or [query].js.

On most platforms (Vercel, Netlify, etc.), these routes resolve automatically without defining every rewrite manually.

So I’d like to understand **why Amplify requires manually defining each path** instead of automatically serving the correct Next.js route.

### Reproduction steps

**Request:**

Please confirm how to properly handle Next.js dynamic routes ([id], [slug], etc.) in Amplify Hosting.

Is there a recommended wildcard rewrite pattern or regex-based rule to support all Next.js routes without defining each one manually?

Can you confirm if the lack of index.html (in Next.js 14 pages output) affects Amplify’s static route resolution?

Contributor guide

Open the contributing guide

Research direction

Start with pages/proposals/[proposal_id]/preview/index.js and the scripts/generate-amplify-rewrites.js and scripts/update-amplify-rewrites.js entry points, then inspect the Amplify build configuration. Reproduce the /share?id=... request and compare its generated rewrite with the expected dynamic destination. Done means the proposal ID, preview path, and query parameter are preserved without manually listing every route.

Written by the indexing model from the issue text.

Assessment

Tech stack
aws, nextjs
Domain
cloud, web-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.