new·Earn with mozg — 20% of every monthSend somebody here and take a fifth of every plan payment they make, for as long as they keep paying — not a bounty on the first invoice. Your handle is the link, the window is thirty days, and the commission lands on your balance the second they pay. Free to join: if you have signed in, you already have the link. mozg.sh/earnall news →
mozg.beta
Sign in

Next.js App Router · all subjects

metadata & seo

19 notes, read out of this brain and free to use. Each one was extracted from a source and is re-checked against its exam.

Root layout with metadata in Next.js 13

In app/layout.tsx, export a metadata object with type Metadata imported from 'next': `export const metadata: Metadata = { title: 'Home', description: 'Welcome to Next.js' }`. In JavaScript, export a plain metadata object without the type annotation.

Replace next/head with metadata API

In pages directory, next/head is used to manage head HTML elements. In app directory, next/head is replaced with the built-in SEO support using metadata. Export a metadata object or use generateMetadata function instead of using the Head component.

Metadata APIs available in Next.js

Three metadata APIs are available: (1) the static metadata object, (2) the dynamic generateMetadata function, and (3) special file conventions for static or dynamically generated favicons and OG images. Both metadata object and generateMetadata function exports are only supported in Server Components.

Default meta tags always added

Two default meta tags are always added even if a route doesn't define metadata: a meta charset tag setting character encoding to utf-8, and a meta viewport tag setting content to width=device-width, initial-scale=1.

Static metadata export location

Static metadata is defined by exporting a Metadata object from a static layout.js or page.js file. The metadata object must be exported as a named export.

generateMetadata function signature

The generateMetadata function accepts two parameters: (1) an object containing params (a Promise of route parameters) and searchParams (a Promise of query string parameters), and (2) parent, a ResolvingMetadata instance. It returns a Promise<Metadata>.

Streaming metadata behavior

For dynamically rendered pages, Next.js streams metadata separately, injecting it into the HTML once generateMetadata resolves, without blocking UI rendering. This improves perceived performance by allowing visual content to stream first. However, streaming metadata is disabled for bots and crawlers that expect metadata in the head tag (detected via User Agent header), such as Twitterbot, Slackbot, and Bingbot. Prerendered pages do not use streaming since metadata is resolved at build time.

File-based metadata special files

The following special files are available for metadata: favicon.ico, apple-icon.jpg, and icon.jpg for favicons; opengraph-image.jpg and twitter-image.jpg for OG images; robots.txt for search engine directives; sitemap.xml for sitemaps. These can be used as static files or generated programmatically.

Favicon placement

Add a favicon.ico file to the root of the app folder to add a favicon to the application.

Static Open Graph image placement

Create an opengraph-image.jpg file in the root of the app folder to add a static OG image. OG images can also be added for specific routes by creating opengraph-image.jpg deeper in the folder structure. More specific images in the folder hierarchy take precedence over OG images higher up.

OG image file formats supported

OG image file formats supported include jpeg, jpg, png, and gif in addition to the standard opengraph-image.jpg naming convention.

ImageResponse constructor for dynamic OG images

The ImageResponse constructor from next/og allows generating dynamic images using JSX and CSS. It is useful for OG images that depend on data. The constructor returns a PNG image that can be used as an opengraph-image.tsx or similar file.

ImageResponse required exports

When generating OG images with ImageResponse, export a size object with width and height properties, export a contentType string (typically 'image/png'), and export a default async function that returns new ImageResponse().

ImageResponse JSX and CSS support

ImageResponse supports common CSS properties including flexbox and absolute positioning, custom fonts, text wrapping, centering, and nested images. Only flexbox and a subset of CSS properties are supported; advanced layouts like display: grid will not work.

ImageResponse implementation details

ImageResponse uses @vercel/og, satori, and resvg to convert HTML and CSS into PNG.

Dynamic OG image example with ImageResponse

Example showing how to generate dynamic OG images for blog posts: ```tsx import { ImageResponse } from 'next/og' import { getPost } from '@/app/lib/data' export const size = { width: 1200, height: 630, } export const contentType = 'image/png' export default async function Image({ params, }: { params: Promise<{ slug: string }> }) { const { slug } = await params const post = await getPost(slug) return new ImageResponse( ( <div style={{ fontSize: 128, background: 'white', width: '100%', height: '100%', display: 'flex', alignItems: 'center', justifyContent: 'center', }} > {post.title} </div> ) ) } ``` This example shows a route-specific OG image generator in app/blog/[slug]/opengraph-image.tsx that fetches post data and renders it as an image.

generateMetadata function with dynamic params example

Example of using generateMetadata to fetch and return metadata for a specific blog post: ```tsx import type { Metadata, ResolvingMetadata } from 'next' type Props = { params: Promise<{ slug: string }> searchParams: Promise<{ [key: string]: string | string[] | undefined }> } export async function generateMetadata( { params, searchParams }: Props, parent: ResolvingMetadata ): Promise<Metadata> { const slug = (await params).slug const post = await fetch(`https://api.vercel.app/blog/${slug}`).then((res) => res.json() ) return { title: post.title, description: post.description, } } export default function Page({ params, searchParams }: Props) {} ``` The function receives route parameters as a Promise and must await them before use.

Static metadata export example

Example of defining static metadata by exporting a metadata object from a layout file: ```tsx import type { Metadata } from 'next' export const metadata: Metadata = { title: 'My Blog', description: '...', } export default function Layout() {} ``` The metadata object is exported as a named export in layout.js or page.js files.

htmlLimitedBots configuration option

The htmlLimitedBots option in next.config.js can be used to customize or disable streaming metadata for bots and crawlers.

Give your agent this brain