Files
john 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
Add TKMind platform extensions, H5/MindSpace stack, and deployment tooling.
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>
2026-06-14 21:30:20 +08:00

313 lines
8.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
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 CardX / 微博)
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,
});
}
```