---
title: Next.js 13.3
description: Next.js 13.3 introduces dynamic open graph images, advanced static exports, parallel routes and interception, OTEL support, and more.
url: "https://nextjs.org/blog/next-13-3"
publishedAt: April 6th 2023
authors:
  - Delba de Oliveira
  - Tim Neutkens
---


Next.js 13.3 adds popular community-requested features, including:

- [**File-Based Metadata API**](#file-based-metadata-api): Dynamically generate sitemaps, robots, favicons, and more.
- [**Dynamic Open Graph Images**](#dynamic-open-graph-image-generation): Generate OG images using JSX, HTML, and CSS.
- [**Static Export for App Router**](#static-export-for-app-router): Static / Single-Page Application (SPA) support for Server Components.
- [**Parallel Routes and Interception**](#parallel-routes-and-interception): Advanced routing features for the App Router.

Update today by running:

```bash filename="Terminal"
npm i next@latest react@latest react-dom@latest eslint-config-next@latest
```

We are closing in on marking App Router as stable in the next minor release and are shifting our focus to optimizing performance, enhancing behaviors, and fixing bugs.

While we're still working on a few features like Mutations we don't expect these to impact the API surface of other App Router features. We're excited to see what you build with the App Router and [look forward to your feedback](https://github.com/vercel/next.js/discussions/41745).

## File-Based Metadata API

In [Next.js 13.2](https://nextjs.org/blog/next-13-2#built-in-seo-support-with-new-metadata-api), we announced a new Metadata API, allowing you to define metadata (e.g. `title`, `meta`, and `link` tags inside your HTML `head` element) by exporting a Metadata object from a layout or page.

```jsx filename="layout.js or page.js"
// either Static metadata
export const metadata = {
  title: 'Home',
};
// Output:
// <head>
//	 <title>Home</title>
// </head>

// or Dynamic metadata
export async function generateMetadata({ params, searchParams }) {
  const product = await getProduct(params.id);
  return { title: product.title };
}
// Output:
// <head>
//	 <title>My Unique Product</title>
// </head>

export default function Page() {}
```

In addition to config-based metadata, the Metadata API now supports new file conventions, allowing you to conveniently customize your pages for improved SEO and sharing on the web:

- `opengraph-image.(jpg|png|svg)`
- `twitter-image.(jpg|png|svg)`
- `favicon.ico`
- `icon.(ico|jpg|png|svg)`
- `sitemap.(xml|js|jsx|ts|tsx)`
- `robots.(txt|js|jsx|ts|tsx)`
- `manifest.(json|js|jsx|ts|tsx)`

For example, you can use file-based metadata to add a favicon for your app and an open graph image for your `/about` page:

```bash
app
├── favicon.ico
├── layout.js
├── page.js
└── about
    ├── opengraph-image.jpg
    └── page.js
```

Next.js will automatically serve these files with hashes (for the file name) in production for caching, and update the relevant `head` elements with the correct metadata information such as the asset's URL, file type, and image size.

```jsx
// Visiting "/"
<link rel="icon" href="<computedUrl>"/>

// Visiting "/about"
<link rel="icon" href="<computedUrl>"/>
<meta property="og:image" content="<computedUrl>" type="<computedType>" ... />
```

Adding static files to your application is often the simplest approach, but there are cases where you may need to create files dynamically. For each static file convention, there's an accompanying dynamic `(.js|.jsx|.ts|.tsx)` variant that allows you to write code to generate the file.

For example, while you can add a static `sitemap.xml` file, most sites have some pages that are dynamically generated using an external data source. To generate a dynamic sitemap, you can add a `sitemap.js` file that returns an array of your dynamic routes.

```jsx filename="app/sitemap.js"
export default async function sitemap() {
  const res = await fetch('https://.../posts');
  const allPosts = await res.json();

  const posts = allPosts.map((post) => ({
    url: `https://acme.com/blog/${post.slug}`,
    lastModified: post.publishedAt,
  }));

  const routes = ['', '/about', '/blog'].map((route) => ({
    url: `https://acme.com${route}`,
    lastModified: new Date().toISOString(),
  }));

  return [...routes, ...posts];
}
```

With [config-based](/docs/app/api-reference/file-conventions/metadata#metadata-object) and new file-based options, you now have a comprehensive Metadata API to cover both static and dynamic metadata.

The Metadata API is available in 13.3 for the App Router (`app`). It is not available in the `pages` directory. Learn more about [file-based metadata and view the API reference](/docs/app/api-reference/file-conventions/metadata#file-based-metadata).

## Dynamic Open Graph Image Generation

Six months ago, we released [@vercel/og](https://vercel.com/blog/introducing-vercel-og-image-generation-fast-dynamic-social-card-images) and [Satori](https://github.com/vercel/satori), libraries that allow you to generate images dynamically using JSX, HTML, and CSS.

`@vercel/og` was put to the test at [Next.js Conf](https://nextjs.org/conf), generating over 100,000 dynamic ticket images for every attendee. With extensive adoption across Vercel customers and over 900,000 downloads since the release, we're excited to bring dynamically generated images to all Next.js applications without the need for an external package.

You can now import `ImageResponse` from `next/server` to generate images:

```jsx filename="/app/about/opengraph-image.tsx"
import { ImageResponse } from 'next/server';

export const size = { width: 1200, height: 600 };
export const alt = 'About Acme';
export const contentType = 'image/png';
export const runtime = 'edge';

export default function og() {
  return new ImageResponse();
  // ...
}
```

`ImageResponse` naturally integrates well with other Next.js APIs, including Route Handlers and file-based Metadata. For example, you can use `ImageResponse` in a `opengraph-image.tsx` file to generate Open Graph and Twitter images at build time or dynamically at request time.

Learn more about the [Image Response API.](/docs/app/building-your-application/optimizing/metadata#dynamic-image-generation)

## Static Export for App Router

The Next.js App Router now supports fully static exports.

You can start as a static site or Single-Page Application (SPA), then later optionally upgrade to use Next.js features that require a server.

When running `next build`, Next.js generates an HTML file per route. By breaking a strict SPA into individual HTML files, Next.js can avoid loading unnecessary JavaScript code on the client-side, reducing the bundle size and enabling faster page loads.

```js filename="next.config.js"
/**
 * @type {import('next').NextConfig}
 */
const nextConfig = {
  output: 'export',
};

module.exports = nextConfig;
```

Static Export works with the `app` router's new features including static Route Handlers, Open Graph images, and React Server Components.

For example, Server Components will run during the build, similar to traditional static-site generation, rendering the components into static HTML for the initial page load and a static payload for client navigation between routes.

Previously, to use Static Export in the `pages` directory, you needed to run `next export`. However, with the `next.config.js` option, `next build` will output a `out` directory when `output: 'export'` is set. You can use the same configuration for the `app` router and `pages` directory. This means `next export` is no longer required.

With advanced static export support, you'll get errors earlier in the development process (`next dev`), such as when attempting to use a dynamic function that requires a server like `cookies()` or `headers()`.

Learn more about [Static Export](/docs/app/building-your-application/deploying/static-exports).

## Parallel Routes and Interception

Next.js 13.3 introduces new dynamic conventions that allow you to implement advanced routing cases: **Parallel Routes and Intercepting Routes**. These features enable you to show more than one page in the same view, like with complex dashboards or modals.

With Parallel Routes, you can simultaneously render one or more pages in the _same view_ that can be navigated independently. It can also be used to conditionally render pages.

Parallel Routes are created using named **"slots".** Slots are defined with the `@folder` convention:

```bash
dashboard
├── @user
│   └── page.js
├── @team
│   └── page.js
├── layout.js
└── page.js
```

The layout in the same route segment accepts the slots as props:

```jsx filename="app/dashboard/layout.js"
export default async function Layout({ children, user, team }) {
  const userType = getCurrentUserType();

  return (
    <>
      {userType === 'user' ? user : team}
      {children}
    </>
  );
}
```

In the example above, the `@user` and `@team` parallel route slots (explicit) are conditionally rendered based on your logic. `children` is an implicit route slot that does _not_ need to be mapped to a `@folder`. For example, `dashboard/page.js` is equivalent to `dashboard/@children/page.js`.

Intercepting routes allow you to load a new route within the current layout while "masking" the browser URL. This is useful when keeping the context of the current page is important, such as expanding a photo in a feed through a modal where the feed is kept in the background of the modal.

Intercepting routes can be defined with the `(..)` convention, similar to relative paths `../`. You can also use the `(...)` convention to create a path relative to the `app` directory.

```bash
feed
├── @modal
│   └── (..)photo
│       └── [id]
│           └── page.tsx
├── page.tsx
└── layout.tsx
photo
└── [id]
    └── page.tsx
```

In the example above, clicking the photo from the user's profile will open the photo in a modal during client-side navigation. However, refreshing or sharing the page will load the photo with its default layout.

<Image
  caption="Parallel routes and interception enable Instagram-like modal routing."
  src="/static/blog/next-13-3/modal-routing.png"
  width={3596 / 3}
  height={2706 / 2}
/>

This solves the challenges you may have when creating modals, such as making the modal content shareable through an URL, preventing context from being lost when the page is refreshed, and closing and reopening the modal with backward and forward navigation.

For more examples and behavior, see the [Parallel](/docs/app/building-your-application/routing/parallel-routes) and [Intercepting Routes documentation](/docs/app/building-your-application/routing/intercepting-routes).

## Other Improvements

- **Design Updates:** The Next.js [homepage](https://nextjs.org/) and [showcase](https://nextjs.org/showcase) have been refreshed with a new design.
- **Turbopack:** Added support for Middleware, all `next/font` options, and streaming with Server Components as it approaches beta ([see demo](https://twitter.com/padmaia/status/1641130761775464448)). We've also patched additional bugs discovered while dogfooding on mature Next.js apps like [vercel.com](https://vercel.com) and [nextjs.org](https://nextjs.org/). [Learn more](/docs/architecture/turbopack).
- **Fast Refresh for `next.config.js`:** Making changes to `next.config.js` will now automatically restart your local dev server. This extends automatic reloading of `.env`, `.env.*`, `jsconfig.json`, `tsconfig.json` configuration files.
- **Accessibility:** The App Router now includes the route annoucement from `pages`. This feature announces client-side route transitions to screen readers and other assistive technology. [Learn more](/docs/accessibility).
- **Statically Typed Links**: `redirects` and `rewrites` set in `next.config.js` are now considered during type checking. [Learn more](/docs/app/building-your-application/configuring/typescript#statically-typed-links).
- **Tailwind CSS for `create-next-app`:** When starting a new project with `npx create-next-app@latest`, you can now optionally select Tailwind CSS, or use the `--tailwind` flag, to preconfigure your application with this styling solution.
- **Route Handlers:** Using `export default` instead of a [supported HTTP verb](/docs/app/api-reference/file-conventions/route) now throws a helpful error with `route.ts`. [Learn more about Route Handlers](/docs/app/building-your-application/routing/route-handlers).
- **Images:** `next/image` now supports the [`fetchPriority="high"`](https://developer.mozilla.org/docs/Web/HTML/Element/img#:~:text=elementtiming%20attribute%20page.-,fetchpriority,-Experimental) attribute.
- **Metadata:** The previous API for metadata (`head.js`), which was deprecated in 13.2, has been removed. Instead, use the built-in support for SEO through the [Metadata](/docs/app/api-reference/file-conventions/metadata) API.
- **Opt folders out of routing:** Prefix a folder with \_ to opt it and any child segments out of routing. For example, `app/_dashboard/page.tsx` would not be routable.
- **App Router:** We've added a new `useParams` client component hook to read the dynamic parameters for the given route segment. [Learn more](/docs/app/api-reference/functions/use-params).
- **Improved Stylesheet Loading:** Next.js now implements React’s Suspensey CSS which fixes many issues around CSS loading and flashes of unstyled content, particularly during navigation.
- **Improved Not Found handling:** In addition to catching expected `notFound()` errors, the root `app/not-found.js` file will also handle any unmatched URLs for your whole application. This means users that visit a URL that is not handled by your app will be shown the UI exported by the `app/not-found.js` file. [Learn more](/docs/app/api-reference/file-conventions/not-found).
- **Improved client-side router cache:** `router.refresh()` will now invalidate the entire cache and search params are now part of the cache key allowing navigation between two search params (e.g. `/?search=leerob` and `/?search=tim`) to correctly restore content that relied on the param.

## Community

Next.js is the result of the combined work of over 2,600 individual developers, industry partners like Google and Meta, and our core team at Vercel. With over 4.2 million npm downloads per week and 104,000+ GitHub stars, Next.js is one of the most popular ways of building the Web.

Join the community on [GitHub Discussions](https://github.com/vercel/next.js/discussions), [Reddit](https://www.reddit.com/r/nextjs/), and [Discord](https://nextjs.org/discord).

This release was brought to you by:

- The **Next.js** team: [Andrew](https://github.com/acdlite), [Balazs](https://github.com/balazsorban44), [Hannes](https://github.com/hanneslund), [Jan](https://github.com/jankaifer), [Jiachi](https://github.com/huozhi), [Jimmy](https://github.com/feedthejim), [JJ](https://github.com/ijjk), [Josh](https://github.com/gnoff), [Sebastian](https://github.com/sebmarkbage), [Shu](https://github.com/shuding), [Steven](https://github.com/styfle), [Tim](https://github.com/timneutkens), and [Wyatt](https://github.com/wyattjoh).
- The **Turbopack** team: [Alex](https://github.com/alexkirsz), [Donny](https://github.com/kdy1), [Justin](https://github.com/jridgewell), [Leah](https://github.com/forsakenharmony), [LongYinan](https://github.com/brooooooklyn), [Maia](https://github.com/padmaia), [OJ](https://github.com/kwonoj), [Tobias](https://github.com/sokra), and [Will](https://github.com/wbinnssmith).

And the contributions of: @shuding, @huozhi, @sokra, @hanneslund, @JesseKoldewijn, @kaguya3222, @yangshun, @ijjk, @konomae, @Brooooooklyn, @jridgewell, @zlrlyy, @JohnDaly, @abhiyandhakal, @benjie, @johnnyomair, @nk980113, @dirheimerb, @DerTimonius, @DuCanhGH, @padmaia, @stafyniaksacha, @Gladowar, @zek, @jankaifer, @styfle, @balazsorban44, @wbinnssmith, @chibicode, @ForsakenHarmony, @franktronics, @FSaldanha, @Schniz, @raisedadead, @AdamKatzDev, @wyattjoh, @leerob, @meesvandongen, @vladikoff, @feedthejim, @tka5, @pyjun01, @gdborton, @M3kH, @aretrace, @shivanshubisht, @alexkirsz, @agrattan0820, @vinaykulk621, @heyitsuzair, @mrkldshv, @timneutkens, @furkanmavili, @swaminator, @EndangeredMassa, @DevEsteves, @rishabhpoddar, @schehata, @molebox, @dlehmhus, @akshaynox, @sp00ls, @janicklas-ralph, @tomryanx, @kwonoj, @karlhorky, @kdy1, @dante-robinson, @lachlanjc, @ianmacartney, @hotters, @isaackatayev, @insik-han, @jayair, @ivanhofer, @javivelasco, @SukkaW, @visshaljagtap, @imranbarbhuiya, @nivak-monarch, @HarshaVardhanReddyDuvvuru, @ianldgs, @ricardofiorani, @swarnava, and @gustavostz.