nextjs-seo

📁 laguagu/claude-code-nextjs-skills 📅 Jan 26, 2026
52
总安装量
55
周安装量
#4149
全站排名
安装命令
npx skills add https://github.com/laguagu/claude-code-nextjs-skills --skill nextjs-seo

Agent 安装分布

opencode 46
claude-code 44
gemini-cli 43
github-copilot 35
antigravity 30

Skill 文档

Next.js SEO Optimization

Comprehensive SEO guide for Next.js 16+ applications using App Router.

Version: Updated for Next.js 16.1.3 (January 2026)

Quick SEO Audit

Run this checklist for any Next.js project:

  1. Check robots.txt: curl https://your-site.com/robots.txt
  2. Check sitemap: curl https://your-site.com/sitemap.xml
  3. Check metadata: View page source, search for <title> and <meta name="description">
  4. Check JSON-LD: View page source, search for application/ld+json
  5. Check Core Web Vitals: Run Lighthouse in Chrome DevTools

Essential Files

app/layout.tsx – Root Metadata

import type { Metadata, Viewport } from 'next';

// Viewport (separate export required in Next.js 14+)
export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  maximumScale: 5,
  userScalable: true,
  themeColor: [
    { media: '(prefers-color-scheme: light)', color: '#ffffff' },
    { media: '(prefers-color-scheme: dark)', color: '#0a0a0a' },
  ],
};

export const metadata: Metadata = {
  metadataBase: new URL('https://your-site.com'),
  title: {
    default: 'Site Title - Main Keyword',
    template: '%s | Site Name',
  },
  description: 'Compelling description with keywords (150-160 chars)',
  keywords: ['keyword1', 'keyword2', 'keyword3'],
  openGraph: {
    type: 'website',
    locale: 'en_US',
    url: 'https://your-site.com',
    siteName: 'Site Name',
    title: 'Site Title',
    description: 'Description for social sharing',
    images: [{ url: '/og-image.png', width: 1200, height: 630, alt: 'Site preview' }],
  },
  twitter: {
    card: 'summary_large_image',
    title: 'Site Title',
    description: 'Description for Twitter',
    images: ['/og-image.png'],
  },
  alternates: {
    canonical: '/',
  },
  robots: {
    index: true,
    follow: true,
  },
};

app/sitemap.ts – Dynamic Sitemap

import type { MetadataRoute } from 'next';

export default function sitemap(): MetadataRoute.Sitemap {
  const baseUrl = 'https://your-site.com';

  return [
    {
      url: baseUrl,
      lastModified: new Date(),
      changeFrequency: 'weekly',
      priority: 1,
      images: [`${baseUrl}/og-image.png`], // Next.js 16 Image Sitemap
    },
    {
      url: `${baseUrl}/about`,
      lastModified: new Date(),
      changeFrequency: 'monthly',
      priority: 0.8,
    },
  ];
}

app/robots.ts – Robots Configuration

import type { MetadataRoute } from 'next';

export default function robots(): MetadataRoute.Robots {
  const baseUrl = 'https://your-site.com';

  return {
    rules: [
      {
        userAgent: '*',
        allow: '/',
        disallow: ['/api/', '/_next/', '/admin/'],
      },
    ],
    sitemap: `${baseUrl}/sitemap.xml`,
    host: baseUrl,
  };
}

Key Principles

Rendering Strategy for SEO

Strategy Use When SEO Impact
SSG (Static) Content rarely changes Best – pre-rendered HTML
SSR Dynamic content per request Great – server-rendered
ISR Large sites, periodic updates Great – cached + fresh
CSR Dashboards, authenticated areas Poor – avoid for SEO pages

Core Web Vitals Targets

Metric Target Impact
LCP (Largest Contentful Paint) < 2.5s Loading speed
INP (Interaction to Next Paint) < 200ms Interactivity
CLS (Cumulative Layout Shift) < 0.1 Visual stability

References

Common Mistakes to Avoid

  1. Mixing next-seo with Metadata API – Use only Metadata API in App Router
  2. Missing canonical URLs – Always set alternates.canonical
  3. Using CSR for SEO pages – Use SSG/SSR for indexable content
  4. Blocking assets in robots.txt – Don’t block CSS/JS needed for rendering
  5. Missing metadataBase – Required for relative URLs in metadata
  6. Viewport in metadata – Must be separate export in Next.js 14+
  7. Mixing metadata object and generateMetadata – Use one or the other, not both

Quick Fixes

Add noindex to a page

export const metadata: Metadata = {
  robots: {
    index: false,
    follow: false,
  },
};

Dynamic metadata per page

export async function generateMetadata({ params }): Promise<Metadata> {
  const product = await getProduct(params.id);
  return {
    title: product.name,
    description: product.description,
  };
}

Canonical for dynamic routes

export async function generateMetadata({ params }): Promise<Metadata> {
  return {
    alternates: {
      canonical: `/products/${params.slug}`,
    },
  };
}