4e21ca937a
Deploy Documentation / deploy (push) Has been cancelled
Canary / Prepare Version (push) Has been cancelled
Canary / build-cli (push) Has been cancelled
Canary / Upload Install Script (push) Has been cancelled
Canary / bundle-desktop (push) Has been cancelled
Canary / bundle-desktop-intel (push) Has been cancelled
Canary / bundle-desktop-linux (push) Has been cancelled
Canary / bundle-desktop-windows (push) Has been cancelled
Canary / bundle-desktop-windows-cuda (push) Has been cancelled
Canary / Release (push) Has been cancelled
Unused Dependencies / machete (push) Has been cancelled
CI / changes (push) Has been cancelled
CI / Check Rust Code Format (push) Has been cancelled
CI / Build and Test Rust Project (push) Has been cancelled
CI / Build Rust Project on Windows (push) Has been cancelled
CI / Check MSRV (push) Has been cancelled
CI / Lint Rust Code (push) Has been cancelled
CI / Check Generated Schemas are Up-to-Date (push) Has been cancelled
CI / Test and Lint Electron Desktop App (push) Has been cancelled
CI / H5 Plaza Tests and Build (push) Has been cancelled
Live Provider Tests / check-fork (push) Has been cancelled
Live Provider Tests / changes (push) Has been cancelled
Live Provider Tests / Build Binary (push) Has been cancelled
Live Provider Tests / Smoke Tests (push) Has been cancelled
Live Provider Tests / Smoke Tests (Code Execution) (push) Has been cancelled
Live Provider Tests / Compaction Tests (push) Has been cancelled
Live Provider Tests / goose server HTTP integration tests (push) Has been cancelled
Publish Ask AI Bot Docker Image / docker (push) Has been cancelled
Publish Docker Image / docker (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Fork goose with custom MCP widgets, platform extensions (aider, git, web, search), MindSpace H5 backend/frontend, Plaza/Ops UIs, and deploy scripts for tkmind.cn. Co-authored-by: Cursor <cursoragent@cursor.com>
313 lines
8.3 KiB
Markdown
313 lines
8.3 KiB
Markdown
---
|
||
sidebar_position: 8
|
||
title: SEO 策略
|
||
sidebar_label: SEO
|
||
description: Plaza 的 SEO 架构、Open Graph 规范、sitemap 生成、静态化策略和爬虫优化
|
||
---
|
||
|
||
# SEO 策略
|
||
|
||
> **权威文档**:本页是 Plaza 所有 HTML meta、Open Graph、JSON-LD、robots 规范的唯一来源;[03-frontend](./03-frontend) 通过 `lib/metadata.ts` 引用此处约定。
|
||
|
||
## 核心目标
|
||
|
||
- 广场每个帖子、每个分类页、每个用户主页都能被搜索引擎完整收录。
|
||
- 微信/微博/钉钉等社交平台分享时展示封面图、标题和摘要。
|
||
- 新帖发布后 24 小时内可被 Googlebot 和百度蜘蛛发现。
|
||
|
||
---
|
||
|
||
## 渲染策略
|
||
|
||
| 页面 | 渲染方式 | 缓存策略 | 说明 |
|
||
| --- | --- | --- | --- |
|
||
| /plaza 首页 | SSR(`force-dynamic`) | `fetch` revalidate 60s + Redis Feed 缓存 | 服务端每次渲染,API 层缓存热门列表 |
|
||
| /plaza/cat/:slug 分类 | SSR(`force-dynamic`) | `fetch` revalidate 300s | 分类元数据预生成 `generateStaticParams` |
|
||
| /plaza/p/:id 帖子详情 | SSR(`force-dynamic`) | `no-store` | 互动数实时显示 |
|
||
| /u/:slug 用户主页 | SSR | `revalidate: 300` | 5 分钟 ISR |
|
||
| 404 页面 | 静态 | - | Next.js 默认 |
|
||
|
||
**说明**:Plaza 首页/分类页使用 `dynamic = 'force-dynamic'`,通过 `lib/api.ts` 的 `next.revalidate` 控制上游 API 缓存,而非 Next.js 页面级 ISR。用户主页保留 `revalidate: 300`。加载态使用 `loading.tsx` + `PostGridSkeleton`。
|
||
|
||
---
|
||
|
||
## HTML meta 规范
|
||
|
||
### 帖子详情页(最重要)
|
||
|
||
```typescript
|
||
// app/plaza/p/[id]/page.tsx
|
||
export async function generateMetadata({ params }: { params: { id: string } }): Promise<Metadata> {
|
||
const post = await fetchPost(params.id);
|
||
|
||
if (!post) {
|
||
return { title: 'Page Not Found' };
|
||
}
|
||
|
||
const url = `https://go.tkmind.cn/plaza/p/${post.id}`;
|
||
const image = post.cover_url || 'https://go.tkmind.cn/og-default.png';
|
||
|
||
return {
|
||
title: `${post.title} - Plaza | MindSpace`,
|
||
description: post.summary || `${post.author.display_name} 用 MindSpace 创作的作品`,
|
||
keywords: post.tags.join(', '),
|
||
|
||
// Open Graph(微信、Facebook、钉钉)
|
||
openGraph: {
|
||
title: post.title,
|
||
description: post.summary,
|
||
url,
|
||
siteName: 'MindSpace Plaza',
|
||
images: [
|
||
{
|
||
url: image,
|
||
width: 1200,
|
||
height: 630,
|
||
alt: post.title,
|
||
},
|
||
],
|
||
type: 'article',
|
||
publishedTime: post.published_at,
|
||
authors: [`https://go.tkmind.cn/u/${post.author.slug}`],
|
||
tags: post.tags,
|
||
},
|
||
|
||
// Twitter Card(X / 微博)
|
||
twitter: {
|
||
card: 'summary_large_image',
|
||
title: post.title,
|
||
description: post.summary,
|
||
images: [image],
|
||
creator: `@${post.author.slug}`,
|
||
},
|
||
|
||
// 规范 URL(防止重复内容)
|
||
alternates: {
|
||
canonical: url,
|
||
},
|
||
|
||
// 爬虫指令
|
||
robots: {
|
||
index: true,
|
||
follow: true,
|
||
},
|
||
};
|
||
}
|
||
```
|
||
|
||
### 用户主页
|
||
|
||
```typescript
|
||
openGraph: {
|
||
type: 'profile',
|
||
firstName: user.display_name,
|
||
username: user.slug,
|
||
images: [{ url: user.avatar_url, width: 400, height: 400 }],
|
||
}
|
||
```
|
||
|
||
### 广场首页
|
||
|
||
```typescript
|
||
openGraph: {
|
||
type: 'website',
|
||
title: 'Plaza - 发现 AI 创作的精彩内容',
|
||
description: '浏览来自全球用户用 MindSpace 创作的报告、作品和页面',
|
||
images: [{ url: 'https://go.tkmind.cn/plaza-og.png', width: 1200, height: 630 }],
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 结构化数据(JSON-LD)
|
||
|
||
帖子详情页在 `<head>` 中注入 Article Schema:
|
||
|
||
```typescript
|
||
// app/plaza/p/[id]/page.tsx
|
||
export default async function PostPage({ params }) {
|
||
const post = await fetchPost(params.id);
|
||
|
||
const jsonLd = {
|
||
'@context': 'https://schema.org',
|
||
'@type': 'Article',
|
||
headline: post.title,
|
||
description: post.summary,
|
||
image: post.cover_url,
|
||
datePublished: post.published_at,
|
||
author: {
|
||
'@type': 'Person',
|
||
name: post.author.display_name,
|
||
url: `https://go.tkmind.cn/u/${post.author.slug}`,
|
||
},
|
||
publisher: {
|
||
'@type': 'Organization',
|
||
name: 'MindSpace',
|
||
logo: {
|
||
'@type': 'ImageObject',
|
||
url: 'https://go.tkmind.cn/logo.png',
|
||
},
|
||
},
|
||
};
|
||
|
||
return (
|
||
<>
|
||
<script
|
||
type="application/ld+json"
|
||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd) }}
|
||
/>
|
||
{/* 页面内容 */}
|
||
</>
|
||
);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Sitemap 生成
|
||
|
||
Next.js 动态生成 sitemap,百度蜘蛛和 Googlebot 可以发现所有公开内容。
|
||
|
||
```typescript
|
||
// app/sitemap.ts
|
||
export default async function sitemap(): Promise<MetadataRoute.Sitemap> {
|
||
const baseUrl = 'https://go.tkmind.cn';
|
||
|
||
// 静态页面
|
||
const staticPages = [
|
||
{ url: `${baseUrl}/plaza`, lastModified: new Date(), changeFrequency: 'hourly', priority: 1.0 },
|
||
];
|
||
|
||
// 分类页
|
||
const categories = await fetchCategories();
|
||
const categoryPages = categories.map((cat) => ({
|
||
url: `${baseUrl}/plaza/cat/${cat.slug}`,
|
||
lastModified: new Date(),
|
||
changeFrequency: 'hourly' as const,
|
||
priority: 0.8,
|
||
}));
|
||
|
||
// 帖子详情页(最近 1000 条已发布帖子)
|
||
const posts = await fetchRecentPosts(1000);
|
||
const postPages = posts.map((post) => ({
|
||
url: `${baseUrl}/plaza/p/${post.id}`,
|
||
lastModified: new Date(post.updated_at),
|
||
changeFrequency: 'weekly' as const,
|
||
priority: 0.6,
|
||
}));
|
||
|
||
// 用户主页(有发布内容的用户)
|
||
const users = await fetchActiveCreators(500);
|
||
const userPages = users.map((user) => ({
|
||
url: `${baseUrl}/u/${user.slug}`,
|
||
lastModified: new Date(user.last_post_at),
|
||
changeFrequency: 'weekly' as const,
|
||
priority: 0.5,
|
||
}));
|
||
|
||
return [...staticPages, ...categoryPages, ...postPages, ...userPages];
|
||
}
|
||
```
|
||
|
||
Sitemap URL:`https://go.tkmind.cn/sitemap.xml`,在 `robots.txt` 中声明。
|
||
|
||
---
|
||
|
||
## robots.txt
|
||
|
||
```typescript
|
||
// app/robots.ts
|
||
export default function robots(): MetadataRoute.Robots {
|
||
return {
|
||
rules: [
|
||
{
|
||
userAgent: '*',
|
||
allow: ['/plaza', '/u/'],
|
||
disallow: ['/ops', '/api', '/_next'],
|
||
},
|
||
],
|
||
sitemap: 'https://go.tkmind.cn/sitemap.xml',
|
||
};
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## OG 封面图生成
|
||
|
||
帖子必须有封面图才能在社交平台获得好的分享展示效果。
|
||
|
||
### 策略(优先级从高到低)
|
||
|
||
1. **创作者手动上传封面**:发布到广场时可以选择或上传封面图。
|
||
2. **publication 的封面**:MindSpace 发布时生成的页面封面。
|
||
3. **自动生成 OG 图**:用 `@vercel/og` 或 Next.js Image Response API 动态生成。
|
||
|
||
### 动态 OG 图生成(兜底)
|
||
|
||
```typescript
|
||
// app/plaza/p/[id]/opengraph-image.tsx
|
||
import { ImageResponse } from 'next/og';
|
||
|
||
export default async function Image({ params }: { params: { id: string } }) {
|
||
const post = await fetchPost(params.id);
|
||
|
||
return new ImageResponse(
|
||
(
|
||
<div
|
||
style={{
|
||
width: '1200px',
|
||
height: '630px',
|
||
background: 'linear-gradient(135deg, #667eea 0%, #764ba2 100%)',
|
||
display: 'flex',
|
||
flexDirection: 'column',
|
||
justifyContent: 'center',
|
||
padding: '60px',
|
||
}}
|
||
>
|
||
<div style={{ color: 'white', fontSize: '48px', fontWeight: 'bold', marginBottom: '20px' }}>
|
||
{post.title}
|
||
</div>
|
||
<div style={{ color: 'rgba(255,255,255,0.8)', fontSize: '24px' }}>
|
||
{post.author.display_name} · MindSpace Plaza
|
||
</div>
|
||
</div>
|
||
),
|
||
{ width: 1200, height: 630 },
|
||
);
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## 页面加载性能与 SEO
|
||
|
||
Google Core Web Vitals 是搜索排名因素,以下措施保证达标:
|
||
|
||
| 措施 | 目标 |
|
||
| --- | --- |
|
||
| 首屏 SSR 直出 HTML | LCP < 2.5s |
|
||
| 图片使用 `next/image` 自动 WebP + lazy | CLS < 0.1 |
|
||
| 字体使用 `next/font` 避免布局偏移 | CLS < 0.1 |
|
||
| 帖子列表图片预加载第一屏 | LCP < 2.5s |
|
||
| PostCard 骨架屏占位 | CLS < 0.1 |
|
||
|
||
---
|
||
|
||
## 百度 SEO 特别注意
|
||
|
||
- 百度蜘蛛对 JavaScript 渲染支持差,**必须服务端渲染**,不能依赖客户端 hydration 生成内容。
|
||
- 百度不抓取 `noindex` 页面,帖子详情必须确保没有误加 `noindex`。
|
||
- 百度对外链有延迟,新帖发布后主动通过百度搜索资源平台 API 推送 URL。
|
||
|
||
```typescript
|
||
// 新帖发布后,主动推送到百度
|
||
async function pingBaidu(url: string) {
|
||
await fetch('http://data.zz.baidu.com/urls?site=go.tkmind.cn&token=YOUR_TOKEN', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'text/plain' },
|
||
body: url,
|
||
});
|
||
}
|
||
```
|