关于 nextjs-seo-optimizer
面向 Next.js 应用开发者的 SEO 实施与审计技能,涵盖元数据、爬取控制、结构化数据、性能和验证,并提供 App Router 与旧版 Pages Router 的指导。
主要功能
- 01静态与动态元数据
- 02配置站点地图和 robots.txt
- 03JSON-LD 结构化数据
- 04Core Web Vitals 优化指导
- 05SEO 审计与验证清单
适用场景
- 01为静态和动态页面设置 SEO 元数据
- 02创建站点地图和爬虫规则
- 03为内容页面添加结构化数据
- 04审计技术 SEO 与性能
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ kumbajirajkumar123/ nextjs-seo-optimizer --skill nextjs-seo-optimizer安装后在 Claude Code 中输入/nextjs-seo-optimizer确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
.gitignoreLICENSECONTRIBUTING.mdCHANGELOG.mdREADME.mdINSTALLATION.md.github/workflows/validate.ymlrelease.ymlreferences/complete-example.mdnext-sitemap-guide.mdperformance-optimization.mdpages-router-seo.mdscripts/validate-seo.js详细介绍
Next.js SEO 优化器
通过配置合适的元数据、站点地图、robots.txt 和结构化数据,为 Next.js 应用优化搜索引擎表现。
SEO 核心实施策略
按以下顺序实施,以获得最大效果:
- 设置 Metadata API(基础)— 标题、描述、Open Graph
- 生成站点地图(发现)— 帮助搜索引擎找到所有页面
- 配置 Robots.txt(控制)— 管理爬虫访问权限
- 结构化数据(丰富结果)— 启用丰富摘要
- 性能优化(排名)— Core Web Vitals
- 内部链接(架构)— 网站结构和流转
1. Metadata API 实现
静态元数据(固定内容页面)
用于内容不变的页面(首页、关于、联系):
// app/layout.tsx or app/page.tsx
import { Metadata } from 'next'
export const metadata: Metadata = {
title: {
default: 'Your Site Name',
template: '%s | Your Site Name' // Pages will be "Page Title | Your Site Name"
},
description: 'Compelling 150-160 character description with keywords',
keywords: ['keyword1', 'keyword2', 'keyword3'],
authors: [{ name: 'Author Name', url: 'https://example.com' }],
creator: 'Company Name',
publisher: 'Company Name',
metadataBase: new URL('https://yourdomain.com'),
alternates: {
canonical: '/',
},
openGraph: {
type: 'website',
locale: 'en_US',
url: 'https://yourdomain.com',
title: 'Your Site Name',
description: 'Compelling description for social sharing',
siteName: 'Your Site Name',
images: [{
url: '/og-image.jpg', // 1200x630px recommended
width: 1200,
height: 630,
alt: 'Image description',
}],
},
twitter: {
card: 'summary_large_image',
title: 'Your Site Name',
description: 'Compelling description',
creator: '@yourtwitterhandle',
images: ['/twitter-image.jpg'], // 1200x628px
},
robots: {
index: true,
follow: true,
googleBot: {
index: true,
follow: true,
'max-video-preview': -1,
'max-image-preview': 'large',
'max-snippet': -1,
},
},
verification: {
google: 'verification-code',
yandex: 'verification-code',
yahoo: 'verification-code',
},
}
动态元数据(数据库/CMS 内容)
用于博客文章、产品和动态页面:
// app/blog/[slug]/page.tsx
import { Metadata, ResolvingMetadata } from 'next'
type Props = {
params: { slug: string }
searchParams: { [key: string]: string | string[] | undefined }
}
export async function generateMetadata(
{ params, searchParams }: Props,
parent: ResolvingMetadata
): Promise<Metadata> {
// Fetch data
const post = await fetchBlogPost(params.slug)
// Optionally access and extend parent metadata
const previousImages = (await parent).openGraph?.images || []
const previousKeywords = (await parent).keywords || []
return {
title: post.title, // Will use template from layout
description: post.excerpt.substring(0, 160),
keywords: [...previousKeywords, ...post.tags],
authors: [{ name: post.author.name }],
openGraph: {
title: post.title,
description: post.excerpt,
type: 'article',
publishedTime: post.publishedAt,
modifiedTime: post.updatedAt,
authors: [post.author.name],
images: [post.coverImage, ...previousImages],
url: `https://yourdomain.com/blog/${params.slug}`,
},
twitter: {
card: 'summary_large_image',
title: post.title,
description: post.excerpt,
images: [post.coverImage],
},
alternates: {
canonical: `https://yourdomain.com/blog/${params.slug}`,
},
}
}
export default function Page({ params }: Props) {
// Page content
}
元数据最佳实践
标题优化:
- 长度:50–60 个字符(移动端 SERP 显示限制)
- 将主要关键词放在靠前位置
- 使用模板以保持一致:
%s | Brand Name - 避免关键词堆砌
- 确保每个页面的标题各不相同
描述优化:
- 长度:150–160 个字符(桌面端 SERP 限制),移动端为 120 个字符
- 自然地包含主要和次要关键词
- 撰写吸引人的文案,鼓励用户点击
- 适当加入行动号召
- 确保每个描述各不相同
图片要求:
- Open Graph:1200x630px(16:9 比例)
- Twitter Card:1200x628px(1.91:1 比例)
- 文件大小:< 1MB
- 格式:JPG 或 PNG
- 添加描述性替代文本
2. 生成站点地图
内置静态站点地图(简单网站)
适用于路由可预测的静态网站:
// app/sitemap.ts
import { MetadataRoute } from 'next'
export default function sitemap(): MetadataRoute.Sitemap {
return [
{
url: 'https://yourdomain.com',
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 1,
},
{
url: 'https://yourdomain.com/about',
lastModified: new Date(),
changeFrequency: 'monthly',
priority: 0.8,
},
{
url: 'https://yourdomain.com/blog',
lastModified: new Date(),
changeFrequency: 'weekly',
priority: 0.5,
},
]
}
动态站点地图(CMS/数据库内容)
适用于包含来自 CMS 或数据库的动态内容的网站:
// app/sitemap.ts
import { MetadataRoute } from 'next'
export default async function sitemap(): MetadataRoute.Sitemap {
// Fetch dynamic routes
const posts = await fetch('https://api.example.com/posts').then((res) => res.json())
const products = await fetch('https://api.example.com/products').then((res) => res.json())
const postEntries: MetadataRoute.Sitemap = posts.map((post: any) => ({
url: `https://yourdomain.com/blog/${post.slug}`,
lastModified: new Date(post.updatedAt),
changeFrequency: 'weekly',
priority: 0.7,
}))
const productEntries: MetadataRoute.Sitemap = products.map((product: any) => ({
url: `https://yourdomain.com/products/${product.slug}`,
lastModified: new Date(product.updatedAt),
changeFrequency: 'daily',
priority: 0.9,
}))
return [
{
url: 'https://yourdomain.com',
lastModified: new Date(),
changeFrequency: 'yearly',
priority: 1,
},
...postEntries,
...productEntries,
]
}
使用 next-sitemap(大型网站推荐)
有关自动生成的详细设置,请参阅 references/next-sitemap-guide.md。
优先级指南:
- 首页:1.0
- 重要落地页:0.8-0.9
- 博客文章 / 产品:0.6-0.8
- 分类页面:0.5-0.7
- 其他页面:0.4-0.6
更新频率指南:
always:股价、实时数据hourly:新闻网站、频繁更新的内容daily:博客、活跃的电商网站weekly:常规博客文章monthly:功能页面yearly:静态页面(关于、联系)never:已归档内容
3. 配置 Robots.txt
基础 robots.txt(内置)
// app/robots.ts
import { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
return {
rules: {
userAgent: '*',
allow: '/',
disallow: ['/admin/', '/api/', '/private/'],
},
sitemap: 'https://yourdomain.com/sitemap.xml',
}
}
高级 robots.txt(多个用户代理)
// app/robots.ts
import { MetadataRoute } from 'next'
export default function robots(): MetadataRoute.Robots {
const baseUrl = process.env.NEXT_PUBLIC_BASE_URL || 'https://yourdomain.com'
return {
rules: [
{
userAgent: '*',
allow: '/',
disallow: ['/admin/', '/api/', '/_next/', '/private/'],
crawlDelay: 1,
},
{
userAgent: 'Googlebot',
allow: '/',
disallow: ['/admin/', '/private/'],
},
{
userAgent: 'GPTBot', // Block AI scrapers if desired
disallow: ['/'],
},
],
sitemap: `${baseUrl}/sitemap.xml`,
host: baseUrl,
}
}
常见的禁止访问路径:
/admin/— 管理面板/api/— API 端点(非公开端点除外)/_next/— Next.js 内部文件/private/— 私有/受限内容/search?*— 搜索结果页面(防止内容重复)/cart/— 购物车页面/checkout/— 结账页面*?*— 所有包含查询参数的页面(可选,谨慎使用)
特定环境的规则:
const isDevelopment = process.env.NODE_ENV === 'development'
const isStaging = process.env.VERCEL_ENV === 'preview'
if (isDevelopment || isStaging) {
return {
rules: {
userAgent: '*',
disallow: '/', // Block all indexing in dev/staging
},
}
}
4. 结构化数据(JSON-LD)
添加结构化数据以在搜索结果中展示丰富信息。务必在 https://search.google.com/test/rich-results 测试。
组织架构 Schema(首页)
// app/page.tsx or components/StructuredData.tsx
export default function HomePage() {
const organizationSchema = {
'@context': 'https://schema.org',
'@type': 'Organization',
name: 'Your Company Name',
url: 'https://yourdomain.com',
logo: 'https://yourdomain.com/logo.png',
description: 'Company description',
address: {
'@type': 'PostalAddress',
streetAddress: '123 Main St',
addressLocality: 'City',
addressRegion: 'State',
postalCode: '12345',
addressCountry: 'US',
},
contactPoint: {
'@type': 'ContactPoint',
telephone: '+1-234-567-8900',
contactType: 'Customer Service',
},
sameAs: [
'https://twitter.com/yourcompany',
'https://facebook.com/yourcompany',
'https://linkedin.com/company/yourcompany',
],
}
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(organizationSchema) }}
/>
{/* Page content */}
</>
)
}
文章 Schema(博客文章)
export default function BlogPost({ post }: { post: Post }) {
const articleSchema = {
'@context': 'https://schema.org',
'@type': 'BlogPosting',
headline: post.title,
description: post.excerpt,
image: post.coverImage,
author: {
'@type': 'Person',
name: post.author.name,
url: `https://yourdomain.com/authors/${post.author.slug}`,
},
publisher: {
'@type': 'Organization',
name: 'Your Company',
logo: {
'@type': 'ImageObject',
url: 'https://yourdomain.com/logo.png',
},
},
datePublished: post.publishedAt,
dateModified: post.updatedAt,
mainEntityOfPage: {
'@type': 'WebPage',
'@id': `https://yourdomain.com/blog/${post.slug}`,
},
}
return (
<>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(articleSchema) }}
/>
{/* Article content */}
</>
)
}
产品 Schema(电商)
const productSchema = {
'@context': 'https://schema.org',
'@type': 'Product',
name: product.name,
image: product.images,
description: product.description,
sku: product.sku,
brand: {
'@type': 'Brand',
name: product.brand,
},
offers: {
'@type': 'Offer',
url: `https://yourdomain.com/products/${product.slug}`,
priceCurrency: 'USD',
price: product.price,
availability: product.inStock
? 'https://schema.org/InStock'
: 'https://schema.org/OutOfStock',
seller: {
'@type': 'Organization',
name: 'Your Company',
},
},
aggregateRating: {
'@type': 'AggregateRating',
ratingValue: product.rating,
reviewCount: product.reviewCount,
},
}
FAQ Schema
const faqSchema = {
'@context': 'https://schema.org',
'@type': 'FAQPage',
mainEntity: faqs.map((faq) => ({
'@type': 'Question',
name: faq.question,
acceptedAnswer: {
'@type': 'Answer',
text: faq.answer,
},
})),
}
面包屑 Schema
const breadcrumbSchema = {
'@context': 'https://schema.org',
'@type': 'BreadcrumbList',
itemListElement: breadcrumbs.map((crumb, index) => ({
'@type': 'ListItem',
position: index + 1,
name: crumb.name,
item: `https://yourdomain.com${crumb.path}`,
})),
}
5. Core Web Vitals 优化
这些指标会直接影响搜索排名。详细策略请参阅 references/performance-optimization.md。
快速见效的方法:
- 使用 Next.js
<Image>组件(自动优化) - 在 next.config.js 中启用
experimental.optimizePackageImports - 设置合适的缓存标头
- 对大型组件使用动态导入:
const HeavyComponent = dynamic(() => import('./HeavyComponent')) - 尽量减少客户端组件(
'use client')的使用 - 设置合适的加载状态
6. SEO 审核清单
审核或实施 SEO 时,请检查:
元数据:
- 所有页面都有唯一标题(50-60 个字符)
- 所有页面都有唯一描述(150-160 个字符)
- 在根布局中设置 metadataBase
- 为所有页面设置规范 URL
- Open Graph 图片(1200x630px)
- Twitter Card 图片(1200x628px)
- 页面之间没有重复的元数据
技术 SEO:
- 可通过 /sitemap.xml 访问 sitemap.xml
- 可通过 /robots.txt 访问 robots.txt
- Sitemap 包含所有公开页面
- robots.txt 引用了 sitemap
- 没有意外屏蔽重要页面
- 已启用并强制使用 HTTPS
- 404 页面返回 404 状态码
- 正确使用 301(永久)重定向
结构化数据:
- 首页包含 Organization 架构
- 博客文章包含 Article 架构
- 产品页面包含 Product 架构(如适用)
- 多层级页面包含 Breadcrumb 架构
- JSON-LD 有效(使用 Google Rich Results Test 测试)
性能:
- LCP < 2.5s(最大内容绘制)
- FID < 100ms(首次输入延迟)
- CLS < 0.1(累积布局偏移)
- 图片已优化(WebP、尺寸正确)
- 关键 CSS 已内联
- JavaScript 包 < 100KB(初始加载)
内容:
- 标题层级正确(每页一个 H1)
- 已实施内部链接策略
- 所有图片都包含替代文本
- 设计适配移动设备
- 符合无障碍标准(WCAG 2.1 AA)
7. 常见 SEO 问题及修复方法
问题:元数据重复
- 修复:使用 generateMetadata 为每个页面提供唯一数据
- 修复:实施正确的规范 URL
问题:Core Web Vitals 表现不佳
- 修复:使用 Next.js Image 组件
- 修复:实施代码分割
- 修复:启用 SWC 压缩
- 参见 references/performance-optimization.md
问题:缺少结构化数据
- 修复:为相关页面类型添加 JSON-LD
- 修复:使用 Google Rich Results Test 测试
问题:robots.txt 错误地屏蔽了重要页面
- 修复:使用 Google Search Console robots.txt 测试工具进行测试
- 修复:仔细检查 disallow 规则
问题:Sitemap 未更新
- 修复:使用动态 sitemap 获取数据
- 修复:实施 next-sitemap 以自动生成
8. 测试与验证工具
使用以下工具验证 SEO 实施情况:
Google 工具:
- Google Search Console - 监控搜索表现
- Google Rich Results Test - 验证结构化数据
- PageSpeed Insights - 测试 Core Web Vitals
- Lighthouse - 全面审核
第三方工具:
- Screaming Frog - 抓取网站并识别问题
- Ahrefs Site Audit - 检查技术 SEO 问题
- SEMrush Site Audit - 全面分析 SEO
- Schema Markup Validator - 测试 JSON-LD
测试命令:
# Test metadata locally
curl -I http://localhost:3000/page-to-test
# View sitemap
curl http://localhost:3000/sitemap.xml
# View robots.txt
curl http://localhost:3000/robots.txt
# Run Lighthouse audit
npx lighthouse http://localhost:3000 --view
实施优先级
对于新项目:
- 在根布局中设置 metadataBase
- 为所有页面添加基本元数据
- 创建 sitemap.ts
- 创建 robots.ts
- 为关键页面添加结构化数据
- 优化性能
- 实施全面测试
对于现有项目:
- 审核当前 SEO(使用 Lighthouse)
- 修复关键问题(robots.txt 损坏、缺少 sitemap)
- 添加缺失的元数据
- 实施结构化数据
- 优化 Core Web Vitals
- 使用 Google Search Console 进行监控
Next.js 版本兼容性
此技能支持:
- ✅ Next.js 13+(App Router)——所有功能
- ⚠️ Next.js 12(Pages Router)——使用旧版模式,参见 references/pages-router-seo.md
- ❌ Next.js < 12——建议升级
快速入门命令
# Validate sitemap locally
curl http://localhost:3000/sitemap.xml | head -n 20
# Test robots.txt
curl http://localhost:3000/robots.txt
# Run SEO audit
npm run build && npm start
# Then in browser: DevTools > Lighthouse > SEO audit
# Test metadata extraction
curl -s http://localhost:3000 | grep -E '<title>|<meta'
环境变量
在 .env.local 中设置:
NEXT_PUBLIC_BASE_URL=https://yourdomain.com
NEXT_PUBLIC_SITE_NAME="Your Site Name"
NEXT_PUBLIC_OG_IMAGE=https://yourdomain.com/og-image.jpg
GOOGLE_VERIFICATION_CODE=your-verification-code
其他资源
有关具体场景和高级模式:
- next-sitemap 设置:参见 references/next-sitemap-guide.md
- 性能优化:参见 references/performance-optimization.md
- Pages Router 迁移:参见 references/pages-router-seo.md