Next.js started out as a small, zero-config framework for server-rendered universal JavaScript web apps, built on top of React, Webpack, and Babel. Initially, it was focused on enabling a smooth universal JavaScript experience. Over the years, it evolved to support static site generation, TypeScript, dynamic pages, serverless functions, and more.

Written by:
  • Thom Krupa

    Thom Krupa

  • Melvin Kosisochukwu

Last update: July 26, 2023
  • Next.js logo
  • JS framework: React
  • Core Maintainer: Vercel, Inc.
  • Website:
  • Founded: 2015
  • Github Stars:
  • npm downloads:

Last update: July 26, 2023

Next.js 1.0 - the beginning

It was fall of 2016 when I discovered the first version of Next.js. I created a simple file that looked like this:

I executed in the terminal and the magic happened. Two lines of code, one command later, and my new hello world website went live. It was hard to compare that experience to developing custom WordPress themes. Next.js and Now (currently Vercel) felt incredibly easy. Almost like cheating.

A few months later, I shipped my first project using Next.js and the WordPress API. The project had some serious performance issues. Fetching data on every request from many API endpoints wasn't the best idea. I probably should export those pages to static ones, right? But it wasn't trivial in the first versions of Next.js.

Fast-forward to Next.js 9.3

Next.js evolved to support static site generation. Vercel evolved to support serverless.

Version 9.3 introduced three new data fetching methods:

  • to fetch data at build time, this can be content for a single post
  • to specify a collection of dynamic routes, for example, a list of blog posts
  • to fetch data on every request.

Below is a simple example of static generation:

The code above fetches from the API all blog posts at build time and creates array with for each of them. Data for each single blog post is fetched in based on the param.

If you are familiar with Gatsby, you can notice that is a bit like in . But I think Next approach is easier to understand. The difference is that you don't need to specify a path to a template and passing in . In Next, everything is in the same file. In this case, value is accessible through a query parameter. To learn more check the Migrating from Gatsby article.

If you add a new post you need to re-build the project unless you change to . If there is no existing HTML file on the CDN, Next.js will try to fetch content on the client and cache it. Fallback is very useful if you have a large collection of posts that updates frequently.

Image component

Next.js 10, among other things, has introduced a new, built-in image component and optimization. From now on you don't have to worry about shipping large images for mobile devices. Next handles resizing and generates a modern WebP image format that is approximately 30% smaller than JPG. If your website has a lot of images this can greatly reduce bandwidth and client-side performance.

To use component import it from :

Next.js' approach doesn't affect build time at all. All optimizations are done at request time. Currently, Next supports 4 cloud providers: Vercel, Imgix, Cloudinary, and Akamai.

Next.js 13 - what’s new?

The following are some of the new features that were introduced in Next.js 13:

  • A new Image component - the new Image component makes it easier to display images without layout shift and optimize files on-demand for increased performance.
  • A new font system - the new Font system automatically optimizes fonts, including custom fonts. It also removes external network requests for improved privacy and performance.
  • A new App Router - the new App Router is a more flexible and powerful way to manage routing in your Next.js application.
  • Improved TypeScript support - TypeScript support has been improved in Next.js 13, with better type checking and more efficient compilation.

The app directory

The app directory in Next.js is a new feature introduced in version 13. It allows you to create a separate directory for your application code, which can help improve the performance and scalability of your application.

The app directory is located at pages/app. This directory contains all of the files that make up your application, such as components, pages, and layouts.

When you use the app directory, Next.js will automatically pre-render all pages at build time. It can improve the performance of your application for users who visit your site for the first time.

The app directory also helps to improve the scalability of your application. Separating your application code from pages can make it easier to scale your application horizontally.

What do you stand to gain by using the app directory in Next.js?

  • Improved performance - pre-rendering all of your pages at build time can improve the performance of your application for users who visit your site for the first time.
  • Improved scalability - separating application code from pages can facilitate horizontal scaling of your application.
  • Easier to management - the app directory can help make your application code easier to manage as the entire application code is located in a single directory.

React server components

React Server Components (RSCs) are a new feature that allows you to render React components on the server. This can be used to improve the performance of your application, as the server can render the components before they are sent to the client.

RSCs are similar to regular React components but there are a few differences. First, RSCs must be exported as a function. Second, RSCs cannot access any state or props that are not defined in the function's parameters.

Here is an example of a React Server Component:

This component takes a title prop as input and renders a heading with the title.

