Skip to content

Next.js - Routing

Next.js uses a file-system based router within the app directory. Folders define route segments, and page.tsx (or .js, .jsx) files within those folders make the route publicly accessible.

  • Root Route: app/page.tsx maps to /.
  • Nested Routes: Folders create nested paths. app/dashboard/settings/page.tsx maps to /dashboard/settings.
  • Dynamic Segments: Use square brackets [] to create routes that match dynamic values. app/blog/[slug]/page.tsx maps to /blog/:slug (e.g., /blog/hello-world, /blog/another-post). The slug value is passed as a prop to the page component.
  • Catch-all Segments: Use brackets with three dots [...folderName] to match multiple subsequent segments. app/shop/[...filters]/page.tsx matches /shop/a, /shop/a/b, /shop/a/b/c, etc.
  • Optional Catch-all Segments: Use double square brackets [[...folderName]] to match zero or more segments. app/docs/[[...slug]]/page.tsx matches /docs, /docs/getting-started, /docs/a/b, etc.

Client-side navigation (moving between pages without a full browser refresh) is handled by the Link component imported from next/link.

  • href: The path to navigate to (e.g., /dashboard, /blog/my-first-post). This should match the route structure defined in your app directory.

Example Link usage:

import Link from 'next/link';
function Navigation() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/about">About Us</Link>
<Link href="/blog/latest-news">Latest News</Link>
</nav>
);
}

With the App Router, pages are React Server Components by default. This allows you to fetch data directly within the component using async/await.

Let’s modify the home page to fetch some data, for example, stars for the Next.js repository on GitHub.

Update app/page.tsx:

app/page.tsx
import Link from 'next/link';
async function getRepoStars() {
try {
const res = await fetch('https://api.github.com/repos/vercel/next.js', {
// Optional: Improve performance and reduce requests during development/build
next: { revalidate: 60 } // Revalidate data at most once per minute
});
if (!res.ok) {
// Handle HTTP errors
throw new Error(`Failed to fetch: ${res.status}`);
}
const json = await res.json();
return json.stargazers_count;
} catch (error) {
console.error('Error fetching repo stars:', error);
return 'N/A'; // Provide a fallback value
}
}
export default async function HomePage() {
const stars = await getRepoStars();
return (
<main>
<h1>Welcome to Next.js!</h1>
<p>Explore our content:</p>
<Link href="/posts">Go to Posts</Link>
<br />
<p>Next.js GitHub Stars: {stars}</p>
</main>
);
}

Note: Data fetching in Server Components happens on the server. The fetch call is executed server-side, and the resulting HTML is sent to the browser. Next.js extends the native fetch API with options for caching and revalidation (next: { revalidate: ... }).

For more complex data fetching patterns or fetching data on the client-side, refer to the official Next.js Data Fetching documentation.

If your server isn’t running, start it:

npm run dev

Open http://localhost:3000 in your browser. You should now see the home page displaying the number of GitHub stars for the Next.js repository (or ‘N/A’ if the fetch failed).

Navigating to the /posts page using the link should still work seamlessly.