Routing in Next.js
Next.js has a file-system-based routing system. The URLs you can access in your browser are determined by how you organize your files and folders within your project.
Understanding the src/app Directory
In Next.js (when using the App Router), the src/app directory serves as the foundation for your application's structure. Key files inside this directory include:
- layout.tsx – Defines the layout for your application, allowing you to persist UI elements across different pages.
- page.tsx – Represents the content of a particular route.
Scenario 1: Creating a Homepage
Suppose you want to have a homepage accessible at:
To achieve this, ensure that a page.tsx file exists inside the src/app directory. By default, this file is created when you initialize a Next.js project.
Scenario 2: Creating Additional Pages
Now, let's say you want to create additional pages with different URLs.
Creating an About Page
To create a page accessible at:
Follow these steps:
- Inside the src/app directory, create a new folder named about.
- Inside about, create a page.tsx file.
- Add the following code:
export default function About() {
return <h1>Hello from About</h1>
}
Creating a Custom Page (e.g., Ramx Page)
If you want a page accessible at:
Follow the same steps as above:
- Inside src/app, create a folder named ramx.
- Inside ramx, create a page.tsx file.
- Add the following code:
export default function Ramx() {
return <h1>Hello from Ramx</h1>
}
Folder Structure for the Pages
After adding these pages, your src/app directory will look like this:
src/app/
layout.tsx - Defines layout structure
page.tsx - Homepage
about/
page.tsx - About Page
ramx/
page.tsx - Ramx Page
Nested Routes
Scenario 3: Creating Blog Pages
Suppose you want to handle the following routes:
Steps:
- First, create a blog folder inside src/app.
- Inside blog, create a page.tsx file.
This will create the route:
Handling /blog/first and /blog/second
Brute force method (Good for small projects, but not recommended for scalability):
Manually create separate folders:
src/app/blog/first/page.tsx
src/app/blog/second/page.tsx
Each file should contain:
export default function FirstBlog() {
return <h1>First Blog Post</h1>
}
export default function SecondBlog() {
return <h1>Second Blog Post</h1>
}
Dynamic Routing
Scenario 4: Creating a Product Listing Page
Suppose you want to create a product listing page where:
- /products lists all products.
- Individual product pages exist at /products/product-1, /products/product-2, etc.
Each product also has a details page, such as /products/1.
Brute Force Method (Not Scalable)
Manually create:
src/app/products/product-1/page.tsx
src/app/products/product-2/page.tsx
src/app/products/product-3/page.tsx
Using Dynamic Routing (Recommended Method)
Instead of manually creating pages for each product, use dynamic routing.
Steps:
- Create a folder named [productId] inside src/app/products/.
- Inside [productId], create a page.tsx file.
Your folder structure should look like:
src/app/products/
page.tsx # Product listing page
[productId]/
page.tsx # Dynamic product page
Code for Dynamic Product Page
export default function ProductPage({ params }: { params: { productId: string } }) {
return <h1>Product ID: {params.productId}</h1>;
}
Now, if you visit http://localhost:3000/products/100, the params.productId will be 100, and it will render dynamically.
Nested Dynamic Routes
Scenario 5: Category & Product Pages
Let's say you need URLs like:
- http://localhost:3000/categories/electronics
- http://localhost:3000/categories/fashion
- http://localhost:3000/categories/electronics/phones
- http://localhost:3000/categories/fashion/shoes
Steps to Implement:
- Create a categories folder inside src/app.
- Inside categories, create a dynamic [categoryId] folder.
- Inside [categoryId], create a dynamic [subCategoryId] folder.
- Add page.tsx inside both folders.
Folder Structure:
src/app/categories/
[categoryId]/
page.tsx # Category page
[subCategoryId]/
page.tsx # Sub-category page
Code for Category Page:
export default function CategoryPage({ params }: { params: { categoryId: string } }) {
return <h1>Category: {params.categoryId}</h1>;
}
Code for Sub-Category Page:
export default function SubCategoryPage({ params }: { params: { categoryId: string, subCategoryId: string } }) {
return <h1>{params.subCategoryId} in {params.categoryId}</h1>;
}
Catch-All Segments
Scenario 6: Handling Unknown Nested Routes
If you need to handle any level of nested paths, use a catch-all segment.
Example URLs:
- http://localhost:3000/docs
- http://localhost:3000/docs/getting-started
- http://localhost:3000/docs/api/reference
How to Implement:
- Inside src/app, create a docs folder.
- Inside docs, create a [...slug] folder (the three dots indicate "catch-all").
- Inside [...slug], create page.tsx.
Folder Structure:
src/app/docs/
[...slug]/
page.tsx
Code for Catch-All Route:
export default function DocsPage({ params }: { params: { slug?: string[] } }) {
return (
<div>
<h1>Docs Page</h1>
<p>Path: {params.slug ? params.slug.join(" / ") : "Home"}</p>
</div>
);
}
Do check out the previous blog