To use an RSC, you need to wrap it in a StaticRoute component. The StaticRoute component takes a path and an RSC as input.

Here is an example of how to use an RSC in Next.js:

This code will render the MyServerComponent component when the user visits the / path.


In Next.js, a layout is a React component shared across multiple pages. Layouts can be used to share common UI elements, such as a header, footer, or sidebar. They can also be used to apply global styles to your application.

There are two ways to define a layout in Next.js:

Global layout

You can define a global layout by exporting a React component from a layout.js file. This layout will be applied to all pages in your application.

Here is an example of a global layout in Next.js:

This layout defines a header, main, and footer section. The children prop is a placeholder for the content of the page.

Per-page layout

You can also define a per-page layout by adding a getLayout prop to your page component. This prop should return a React component that will be used as the layout for that page.

Here is an example of a per-page layout in Next.js:

This component defines a heading with "This is my page" text. The getLayout prop returns the global layout which is then used to wrap the content of the page.

Some of the benefits of using layouts in Next.js:

  • Consistency - layouts can help improve the consistency of your application by ensuring that all pages have the same basic structure.
  • Readability - layouts can make your application easier to read by grouping common UI elements together.
  • Performance - layouts can help improve the performance of your application by reducing the amount of code that needs to be rendered on each page.


Streaming is a feature in Next.js that allows you to send data to the client as it becomes available. It improves your application's performance by reducing the time the client needs to wait for the entire page to load.

Streaming is supported in the latest version of Next.js, which is 13.4. To use streaming, you need thegetInitialProps prop on your page component. The getInitialProps prop is a function called when the page is first requested. In this function, you can use the fetch API to fetch data from an API server.

Once you have fetched the data, you can use the stream method to send it to the client. The stream method takes a function as an argument. This function will be called repeatedly with chunks of data as they become available.

Here is an example of how to use streaming in Next.js:

This code will fetch data from the API server and stream it to the client. The client will then render the data as it becomes available. The Suspense component is used to wrap an asynchronous component and display a fallback spinner or skeleton until the asynchronous process is completed. Then it will swap the fallback component for the component wrapped in Suspense.

Streaming can be a great way to improve the performance of your Next.js application. It can also be used to create more interactive and engaging user experiences.

Here is what you stand to gain by using streaming in Next.js:

  • Improved performance - streaming can improve your application's performance by reducing the time the client needs to wait for the entire page to load.
  • Interactive user experiences -streaming can be used to create more interactive and engaging user experience by loading priority content as soon as it is ready and sections of pages that do not require data to be fetched.
  • Reduced bandwidth usage - streaming can reduce bandwidth usage by only sending data to the client as it becomes available.


The @next/font package is a Next.js module that allows you to optimize your fonts, including custom fonts. It also removes external network requests for improved privacy and performance.

The @next/font package is built into Next.js 13.2, so you don't need to install it separately. It allows you to use Google Fonts pre-built or custom local fonts in your file directory.

The code block above enables using the Poppins font from Google Fonts. We can also use local fonts:

The local fonts requires an option object for the font properties, as shown in the code block above. The src key should be assigned the file path of your font located in your project directory.

The @next/font package also includes other features, such as:

  • Automatic fallback fonts - if a user's browser doesn't have the specified font, the @next/font package will automatically fallback to a default font.
  • Self-hosting - the @next/font package can self-host your fonts, which means that you don't need to upload them to a CDN. This can improve performance and privacy.
  • Fonts optimization - the @next/font package can optimize your fonts for performance. It includes minifying the font files and removing unused glyphs.

The next/link and next/image components in Next.js have been improved in a number of ways in recent versions. These improvements include:

  • better performance - the next/link and next/image components now use native browser features for lazy loading and image optimization, which can improve the performance of your application;
  • more flexibility - the next/link and next/image components now support a wider range of props, which gives you more flexibility in how you use them;
  • better accessibility - the next/link and next/image components now have better accessibility support, which makes your Next.js application more accessible to users with disabilities;
  • the next/link does not require you to nest an anchor (<a>) tag within the Link component, creating a better and improved development process;
  • the Next.js 13 update comes with an improved and easy to style Image component.

Differences between Next.js 13 and the previous version

There are several differences in the handling of certain elements in Next.js 13 compared to its previous version, 12. Apart from the recent enhancement and addition to the file structure with the app directory, changes have also been made to Layouts and the handling of routing in Next.js13. Moreover, version 13 provides an improved method for managing fonts, a topic we've covered in previous sections.

