How to Fix: Dynamic Routes not displaying intended page and displaying home page instead
Why a Next.js dynamic route shows the home page instead of the intended page
If every URL renders your homepage, the problem usually is not the link itself. It is almost always a routing mismatch between the path you are visiting and how the dynamic route is defined in Next.js. In this issue, the app is falling back to the wrong route, so requests that should hit a dynamic page are being handled by the homepage instead.
You can review the reproduction project here: GitHub reproduction repository.
Understanding the Root Cause
In Next.js, dynamic routes only work when the file-system routing structure exactly matches the URL shape being requested. If the app is using the App Router, a dynamic segment must be defined with a folder like app/[slug]/page.js. If it is using the Pages Router, it must be a file like pages/[slug].js.
When a route is defined incorrectly, or when the homepage route is effectively catching the request first, Next.js can render / instead of the intended page. This often happens for one of these reasons:
- The dynamic route file is placed in the wrong directory.
- The app mixes App Router and Pages Router conventions incorrectly.
- The link points to a path that does not match the dynamic segment name or nesting structure.
- A rewrite, redirect, or fallback configuration sends unmatched paths back to the homepage.
- The dynamic page exists, but it does not export the expected component or params handling for that router type.
From the symptoms in this issue, the important technical takeaway is this: Next.js is not resolving the requested URL to the dynamic route module, so the homepage becomes the rendered output.
Step-by-Step Solution
The fix is to make the route structure explicit and ensure the requested URL maps to the correct dynamic route file.
1. Confirm which router your project is using
If your project uses an app directory, use App Router conventions. If it uses a pages directory for route definitions, use Pages Router conventions. Do not implement the same route ambiguously across both without a clear reason.
2. Define the dynamic route correctly
For the App Router, the structure should look like this:
app/
page.js
[slug]/
page.js
Example:
// app/[slug]/page.js
export default function DynamicPage({ params }) {
return <h1>Slug: {params.slug}</h1>;
}
For the Pages Router, the structure should look like this:
pages/
index.js
[slug].js
Example:
// pages/[slug].js
import { useRouter } from 'next/router';
export default function DynamicPage() {
const router = useRouter();
const { slug } = router.query;
return <h1>Slug: {slug}</h1>;
}
3. Make sure your links match the route shape
If the dynamic route is [slug], then your links must point to paths like /about, /product-1, or any other single segment.
import Link from 'next/link';
export default function HomePage() {
return (
<div>
<Link href="/test-page">Go to test page</Link>
</div>
);
}
If your actual URL includes nested segments such as /blog/test-page, then the route must also be nested:
app/
blog/
[slug]/
page.js
or:
pages/
blog/
[slug].js
4. Check for homepage rewrites or redirects
If you have a next.config.js with a rewrite sending unknown routes to /, that will mask routing mistakes and make it look like dynamic routing is broken.
// next.config.js
module.exports = {
async rewrites() {
return [
// Be careful with broad catch-all rewrites like this
// {
// source: '/:path*',
// destination: '/',
// }
];
},
};
Remove or narrow any rewrite that unintentionally sends dynamic URLs back to the homepage.
5. If using App Router, access params the correct way
In the App Router, route params are passed into the page component. Do not use useRouter() from the Pages Router pattern inside a server component page.
// Correct for app/[slug]/page.js
export default function Page({ params }) {
return <div>Current slug: {params.slug}</div>;
}
6. Restart the dev server after moving route files
When changing route structure, especially between app and pages, restart the development server to force Next.js to rebuild the route manifest.
npm run dev
7. Verify the route manifest behavior locally
Test these pages explicitly:
/should render the homepage./test-pageshould render the dynamic page if using[slug].- Any nested path should only work if you created a matching nested route.
If /test-page still shows the homepage, then the dynamic route is either not being registered or a rewrite is intercepting it.
Recommended corrected implementation
If the goal is to support single-segment dynamic pages, a minimal App Router setup would be:
app/page.js
app/[slug]/page.js
// app/page.js
import Link from 'next/link';
export default function Home() {
return (
<main>
<h1>Home</h1>
<Link href="/my-page">Open dynamic page</Link>
</main>
);
}
// app/[slug]/page.js
export default function DynamicPage({ params }) {
return (
<main>
<h1>Dynamic route</h1>
<p>Slug: {params.slug}</p>
</main>
);
}
Equivalent Pages Router setup:
pages/index.js
pages/[slug].js
// pages/index.js
import Link from 'next/link';
export default function Home() {
return (
<main>
<h1>Home</h1>
<Link href="/my-page">Open dynamic page</Link>
</main>
);
}
// pages/[slug].js
import { useRouter } from 'next/router';
export default function DynamicPage() {
const { query } = useRouter();
return (
<main>
<h1>Dynamic route</h1>
<p>Slug: {query.slug}</p>
</main>
);
}
Common Edge Cases
- Catch-all routes overriding behavior: A route like
[...slug]can absorb paths you expected to be handled by a simpler route. - Conflicting app and pages routes: If both routers define similar paths, debugging becomes confusing. Keep the ownership of each route clear.
- Wrong nesting level: Visiting
/blog/post-1will not match[slug]at the root level. It needs a nested route. - Static export limitations: If the app is exported statically, some dynamic behavior requires additional configuration such as generated params or fallback handling.
- Case sensitivity and file naming: Route segment names and folder structure must be exact. A misplaced
page.jsor incorrect folder name breaks matching. - Middleware or rewrites: Middleware that rewrites requests to
/can create the exact symptom described in this issue.
FAQ
Why does the browser URL change correctly, but the homepage still renders?
Because the client navigation succeeded, but the requested path did not resolve to the intended route component. A rewrite, route mismatch, or incorrect file structure is usually responsible.
Should I use useRouter() or params for dynamic routes?
Use params in the App Router page component. Use useRouter() in the Pages Router. Mixing them often leads to broken assumptions during routing.
How do I know if a rewrite is causing the issue?
Check next.config.js and any middleware. If a broad rule redirects or rewrites unknown paths to /, your dynamic route may never get a chance to render.
The core fix for this GitHub issue is simple: make the filesystem route match the URL exactly, remove any rewrite that sends dynamic paths to the homepage, and use the correct router API for your Next.js setup. Once those are aligned, the dynamic page will render as expected instead of falling back to home.