
Next.js 13 introduced a new routing system called the App Router, which provides a more flexible and intuitive way to define routes and handle navigation in your application.
What is the App Router ?
The App Router is built on top of React Server Components and introduces new concepts and conventions for defining routes and handling navigation.
With the App Router, you define your routes using a directory structure inside theapp
directory. Each directory represents a route segment, and the files inside those directories define the UI and behavior for that route.
Here's an example of a basic App Router structure:
app/ dashboard/ layout.js page.js settings/ layout.js page.js layout.js page.js
In this example, we have two routes:/dashboard
and/settings
. Each route has its ownlayout.js
andpage.js
files. Thelayout.js
file defines the common UI layout for that route, while thepage.js
file defines the specific UI for that route.
Migrating from Pages Router to App Router
If you have an existing Next.js application using the Pages Router, you can migrate to the App Router incrementally. The App Router is available in Next.js 13 and later versions and can coexist with the Pages Router.
To start migrating, you can create anapp
directory at the root of your project and gradually move your routes and components into it. You can have a mix of Pages Router and App Router in your application during the migration process.
Here's an example of a migrated route:
Before :
pages/ dashboard.js
After :
app/ dashboard/ page.js
In this example, the/dashboard
route is migrated to the App Router by creating adashboard
directory inside theapp
directory and moving the route's logic into thepage.js
file.
File-based Routing
With the App Router, routes are defined using a file-based convention. Each file inside theapp
directory represents a route segment, and the directory structure determines theroute hierarchy.
Here's an example of a more complex App Router structure:
app/ blog/ [slug]/ page.js page.js dashboard/ settings/ page.js page.js layout.js page.js
In this example, we have the following routes:
/
: Defined byapp/page.js
/blog
: Defined byapp/blog/page.js
/blog/[slug]
: Defined byapp/blog/[slug]/page.js
, where[slug]
is a dynamic segment/dashboard
: Defined byapp/dashboard/page.js
/dashboard/settings
: Defined byapp/dashboard/settings/page.js
Thelayout.js
file at the root level defines the common UI layout for all routes.
Layouts and Nesting
The App Router introduces the concept of layouts, which allow you to define shared UI across multiple routes. Layouts are defined using thelayout.js
file in each route directory.
Here's an example of a layout file:
// app/dashboard/layout.jsimportSidebarfrom'./Sidebar';exportdefaultfunctionDashboardLayout({children}){return(<div><Sidebar/><main>{children}</main></div>);}
In this example, theDashboardLayout
component defines the common UI structure for all routes within the/dashboard
route. Thechildren
prop represents the content of the nested routes.
Layouts can be nested, allowing you to create a hierarchy of shared UI components. For example:
app/ dashboard/ settings/ page.js layout.js page.js layout.js
In this case, theapp/dashboard/layout.js
file defines the layout for the/dashboard
route, and theapp/layout.js
file defines the root layout for all routes.
Data Fetching with the App Router
The App Router provides a new data fetching approach using React Server Components. You can fetch data directly in your components using thefetch
function or other data fetching libraries.
Here's an example of data fetching in a page component:
// app/blog/[slug]/page.jsasyncfunctiongetPost(slug){constres=awaitfetch(`https://api.example.com/posts/${slug}`);returnres.json();}exportdefaultasyncfunctionPostPage({params}){constpost=awaitgetPost(params.slug);return(<div><h1>{post.title}</h1><p>{post.content}</p></div>);}
In this example, thegetPost
function fetches a blog post from an API based on theslug
parameter. ThePostPage
component is an async function that awaits the data fetching and renders the post.
The App Router automatically handles data fetching on the server and sends the pre-rendered HTML to the client, providing a fast initial load experience.
6. API Routes
Next.js allows you to create API routes, which are server-side endpoints that can handle HTTP requests and perform server-side logic.
Creating API Routes
To create an API route, you need to create a file inside thepages/api
directory. The file name becomes the route path, and the default export is a request handler function.
Here's an example of a simple API route:
// pages/api/hello.jsexportdefaultfunctionhandler(req,res){res.status(200).json({message:'Hello, World!'});}
In this example, the/api/hello
route responds with a JSON object containing a "Hello, World!" message.
Handling HTTP Methods
API routes can handle different HTTP methods like GET, POST, PUT, DELETE, etc. You can use conditional statements based on thereq.method
to handle specific methods.
Here's an example:
// pages/api/users.jsexportdefaultfunctionhandler(req,res){if(req.method==='GET'){// Handle GET requestres.status(200).json({users:[]});}elseif(req.method==='POST'){// Handle POST requestconstnewUser=req.body;// Process the new user datares.status(201).json({message:'User created'});}else{res.status(405).json({message:'Method not allowed'});}}
In this example, the/api/users
route handles GET and POST requests differently. It returns a list of users for GET requests and creates a new user for POST requests.
Connecting to Databases
API routes can connect to databases or external services to perform data operations. You can use libraries likeprisma
,mongoose
, or any other database client to interact with your database.
Here's an example using Prisma:
// pages/api/posts.jsimportprismafrom'../../lib/prisma';exportdefaultasyncfunctionhandler(req,res){if(req.method==='GET'){constposts=awaitprisma.post.findMany();res.status(200).json({posts});}elseif(req.method==='POST'){const{title,content}=req.body;constnewPost=awaitprisma.post.create({data:{title,content,},});res.status(201).json({post:newPost});}else{res.status(405).json({message:'Method not allowed'});}}
In this example, the/api/posts
route uses Prisma to fetch posts from a database for GET requests and create a new post for POST requests.
Authentication and Authorization
API routes can handle authentication and authorization to protect sensitive data or restrict access to certain endpoints. You can use libraries likejsonwebtoken
ornext-auth
to implement authentication strategies.
Here's an example usingjsonwebtoken
:
// pages/api/protected.jsimportjwtfrom'jsonwebtoken';constsecretKey=process.env.JWT_SECRET;exportdefaultfunctionhandler(req,res){consttoken=req.headers.authorization?.split('')[1];if(!token){res.status(401).json({message:'Unauthorized'});return;}try{constdecoded=jwt.verify(token,secretKey);// Access the authenticated user data from `decoded`res.status(200).json({message:'Protected data'});}catch(error){res.status(401).json({message:'Invalid token'});}}
In this example, the/api/protected
route checks for the presence of a JWT token in theAuthorization
header. It verifies the token using the secret key and grants access to protected data if the token is valid.
Let's go for Part 3 : Deployment and Advanced techniques !
- NextJS Advanced Techniques :https://dev.to/fabrikapp/mastering-nextjs-1314-advanced-techniques-5ba
Or go back to your fundamentals :
Top comments(2)

- LocationNairobi, Kenya
- EducationUniversity of Nairobi
- WorkBusiness Intelligence Developer
- Joined
exactly the kind of a starter documentation I have been looking for. Thank you for putting this up
For further actions, you may consider blocking this person and/orreporting abuse