Here is a table that summarizes the key differences between Next.js 13 and the previous version:

FeatureNext.js 13Previous version
Image componentnew Image component with improved performance and optimizationnext/image component with less client-side JavaScript
Font systemnew Font system with automatic optimization and removal of external network requestsnext/fonts package
App Routernew App Router with improved flexibility and powerpages/index.js file
TypeScript supportimproved TypeScript support with better type checking and more efficient compilationbasic TypeScript support
Other improvementsfaster builds, faster refresh, faster startup, improved accessibility, and more flexible redirects and rewritesno other major improvements

Trade-offs and advantages

The latest Next.js Version 13 offers an enhanced upgrade from its predecessor, boasting exciting new features and substantial performance improvements. However, with these developments come certain trade-offs compared to the previous version. In the following section, we will delve into a detailed review of these advantages, improvements, and the associated trade-offs.

Here are some of the trade-offs and advantages of using Next.js 13:


  • The move to Turbopack compiler as a replacement for Webpack shows a drastic reduction in build time, improving the development experience.
  • Next.js 13 is compatible with React 18 and all its new features (Server-side Component, React Streaming, etc.).
  • Improved image optimization and styling - version 13 has an improved Image component with an enhanced optimization service and improved styling for the component.
  • Improved User Experience - Next.js version 13 enhances the user experience by implementing partial rendering of the available webpage components concurrently while data for other components is being fetched. This technique eliminates the need to wait until all data is fetched before starting the rendering process.


  • With version 13 being relatively new and the app directory just out of beta in 13.4, there is a high chance of bugs and application breaking.
  • Learning curve - working with the new app directory and some of the new features might pose a learning curve.
  • Since the version is relatively new, some community libraries might not be updated to support the features in Next.js 13.
  • The update to version 13 might lead to the deprecation of legacy code or older features.

File Structure

Next.js is zero-config from the very beginning.

Every file in directory is a lambda function.


Next.js has a great, growing community. You can read some interesting conversations and discuss RFC on Github. Vercel's team is very clear about the framework direction and open to community suggestions.

There is a lot of examples showing integration with different tools like Headless CMS, CSS-in-JS, or auth.


How to get started?

The easiest and recommended way to start a new Next.js project is to use:

If you want to learn more, I highly recommend the official Learn Next tutorial.

It helps to understand how to navigate between pages, add static assets, and fetch data. Once completed you will be ready to build your first Next.js application!

Deploying Next.js

The recommended platform is, of course, Vercel. Its CDN is designed at the edge to support features like incremental static generation, where pages first are populated into the durable store (S3), then the pathname is purged to ensure users are able to see the most recent content.

Preview mode works seamlessly on the Vercel platform, as well as the fallback feature. You can connect your repository and everything works out of the box with no additional config needed.

If for some reason you don't want to use Vercel, it is possible to deploy Next.js on every modern hosting platform like Netlify, Render, AWS, DigitalOcean, and so on. Netlify maintains a special next-on-netlify package that enables the server-side rendering of pages. Incremental static regeneration, fallback, and preview don't work exactly like on Vercel, so it's not a 1-to-1 replacement.


With Next.js you can build a full spectrum of websites and apps. From simple marketing pages and blogs to eCommerce and PWA with cookie-based authentication.

It's great for projects that require flexibility in how you build specific parts of the website. First-world static site generator with capabilities of dynamic enhancement. Hybrid mode is what really shines. Does it mean it's perfect for everything? Not at all. If you don't need React and don't plan to update the project frequently it might be overkill.

  • Zero-config
  • Great perceived performance thanks to instant route changes and prefetching.
  • TypeScript support.
  • Automatic code splitting.
  • Dynamic API routes.
  • Vercel team constantly works on reducing JS bundle size and optimizes performance.
  • Built-in integration with the new Web Vitals metrics. Next.js analytics.
  • Hybrid mode: both static generation and SSR.
  • Built-in image component and image optimization on demand.
  • First-class support for internationalization.
Use Cases
  • Hybrid apps. If you need both static and server-side rendered pages on each request.
  • eCommerce. Especially, with big traffic and frequent content updates.
  • Landing pages and marketing websites. Especially, if you already use React and have a design system.
  • Websites with a lot of interactive React components.
  • Websites with a lot of advanced route transitions.

Compare Next.js with

  • Gatsby logo
  • Eleventy logo
  • Gridsome logo
  • Hugo logo
  • Jekyll logo
  • Scully logo
  • Bridgetown logo