Routing is one of the core features that make Next.js such a powerful framework. Unlike traditional React apps—where you must manually set up routing libraries like React Router Next.js provides a built-in file-based router that makes navigation extremely easy.
1. What is File-Based Routing in Next.js?
Next.js automatically creates routes based on the file structure inside your app/ directory.
For example:
app/
+- page.tsx ? "/"
+- about/
¦ +- page.tsx ? "/about"
+- blog/
+- page.tsx ? "/blog"
Each folder becomes a route, and each page.tsx file becomes the page rendered at that route.
No need to configure anything manually, Next.js handles it for you.
2. Creating Your First Page
Inside the app/ directory:
app/page.tsx
// app/page.tsx
export default function HomePage() {
return <h1>Welcome to the Home Page</h1>;
}
That's it! Visiting / in your browser will render this page.
Creating Another Page
// app/about/page.tsx:
export default function AboutPage() {
return <h1>About Us</h1>;
}
Now visiting /about displays the content.
3. Nested Routes
Next.js supports nested folders to create nested routes.
Example structure:
app/
+- dashboard/
+- page.tsx ? "/dashboard"
+- settings/
+- page.tsx ? "/dashboard/settings"
// app/dashboard/page.tsx
export default function Dashboard() {
return <h1>Dashboard Overview</h1>;
}
// app/dashboard/settings/page.tsx
export default function DashboardSettings() {
return <h1>Dashboard Settings</h1>;
}
This is perfect for multi-page dashboards, admin panels, and SaaS apps.
4. Navigating Between Pages
To navigate in a Next.js app, always use next/link.
Example:
// app/navbar.tsx
import Link from "next/link";
export default function NavBar() {
return (
<nav>
<Link href="/">Home</Link>
<Link href="/about">About</Link>
<Link href="/dashboard">Dashboard</Link>
</nav>
);
}
// app/page.tsx
import NavBar from "./navbar";
export default function HomePage() {
return <><Navbar /><h1>Welcome to the Home Page</h1></>;
}
- Client-side navigation (fast)
- Prefetching (Next.js loads pages before visiting them)
- Smooth user experience
5. Dynamic Routes
Dynamic routes are extremely powerful when you need pages like:
- /blog/how-nextjs-works
- /products/123
- /users/alan-joy
To create a dynamic route, use [param] in the folder name.
Example structure:
app/
+- blog/
+- [slug]/
+- page.tsx ? "/blog/:slug"
// app/blog/[slug]/page.tsx
interface Props {
params: { slug: string };
}
export default function BlogPost({ params }: Props) {
return <h1>Blog Article: {params.slug}</h1>;
}
Visits:
- /blog/nextjs-routing
- /blog/react-server-components
And each shows different content.
6. Catch-All Routes ([...slug])
Use this when the number of segments is unknown:
Examples:
- /docs/getting-started/installation
- /docs/api/v1/auth/login
Folder structure:
app/
+- docs/
+- [...slug]/page.tsx
// app/docs/[...slug]/page.tsx
export default function DocsPage({ params }: { params: { slug: string[] } }) {
return (
<>
<h1>Docs Page</h1>
<p>Path: {params.slug.join(" / ")}</p>
</>
);
}
7. Layouts (App Router Feature)
Layouts allow you to share UI across multiple pages like navbars, sidebars, or footers.
app/
+- layout.tsx
+- dashboard/
+- layout.tsx
+- page.tsx
Global layout (applies to all routes)
// app/layout.tsx
export default function RootLayout({ children }) {
return (
<html>
<body>
<header>My App Header</header>
{children}
</body>
</html>
);
}
Dashboard layout (applies to /dashboard and nested pages)
// app/dashboard/layout.tsx
export default function DashboardLayout({ children }) {
return (
<section>
<aside>Sidebar</aside>
<main>{children}</main>
</section>
);
}
Layouts in Next.js 13+ make building complex UIs much easier.
8. Route Groups ( )
Route groups help organize the folder structure without affecting the URL.
Example:
app/
+- (marketing)/
+- home/
+- features/
+- (dashboard)/
+- profile/
+- settings/
Even though folders are grouped, URLs remain:
- /home
- /features
- /profile
- /settings
Why use route groups?
- Organize code
- Separate public vs. private routes
- Keep clean URL structure
9. API Routes
Next.js can also act as a backend using API routes.
Example:
// app/api/hello/route.ts
export async function GET() {
return Response.json({ message: "Hello from API" });
}
Access it at:
/api/hello
This is great for:
- Form submissions
- Auth endpoints
- Webhooks
- Server-side utilities
10. Client Components vs Server Components
In the app/ router:
- Pages and layouts default to Server Components
- Use "use client" when you need client-side code (hooks, events, states)
Example:
// app/counter.tsx
"use client";
import { useState } from "react";
export default function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>
Count: {count}
</button>
);
}
// app/page.tsx
import Counter from "./counter";
export default function HomePage() {
return <><Counter /></>;
}
11. Full Example: A Small Project Structure
app/
+- layout.tsx
+- page.tsx
+- about/
¦ +- page.tsx
+- blog/
¦ +- page.tsx
¦ +- [slug]/
¦ +- page.tsx
+- dashboard/
¦ +- layout.tsx
¦ +- settings/
¦ +- page.tsx
+- api/
+- hello/
+- route.ts
12. Best Practices for Routing
- Use route groups to keep the app organized
- Use dynamic routes for blogs/products/users
- Use API routes for backend logic
- Always use <link> instead of <a> for navigation
- Use layouts to avoid repeating UI
- Avoid deeply nested folders; keep URLs clean
- Handle errors using error.tsx inside route folders
Routing in Next.js is designed to be simple yet powerful. With its file-based system, you can create pages, nested routes, and dynamic paths just by organizing folders—no complex configuration required. Features like layouts, route groups, and API routes make it easy to scale from small projects to large production applications. By understanding these core concepts, you can build clean, maintainable, and high-performance web apps with minimal effort.
To read more about A Complete Beginner’s Guide to Getting Started with Next.js, refer to our blog A Complete Beginner’s Guide to Getting Started with Next.js.