Migrating to Next.js 13: A Simple Walkthroughby@leandronnz
607 reads
607 reads

Migrating to Next.js 13: A Simple Walkthrough

by Leandro NuñezOctober 17th, 2023
Read on Terminal Reader
Read this story w/o Javascript
tldt arrow

Too Long; Didn't Read

This article discusses migrating from Next.js 12 to Next.js 13, highlighting changes in the directory structure, data fetching, API routes, dynamic paths, styling, and more. Next.js 13 introduces the 'app' directory, simplifies data fetching methods, offers improved flexibility for API handling, and enhances dynamic routing. Styling is more modular, and Tailwind CSS integration is updated. The article encourages embracing these changes to create better web experiences and provides references to official Next.js documentation for the migration process.
featured image - Migrating to Next.js 13: A Simple Walkthrough
Leandro Nuñez HackerNoon profile picture

Hello there! I'm Leandro, coming to you from the heart of Argentina where I immerse myself in code, often more tangled than a good tango.

I love building with Next.js, and if you're anything like me, you're not just in this for the coding. It's about the connections we make and the stories we tell through our craft, right?

Today, I’m here to chat about our next adventure: migrating from Next.js 12 to 13. No jargon, no fluff — just you, me, and some real talk about the nitty-gritty of upgrading.

Ready to jump in? ¡Vamos!

Table of Contents

  • Introduction
  • Transitioning to the 'app' Directory Structure
  • Fetching Data and Handling API Routes
  • Dynamic Paths and Incremental Static Regeneration
  • Styling Changes
  • Conclusion
  • References


In the realm of React development, Next.js has always been a game-changer, especially for folks like us who appreciate a framework that's both powerful and manageable. With the release of Next.js 13, things have gotten even more exciting. However, change can be challenging, and migration, a tad bit daunting. Fret not; we'll demystify this process step-by-step.

Transitioning to the 'app' Directory Structure

First off, Next.js 13 introduces a shift in the directory structure. Instead of the pages directory acting as the sole hub, we now work with the app directory. This new setup offers more flexibility, especially when our projects begin to expand in complexity.

// Before: pages/_app.js
// After: app/layout.js

import '../styles/globals.css'

export default function RootLayout({ children }) {
  return (
    <html lang="en">

The app directory becomes the central place for our layouts, pages, and components, enhancing overall organization and scalability.

Fetching Data and Handling API Routes

Next.js 13 simplifies data fetching.

Remember getServerSideProps or getStaticProps? Well, they've become more intuitive. Instead of juggling different data fetching methods, you can now use straightforward functions in your app directory components.

// app/page.js

async function getProjects() {
  const res = await fetch(`https://...`)
  const projects = await res.json()

  return projects

export default async function Index() {
  const projects = await getProjects()

  return => <div>{}</div>)

API routes see a transformation as well, replaced by Route Handlers in the app directory. These handlers allow for more customizability and direct interactions with requests and responses.

// app/api/route.js

export async function GET(request) {
  // Your server-side logic here

Dynamic Paths and Incremental Static Regeneration

Dynamic routing and paths also get a revamp, making them more intuitive to work with, especially within nested routes. The function generateStaticParams replaces getStaticPaths, simplifying how we define our dynamic routes.

// app/posts/[id]/page.js

export async function generateStaticParams() {
  return [{ id: '1' }, { id: '2' }]

async function getPost(params) {
  const res = await fetch(`https://.../posts/${}`)
  const post = await res.json()

  return post

export default async function Post({ params }) {
  const post = await getPost(params);

  return <PostLayout post={post} />

Moreover, the new revalidate option with data fetching methods adds the Incremental Static Regeneration feature, allowing pages to update automatically after a specified period.

// app/page.js

async function getPosts() {
  const res = await fetch(`https://.../posts`, { next: { revalidate: 60 } })
  const data = await res.json()

  return data.posts

Styling Changes

Styling your components is more flexible in Next.js 13. Global styles are no longer restricted to a specific file, meaning you can maintain styles within relevant component files, enhancing modularity. If you're using Tailwind CSS, don't forget to update your tailwind.config.js to include the new app directory.

// tailwind.config.js

module.exports = {
  content: [
    './app/**/*.{js,ts,jsx,tsx,mdx}', // New line to add
    // ... other paths

And, of course, continue importing your global styles as needed.

// app/layout.js

import '../styles/globals.css'

export default function RootLayout({ children }) {
  // ... your layout


So, there we have it, amigos! Transitioning to Next.js 13 might seem like a handful at first, but it's a smooth sail once you get the hang of the changes. The enhancements in data fetching, API handling, routing, and styling are all aimed at making our lives as developers easier, allowing us to focus more on creating fantastic web experiences. As we adapt, let's continue to share our knowledge and grow together in this ever-evolving tech landscape.


I hope this guide serves as a helpful resource for all of you embarking on this migration journey. Remember, staying updated with the latest changes helps us grow and innovate in our projects. ¡Hasta la próxima!