Documentation
Documentation

SEO Guide

Learn how to optimize your Next.js application for search engines using metadata, structured data, and best practices.

Metadata

Next.js 13+ provides a powerful Metadata API for managing SEO-related tags. Here's how to implement basic metadata:

app/layout.tsxtypescript
1import { Metadata } from 'next'
2
3export const metadata: Metadata = {
4 title: 'Your Site Name',
5 description: 'Your site description goes here',
6 keywords: ['nextjs', 'react', 'web development'],
7 authors: [{ name: 'Your Name' }],
8 openGraph: {
9 title: 'Your Site Name',
10 description: 'Your site description goes here',
11 url: 'https://yoursite.com',
12 siteName: 'Your Site Name',
13 images: [
14 {
15 url: 'https://yoursite.com/og.png',
16 width: 1200,
17 height: 630,
18 },
19 ],
20 locale: 'en_US',
21 type: 'website',
22 },
23 twitter: {
24 card: 'summary_large_image',
25 title: 'Your Site Name',
26 description: 'Your site description goes here',
27 creator: '@yourusername',
28 images: ['https://yoursite.com/og.png'],
29 },
30 robots: {
31 index: true,
32 follow: true,
33 googleBot: {
34 index: true,
35 follow: true,
36 'max-video-preview': -1,
37 'max-image-preview': 'large',
38 'max-snippet': -1,
39 },
40 },
41 icons: {
42 icon: '/favicon.ico',
43 shortcut: '/favicon-16x16.png',
44 apple: '/apple-touch-icon.png',
45 },
46}

Dynamic Metadata

Generate dynamic metadata based on the current route or data:

app/blog/[slug]/page.tsxtypescript
1import { Metadata } from 'next'
2import { createServerComponentClient } from '@supabase/auth-helpers-nextjs'
3import { cookies } from 'next/headers'
4
5interface Props {
6 params: { slug: string }
7}
8
9export async function generateMetadata({ params }: Props): Promise<Metadata> {
10 const supabase = createServerComponentClient({ cookies })
11
12 const { data: post } = await supabase
13 .from('posts')
14 .select('title, description, image_url')
15 .eq('slug', params.slug)
16 .single()
17
18 if (!post) {
19 return {
20 title: 'Post Not Found',
21 description: 'The post you're looking for does not exist',
22 }
23 }
24
25 return {
26 title: post.title,
27 description: post.description,
28 openGraph: {
29 title: post.title,
30 description: post.description,
31 images: [
32 {
33 url: post.image_url,
34 width: 1200,
35 height: 630,
36 alt: post.title,
37 },
38 ],
39 },
40 }
41}

Structured Data

Add structured data to help search engines better understand your content:

components/blog-post.tsxtypescript
1import { JsonLd } from 'react-schemaorg'
2
3export default function BlogPost({
4 post,
5 author,
6}: {
7 post: Post
8 author: Author
9}) {
10 return (
11 <>
12 <JsonLd<BlogPosting>
13 item={{
14 '@context': 'https://schema.org',
15 '@type': 'BlogPosting',
16 headline: post.title,
17 description: post.description,
18 image: post.image_url,
19 datePublished: post.published_at,
20 dateModified: post.updated_at,
21 author: {
22 '@type': 'Person',
23 name: author.name,
24 },
25 publisher: {
26 '@type': 'Organization',
27 name: 'Your Company Name',
28 logo: {
29 '@type': 'ImageObject',
30 url: 'https://yoursite.com/logo.png',
31 },
32 },
33 }}
34 />
35 {/* Your blog post content */}
36 </>
37 )
38}

Best Practices

  • Use semantic HTML: Properly structure your content using semantic elements likearticle, section, nav, etc.
  • Optimize images: Use Next.js Image component with proper sizing and formats. Always include descriptive alt text.
  • Performance: Maintain good Core Web Vitals scores. Use proper loading strategies for images and other resources.
  • Mobile-first: Ensure your site is fully responsive and provides a good experience on all devices.
  • URL structure: Use clean, descriptive URLs that include relevant keywords when appropriate.
  • Internal linking: Implement a clear site structure with logical internal linking between related content.
  • Meta descriptions: Write unique, compelling meta descriptions for each page that accurately describe the content.