SEO Setup & Initial Audit
Verify and establish SEO foundations for a Next.js App Router project. Run this before implementing specific SEO features.
Step 1: Audit Current State
Check the project for existing SEO infrastructure:
# Check for metadata in root layout
grep -r "metadata" src/app/layout.tsx || echo "NO metadata export found"
# Check for sitemap
ls src/app/sitemap.ts 2>/dev/null || ls app/sitemap.ts 2>/dev/null || echo "NO sitemap.ts found"
# Check for robots
ls src/app/robots.ts 2>/dev/null || ls app/robots.ts 2>/dev/null || echo "NO robots.ts found"
# Check for existing SEO packages
grep -E "next-seo|next-sitemap|schema-dts" package.json || echo "No SEO packages installed"
# Check metadataBase
grep -r "metadataBase" src/app/layout.tsx || echo "NO metadataBase set"
Report which items are missing before proceeding.
Step 2: Install Dependencies
Only one package is needed — schema-dts provides TypeScript types for Schema.org structured data (zero bundle impact, types only):
pnpm add -D schema-dts
Do NOT install next-seo — it is deprecated and replaced by the built-in Next.js Metadata API. Do NOT install next-sitemap unless the project has complex dynamic sitemap requirements that exceed built-in sitemap.ts capabilities.
Step 3: Set metadataBase in Root Layout
The root layout MUST set metadataBase — all relative OG image URLs resolve against it:
// app/layout.tsx (or src/app/layout.tsx)
import type { Metadata } from 'next'
export const metadata: Metadata = {
metadataBase: new URL(
process.env.NEXT_PUBLIC_SITE_URL || 'http://localhost:3000'
),
title: {
template: '%s | Site Name',
default: 'Site Name',
},
description: 'Site description for search engines',
}
Add NEXT_PUBLIC_SITE_URL to .env:
NEXT_PUBLIC_SITE_URL=https://yourdomain.com
Step 4: Create robots.ts
// app/robots.ts
import type { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://yourdomain.com'
const isProduction = process.env.NODE_ENV === 'production'
if (!isProduction) {
return { rules: { userAgent: '*', disallow: ['/'] } }
}
return {
rules: [
{ userAgent: '*', allow: '/', disallow: ['/api/', '/admin/'] },
{ userAgent: 'GPTBot', disallow: ['/'] },
{ userAgent: 'CCBot', disallow: ['/'] },
],
sitemap: `${baseUrl}/sitemap.xml`,
}
}
Block AI training crawlers (GPTBot, CCBot) by default — most sites do not want their content used for AI training. Remove these rules if the site explicitly opts in.
Step 5: Create sitemap.ts
// app/sitemap.ts
import type { MetadataRoute } from 'next'
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
const baseUrl = process.env.NEXT_PUBLIC_SITE_URL || 'https://yourdomain.com'
// Static pages
const staticPages: MetadataRoute.Sitemap = [
{ url: baseUrl, lastModified: new Date(), changeFrequency: 'daily', priority: 1 },
{ url: `${baseUrl}/about`, lastModified: new Date(), changeFrequency: 'monthly', priority: 0.8 },
]
// Dynamic pages — fetch from your CMS/database
// const posts = await getAllPosts()
// const dynamicPages = posts.map(post => ({
// url: `${baseUrl}/blog/${post.slug}`,
// lastModified: new Date(post.updatedAt),
// changeFrequency: 'weekly' as const,
// priority: 0.7,
// }))
return [...staticPages]
}
Step 6: Google Search Console Verification
Add the verification tag to root layout metadata:
export const metadata: Metadata = {
// ... other metadata
verification: {
google: 'your-google-verification-code',
// yandex: 'yandex-code',
},
}
Step 7: Verify Setup
After setup, confirm all pieces are in place:
- Run
pnpm build— no metadata errors - Visit
http://localhost:3000/sitemap.xml— valid XML - Visit
http://localhost:3000/robots.txt— correct rules - View page source —
<title>,<meta name="description">, andmetadataBasepresent - Check
<link rel="canonical">on each page
SEO Setup Checklist
| Item | Status | Priority |
|---|---|---|
metadataBase in root layout |
Required | Critical |
| Title template in root layout | Required | Critical |
| Default description in root layout | Required | Critical |
robots.ts created |
Required | Critical |
sitemap.ts created |
Required | Critical |
schema-dts installed |
Recommended | High |
| Google Search Console verification | Recommended | High |
NEXT_PUBLIC_SITE_URL env var |
Required | Critical |
| Canonical URLs on all pages | Required | High |
| OG images configured | Recommended | Medium |
What This Skill Does NOT Cover
- Specific metadata patterns for individual pages — see
meta-tagsskill - Structured data (JSON-LD) implementation — see
structured-dataskill - Performance optimization — see
performanceskill - Content optimization — see
content-seoskill