SiteArchitectureSkill site-architecture

这项技能涵盖了使网站内容能够被搜索引擎和AI爬虫发现的技术基础,包括优化robots.txt、站点地图、元标签、核心网页指标等,以提高网站的可发现性和搜索引擎排名。

SEO/SEM 0 次安装 0 次浏览 更新于 3/5/2026

网站架构技能

加载于:base.md + web-content.md

对于技术网站结构,使其能够被搜索引擎和AI爬虫(GPTBot, ClaudeBot, PerplexityBot)发现。


哲学

内容为王,架构为国。

伟大的内容如果埋没在糟糕的架构中将不会被发现。这项技能涵盖了使您的内容能够被以下发现的技术基础:

  • Google, Bing(传统搜索)
  • GPTBot(ChatGPT), ClaudeBot, PerplexityBot(AI助手)
  • 社交平台(Open Graph, Twitter Cards)

robots.txt

基本模板

# robots.txt

# 默认允许所有爬虫
User-agent: *
Allow: /
Disallow: /api/
Disallow: /admin/
Disallow: /private/
Disallow: /_next/
Disallow: /cdn-cgi/

# 站点地图位置
Sitemap: https://yoursite.com/sitemap.xml

# 爬取延迟(可选 - 小心使用,不是所有爬虫都遵守)
# Crawl-delay: 1

AI Bot配置

# 带AI机器人规则的robots.txt

# === 搜索引擎 ===
User-agent: Googlebot
Allow: /

User-agent: Bingbot
Allow: /

# === AI助手(允许发现) ===
User-agent: GPTBot
Allow: /

User-agent: ChatGPT-User
Allow: /

User-agent: Claude-Web
Allow: /

User-agent: ClaudeBot
Allow: /

User-agent: PerplexityBot
Allow: /

User-agent: Amazonbot
Allow: /

User-agent: anthropic-ai
Allow: /

User-agent: Google-Extended
Allow: /

# === 阻止AI训练(可选 - 引用但不用于训练) ===
# 如果您想被引用但不被用于训练,请取消注释这些
# User-agent: CCBot
# Disallow: /

# User-agent: GPTBot
# Disallow: /  # 阻止聊天和训练

# === 阻止刮削器 ===
User-agent: AhrefsBot
Disallow: /

User-agent: SemrushBot
Disallow: /

User-agent: MJ12bot
Disallow: /

# === 默认 ===
User-agent: *
Allow: /
Disallow: /api/
Disallow: /admin/
Disallow: /auth/
Disallow: /private/
Disallow: /*.json$
Disallow: /*?*

Sitemap: https://yoursite.com/sitemap.xml

Next.js robots.txt

// app/robots.ts
import { MetadataRoute } from 'next';

export default function robots(): MetadataRoute.Robots {
  const baseUrl = process.env.NEXT_PUBLIC_URL || 'https://yoursite.com';

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

站点地图

XML站点地图模板

<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
        xmlns:news="http://www.google.com/schemas/sitemap-news/0.9"
        xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
  <url>
    <loc>https://yoursite.com/</loc>
    <lastmod>2025-01-15</lastmod>
    <changefreq>weekly</changefreq>
    <priority>1.0</priority>
  </url>
  <url>
    <loc>https://yoursite.com/pricing</loc>
    <lastmod>2025-01-10</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.9</priority>
  </url>
  <url>
    <loc>https://yoursite.com/blog/article-slug</loc>
    <lastmod>2025-01-12</lastmod>
    <changefreq>monthly</changefreq>
    <priority>0.8</priority>
    <image:image>
      <image:loc>https://yoursite.com/images/article-image.jpg</image:loc>
    </image:image>
  </url>
</urlset>

Next.js动态站点地图

// app/sitemap.ts
import { MetadataRoute } from 'next';

export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
  const baseUrl = process.env.NEXT_PUBLIC_URL || 'https://yoursite.com';

  // 静态页面
  const staticPages = [
    { url: '/', priority: 1.0, changeFrequency: 'weekly' as const },
    { url: '/pricing', priority: 0.9, changeFrequency: 'monthly' as const },
    { url: '/about', priority: 0.8, changeFrequency: 'monthly' as const },
    { url: '/contact', priority: 0.7, changeFrequency: 'yearly' as const },
  ];

  // 动态页面(例如,博客文章)
  const posts = await getBlogPosts(); // 您的数据获取函数
  const blogPages = posts.map((post) => ({
    url: `/blog/${post.slug}`,
    lastModified: new Date(post.updatedAt),
    changeFrequency: 'monthly' as const,
    priority: 0.8,
  }));

  return [
    ...staticPages.map((page) => ({
      url: `${baseUrl}${page.url}`,
      lastModified: new Date(),
      changeFrequency: page.changeFrequency,
      priority: page.priority,
    })),
    ...blogPages.map((page) => ({
      url: `${baseUrl}${page.url}`,
      lastModified: page.lastModified,
      changeFrequency: page.changeFrequency,
      priority: page.priority,
    })),
  ];
}

站点地图索引(大型站点)

<?xml version="1.0" encoding="UTF-8"?>
<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
  <sitemap>
    <loc>https://yoursite.com/sitemap-pages.xml</loc>
    <lastmod>2025-01-15</lastmod>
  </sitemap>
  <sitemap>
    <loc>https://yoursite.com/sitemap-blog.xml</loc>
    <lastmod>2025-01-14</lastmod>
  </sitemap>
  <sitemap>
    <loc>https://yoursite.com/sitemap-products.xml</loc>
    <lastmod>2025-01-13</lastmod>
  </sitemap>
</sitemapindex>

元标签

基本元标签

<head>
  <!-- 基础 -->
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>页面标题 | 品牌名称</title>
  <meta name="description" content="引人入胜的150-160字符描述,包含关键词和CTA。">

  <!-- 规范(防止重复内容) -->
  <link rel="canonical" href="https://yoursite.com/current-page">

  <!-- 语言 -->
  <html lang="en">
  <meta name="language" content="English">

  <!-- 机器人 -->
  <meta name="robots" content="index, follow">
  <meta name="googlebot" content="index, follow">

  <!-- 作者 -->
  <meta name="author" content="作者名称">

  <!-- 收藏夹图标 -->
  <link rel="icon" href="/favicon.ico" sizes="any">
  <link rel="icon" href="/icon.svg" type="image/svg+xml">
  <link rel="apple-touch-icon" href="/apple-touch-icon.png">
  <link rel="manifest" href="/manifest.webmanifest">
</head>

Open Graph(社交分享)

<!-- Open Graph / Facebook -->
<meta property="og:type" content="website">
<meta property="og:url" content="https://yoursite.com/page">
<meta property="og:title" content="页面标题 - 品牌">
<meta property="og:description" content="社交分享的描述(可以更长)。">
<meta property="og:image" content="https://yoursite.com/og-image.jpg">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="630">
<meta property="og:site_name" content="品牌名称">
<meta property="og:locale" content="en_US">

<!-- 文章特定(博客文章) -->
<meta property="og:type" content="article">
<meta property="article:published_time" content="2025-01-15T08:00:00Z">
<meta property="article:modified_time" content="2025-01-20T10:00:00Z">
<meta property="article:author" content="https://yoursite.com/team/author">
<meta property="article:section" content="Technology">
<meta property="article:tag" content="AI, SEO, Content">

Twitter Cards

<!-- Twitter -->
<meta name="twitter:card" content="summary_large_image">
<meta name="twitter:site" content="@yourbrand">
<meta name="twitter:creator" content="@authorhandle">
<meta name="twitter:title" content="页面标题">
<meta name="twitter:description" content="Twitter的描述(最多200字符)。">
<meta name="twitter:image" content="https://yoursite.com/twitter-image.jpg">

Next.js元数据

// app/layout.tsx
import { Metadata } from 'next';

export const metadata: Metadata = {
  metadataBase: new URL('https://yoursite.com'),
  title: {
    default: '品牌名称',
    template: '%s | 品牌名称',
  },
  description: '您的默认站点描述。',
  keywords: ['keyword1', 'keyword2', 'keyword3'],
  authors: [{ name: '品牌名称', url: 'https://yoursite.com' }],
  creator: '品牌名称',
  publisher: '品牌名称',
  robots: {
    index: true,
    follow: true,
    googleBot: {
      index: true,
      follow: true,
      'max-video-preview': -1,
      'max-image-preview': 'large',
      'max-snippet': -1,
    },
  },
  openGraph: {
    type: 'website',
    locale: 'en_US',
    url: 'https://yoursite.com',
    siteName: '品牌名称',
    title: '品牌名称',
    description: '您的站点描述。',
    images: [
      {
        url: '/og-image.jpg',
        width: 1200,
        height: 630,
        alt: '品牌名称',
      },
    ],
  },
  twitter: {
    card: 'summary_large_image',
    site: '@yourbrand',
    creator: '@yourbrand',
  },
  verification: {
    google: 'google-verification-code',
    yandex: 'yandex-verification-code',
  },
};

// app/blog/[slug]/page.tsx
export async function generateMetadata({ params }): Promise<Metadata> {
  const post = await getPost(params.slug);

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      type: 'article',
      publishedTime: post.publishedAt,
      modifiedTime: post.updatedAt,
      authors: [post.author.name],
      images: [post.coverImage],
    },
  };
}

URL结构

最佳实践

✅ 好的URLs:
/blog/ai-seo-best-practices
/products/pro-plan
/pricing
/about/team

❌ 坏的URLs:
/blog?id=123
/p/12345
/index.php?page=about
/Products/Pro_Plan(不一致的大小写)

URL指南

规则 示例
仅小写 /blog/my-post 不是 /Blog/My-Post
连字符不是下划线 /my-page 不是 /my_page
无尾斜杠 /about 不是 /about/
描述性slugs /pricing 不是 /p
无查询参数内容 /blog/post-title 不是 /blog?id=123
最大3-4级深度 /blog/category/post

重定向配置

// next.config.js
module.exports = {
  async redirects() {
    return [
      // 将旧URL重定向到新URL
      {
        source: '/old-page',
        destination: '/new-page',
        permanent: true, // 301重定向
      },
      // 带通配符的重定向
      {
        source: '/blog/old/:slug',
        destination: '/articles/:slug',
        permanent: true,
      },
      // 尾斜杠重定向
      {
        source: '/:path+/',
        destination: '/:path+',
        permanent: true,
      },
    ];
  },
};

规范URL

实施

<!-- 即使对于主URL,也总是包括规范 -->
<link rel="canonical" href="https://yoursite.com/current-page">

何时使用

✅ 使用规范:
- 每个页面(即使只有版本存在)
- 分页内容(指向第1页或使用rel=prev/next)
- 不改变内容的URL参数(?utm_source=...)
- HTTP与HTTPS(规范到HTTPS)
- www与非www(选择一个,规范到它)

示例:/products?sort=price应该规范到/products

Next.js规范

// 在元数据中自动
export const metadata: Metadata = {
  alternates: {
    canonical: '/current-page',
  },
};

安全头

基本头

// next.config.js
const securityHeaders = [
  {
    key: 'X-DNS-Prefetch-Control',
    value: 'on',
  },
  {
    key: 'Strict-Transport-Security',
    value: 'max-age=63072000; includeSubDomains; preload',
  },
  {
    key: 'X-Frame-Options',
    value: 'SAMEORIGIN',
  },
  {
    key: 'X-Content-Type-Options',
    value: 'nosniff',
  },
  {
    key: 'Referrer-Policy',
    value: 'strict-origin-when-cross-origin',
  },
  {
    key: 'Permissions-Policy',
    value: 'camera=(), microphone=(), geolocation=()',
  },
];

module.exports = {
  async headers() {
    return [
      {
        source: '/:path*',
        headers: securityHeaders,
      },
    ];
  },
};

核心网页指标

目标指标

指标 良好 需要改进
LCP(最大内容绘制) ≤2.5s ≤4.0s >4.0s
INP(交互到下一个绘制) ≤200ms ≤500ms >500ms
CLS(累积布局偏移) ≤0.1 ≤0.25 >0.25

优化清单

## LCP(加载)
- [ ] 优化最大图片(WebP, 适当尺寸)
- [ ] 预加载关键资产
- [ ] 使用CDN静态资产
- [ ] 启用压缩(gzip/brotli)
- [ ] 最小化渲染阻塞资源

## INP(交互性)
- [ ] 最小化JavaScript执行时间
- [ ] 分解长任务
- [ ] 使用Web Workers进行重型计算
- [ ] 优化事件处理程序
- [ ] 延迟加载非关键JS

## CLS(视觉稳定性)
- [ ] 设置图片/视频尺寸
- [ ] 为动态内容保留空间
- [ ] 避免在现有内容上方插入内容
- [ ] 使用变换进行动画
- [ ] 预加载字体

Next.js性能

// 图像优化
import Image from 'next/image';

<Image
  src="/hero.jpg"
  alt="英雄图片"
  width={1200}
  height={630}
  priority // 预加载LCP
  placeholder="blur"
  blurDataURL={blurDataUrl}
/>

// 字体优化
import { Inter } from 'next/font/google';

const inter = Inter({
  subsets: ['latin'],
  display: 'swap', // 防止FOIT
});

// 动态导入
import dynamic from 'next/dynamic';

const HeavyComponent = dynamic(() => import('./HeavyComponent'), {
  loading: () => <Skeleton />,
  ssr: false, // 如果需要,仅限客户端
});

内部链接

结构

## 链接架构

首页
├── /pricing (1点击)
├── /features (1点击)
├── /blog (1点击)
│   ├── /blog/category-1 (2点击)
│   │   └── /blog/category-1/post (3点击)
│   └── /blog/category-2 (2点击)
└── /about (1点击)

规则:每个页面在首页的3次点击内

最佳实践

✅ 做:
- 使用描述性锚文本
- 在内容中上下文链接
- 创建主题中心页面
- 在文章末尾链接相关内容
- 使用面包屑导航

❌ 避免:
- “点击这里”作为锚文本
- 孤立页面(无内部链接)
- 每页太多链接(>100)
- 损坏的内部链接
- 重定向链

面包屑

// components/Breadcrumbs.tsx
import Link from 'next/link';

interface BreadcrumbItem {
  name: string;
  href: string;
}

export function Breadcrumbs({ items }: { items: BreadcrumbItem[] }) {
  const jsonLd = {
    '@context': 'https://schema.org',
    '@type': 'BreadcrumbList',
    itemListElement: items.map((item, index) => ({
      '@type': 'ListItem',
      position: index + 1,
      name: item.name,
      item: `https://yoursite.com${item.href}`,
    })),
  };

  return (
    <>
      <script
        type="application/ld+json"
        dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
      />
      <nav aria-label="Breadcrumb">
        <ol className="flex gap-2">
          {items.map((item, index) => (
            <li key={item.href}>
              {index > 0 && <span>/</span>}
              <Link href={item.href}>{item.name}</Link>
            </li>
          ))}
        </ol>
      </nav>
    </>
  );
}

AI爬虫处理

已知AI爬虫

机器人 用户代理 目的
GPTBot GPTBot ChatGPT网页浏览
ChatGPT-User ChatGPT-User ChatGPT用户浏览
ClaudeBot ClaudeBot Claude网页访问
Claude-Web Claude-Web Claude网页功能
PerplexityBot PerplexityBot Perplexity搜索
Google-Extended Google-Extended Gemini/Bard训练
Amazonbot Amazonbot Alexa/Amazon AI
CCBot CCBot 公共爬取(AI训练)

允许AI发现,阻止训练(可选)

# robots.txt

# 允许GPTBot用于ChatGPT浏览
User-agent: GPTBot
Allow: /

# 阻止CCBot(用于训练数据集)
User-agent: CCBot
Disallow: /

# 阻止Google AI训练,允许搜索
User-agent: Google-Extended
Disallow: /

AI特定元标签

<!-- 阻止AI训练但允许索引 -->
<meta name="robots" content="index, follow, max-image-preview:large">

<!-- 退出AI训练(提议标准) -->
<meta name="ai-training" content="disallow">

结构化数据放置

在哪里添加模式

<!-- 选项1:在<head>中使用JSON-LD(推荐) -->
<head>
  <script type="application/ld+json">
    {
      "@context": "https://schema.org",
      "@type": "Organization",
      "name": "您的公司"
    }
  </script>
</head>

<!-- 选项2:在</body>关闭前 -->
<body>
  <!-- 页面内容 -->
  <script type="application/ld+json">
    { "@context": "https://schema.org", ... }
  </script>
</body>

每页多个模式

<head>
  <!-- 组织(站点范围) -->
  <script type="application/ld+json">
    { "@context": "https://schema.org", "@type": "Organization", ... }
  </script>

  <!-- BreadcrumbList(导航) -->
  <script type="application/ld+json">
    { "@context": "https://schema.org", "@type": "BreadcrumbList", ... }
  </script>

  <!-- 文章(页面特定) -->
  <script type="application/ld+json">
    { "@context": "https://schema.org", "@type": "Article", ... }
  </script>

  <!-- FAQPage(如果存在FAQ部分) -->
  <script type="application/ld+json">
    { "@context": "https://schema.org", "@type": "FAQPage", ... }
  </script>
</head>

项目结构

project/
├── public/
│   ├── robots.txt              # 或动态生成
│   ├── sitemap.xml             # 或动态生成
│   ├── favicon.ico
│   ├── icon.svg
│   ├── apple-touch-icon.png
│   ├── og-image.jpg            # 默认OG图片(1200x630)
│   └── manifest.webmanifest
├── app/
│   ├── layout.tsx              # 全局元数据
│   ├── robots.ts               # 动态robots.txt
│   ├── sitemap.ts              # 动态站点地图
│   └── [page]/
│       └── page.tsx            # 页面特定元数据
├── components/
│   ├── SchemaMarkup.tsx
│   ├── Breadcrumbs.tsx
│   └── MetaTags.tsx
└── lib/
    ├── schema.ts               # 模式生成器
    └── seo.ts                  # SEO工具

验证和提交

搜索控制台设置

# 验证所有权方法
1. HTML文件上传(google*.html到public/)
2. Meta标签(添加到<head>)
3. DNS TXT记录
4. Google Analytics(如果已安装)

提交站点地图

1. Google搜索控制台
   - 站点地图 → 添加新站点地图 → yoursite.com/sitemap.xml

2. Bing网站管理员工具
   - 站点地图 → 提交站点地图

3. Yandex网站管理员(如果相关)
   - 索引 → 站点地图文件

清单

## 技术SEO清单

### robots.txt
- [ ] 允许搜索引擎
- [ ] 允许AI机器人(GPTBot, ClaudeBot, PerplexityBot)
- [ ] 阻止admin/private区域
- [ ] 包含站点地图引用
- [ ] 使用Google的robots.txt测试器测试

### 站点地图
- [ ] 包含所有可索引页面
- [ ] 排除noindex页面
- [ ] 包含lastmod日期
- [ ] 提交给搜索控制台
- [ ] 在内容更改时自动更新

### 元标签
- [ ] 每个页面都有独特的标题(50-60字符)
- [ ] 每个页面都有独特的描述(150-160字符)
- [ ] 每个页面都有规范URL
- [ ] Open Graph标签
- [ ] Twitter Card标签

### URL结构
- [ ] 小写,连字符
- [ ] 描述性slugs
- [ ] 无查询参数内容
- [ ] 移动内容的301重定向
- [ ] 无损坏链接

### 性能
- [ ] LCP < 2.5s
- [ ] INP < 200ms
- [ ] CLS < 0.1
- [ ] 启用HTTPS
- [ ] 配置安全头

### 结构化数据
- [ ] 组织模式(首页)
- [ ] BreadcrumbList(所有页面)
- [ ] 文章模式(博客文章)
- [ ] FAQ模式(FAQ部分)
- [ ] 使用Rich Results Test验证

快速参考

文件清单

public/
├── robots.txt          ✓ 必需
├── sitemap.xml         ✓ 必需
├── favicon.ico         ✓ 必需
├── og-image.jpg        ✓ 必需(1200x630)
└── manifest.json       ○ 推荐

元标签长度

标签 长度
标题 50-60个字符
描述 150-160个字符
OG标题 60-90个字符
OG描述 200个字符
Twitter描述 200个字符

图片尺寸

图片 尺寸
OG图片 1200 x 630
Twitter图片 1200 x 628
收藏夹图标 32 x 32
Apple Touch图标 180 x 180