feat: Introduce FAQ and keywords fields to Posts collection for SEO, update payload types, and add related documentation.
Some checks failed
Deploy to Coolify / deploy (push) Failing after 11m57s
Some checks failed
Deploy to Coolify / deploy (push) Failing after 11m57s
This commit is contained in:
202
docs/CMS-Implementation-Plan-FAQ-Keywords.md
Normal file
202
docs/CMS-Implementation-Plan-FAQ-Keywords.md
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
# PayloadCMS Implementation Plan: FAQ & Keywords Fields
|
||||||
|
|
||||||
|
> **目的**:在 `~/Dev/website-ricenoodletw-cms/` 專案中新增 `faq` 和 `keywords` 欄位
|
||||||
|
>
|
||||||
|
> **這份文件供另一個 Agent 在 CMS workspace 中執行**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 概述
|
||||||
|
|
||||||
|
在 PayloadCMS 的 `posts` collection 新增兩個欄位,讓每篇文章可以有獨立的 FAQ 和關鍵字,前端會自動產生對應的 JSON-LD 結構化資料。
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 步驟 1:找到 Posts Collection 設定檔
|
||||||
|
|
||||||
|
找到 `posts` collection 的設定檔,通常在:
|
||||||
|
- `src/collections/Posts.ts`
|
||||||
|
- `src/collections/posts.ts`
|
||||||
|
- `collections/Posts.ts`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 步驟 2:新增 FAQ 欄位
|
||||||
|
|
||||||
|
在 `fields` 陣列中新增:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
name: 'faq',
|
||||||
|
type: 'array',
|
||||||
|
label: '文章專屬 FAQ',
|
||||||
|
admin: {
|
||||||
|
description: '為這篇文章新增 FAQ,將自動產生 FAQPage JSON-LD 結構化資料,有助於 SEO 和 Perplexity 引用',
|
||||||
|
condition: (data) => data?.status === 'published' || true, // 可選:條件顯示
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'question',
|
||||||
|
type: 'text',
|
||||||
|
label: '問題',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
placeholder: '例如:榕樹下米苔目為什麼有兩家?',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'answer',
|
||||||
|
type: 'textarea',
|
||||||
|
label: '答案',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
placeholder: '提供完整且有引用價值的答案...',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 步驟 3:新增 Keywords 欄位
|
||||||
|
|
||||||
|
在 `fields` 陣列中新增:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
{
|
||||||
|
name: 'keywords',
|
||||||
|
type: 'array',
|
||||||
|
label: 'SEO 關鍵字',
|
||||||
|
admin: {
|
||||||
|
description: '文章關鍵字標籤,用於 JSON-LD 結構化資料',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'keyword',
|
||||||
|
type: 'text',
|
||||||
|
label: '關鍵字',
|
||||||
|
required: true,
|
||||||
|
admin: {
|
||||||
|
placeholder: '例如:台東美食',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 步驟 4:完整範例
|
||||||
|
|
||||||
|
以下是完整的欄位定義,可直接複製貼上:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 加在 Posts collection 的 fields 陣列中
|
||||||
|
// 建議放在 content 欄位之後,meta 欄位之前
|
||||||
|
|
||||||
|
// FAQ 欄位
|
||||||
|
{
|
||||||
|
name: 'faq',
|
||||||
|
type: 'array',
|
||||||
|
label: '文章專屬 FAQ',
|
||||||
|
admin: {
|
||||||
|
description: '每題 FAQ 會自動產生 FAQPage JSON-LD,有助於 Perplexity 等 AI 搜尋引擎引用',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'question',
|
||||||
|
type: 'text',
|
||||||
|
label: '問題',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'answer',
|
||||||
|
type: 'textarea',
|
||||||
|
label: '答案',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
// Keywords 欄位
|
||||||
|
{
|
||||||
|
name: 'keywords',
|
||||||
|
type: 'array',
|
||||||
|
label: 'SEO 關鍵字',
|
||||||
|
admin: {
|
||||||
|
description: '用於 Article schema 的 keywords 屬性',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'keyword',
|
||||||
|
type: 'text',
|
||||||
|
label: '關鍵字',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 步驟 5:資料庫遷移
|
||||||
|
|
||||||
|
修改 collection 後,根據你的設定:
|
||||||
|
|
||||||
|
### 如果使用 MongoDB
|
||||||
|
通常不需要額外遷移,新欄位會自動可用。
|
||||||
|
|
||||||
|
### 如果使用 Postgres/SQLite
|
||||||
|
可能需要執行:
|
||||||
|
```bash
|
||||||
|
npm run payload migrate:create
|
||||||
|
npm run payload migrate
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 步驟 6:驗證
|
||||||
|
|
||||||
|
1. 重啟 CMS 開發伺服器
|
||||||
|
2. 進入後台編輯任一文章
|
||||||
|
3. 確認看到「文章專屬 FAQ」和「SEO 關鍵字」欄位
|
||||||
|
4. 新增測試資料並儲存
|
||||||
|
5. 透過 API 確認資料正確回傳:
|
||||||
|
```
|
||||||
|
GET /api/posts?limit=1&depth=1
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## API 回傳格式
|
||||||
|
|
||||||
|
新增欄位後,API 會回傳:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"id": "...",
|
||||||
|
"title": "文章標題",
|
||||||
|
"faq": [
|
||||||
|
{
|
||||||
|
"question": "問題一",
|
||||||
|
"answer": "答案一"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"question": "問題二",
|
||||||
|
"answer": "答案二"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"keywords": [
|
||||||
|
{ "keyword": "台東美食" },
|
||||||
|
{ "keyword": "米苔目" }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 相關文件
|
||||||
|
|
||||||
|
- 前端 TypeScript 型別需同步更新:`src/types/blog.ts`
|
||||||
|
- 前端 JSON-LD 產生邏輯:`src/pages/[category]/[slug].astro`
|
||||||
@@ -140,6 +140,50 @@ export const Posts: CollectionConfig<'posts'> = {
|
|||||||
],
|
],
|
||||||
label: 'Meta',
|
label: 'Meta',
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: 'SEO 強化',
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'faq',
|
||||||
|
type: 'array',
|
||||||
|
label: '文章專屬 FAQ',
|
||||||
|
admin: {
|
||||||
|
description:
|
||||||
|
'每題 FAQ 會自動產生 FAQPage JSON-LD,有助於 Perplexity 等 AI 搜尋引擎引用',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'question',
|
||||||
|
type: 'text',
|
||||||
|
label: '問題',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'answer',
|
||||||
|
type: 'textarea',
|
||||||
|
label: '答案',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'keywords',
|
||||||
|
type: 'array',
|
||||||
|
label: 'SEO 關鍵字',
|
||||||
|
admin: {
|
||||||
|
description: '用於 Article schema 的 keywords 屬性',
|
||||||
|
},
|
||||||
|
fields: [
|
||||||
|
{
|
||||||
|
name: 'keyword',
|
||||||
|
type: 'text',
|
||||||
|
label: '關鍵字',
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
{
|
{
|
||||||
name: 'meta',
|
name: 'meta',
|
||||||
label: 'SEO',
|
label: 'SEO',
|
||||||
|
|||||||
@@ -233,6 +233,25 @@ export interface Post {
|
|||||||
};
|
};
|
||||||
relatedPosts?: (string | Post)[] | null;
|
relatedPosts?: (string | Post)[] | null;
|
||||||
categories?: (string | Category)[] | null;
|
categories?: (string | Category)[] | null;
|
||||||
|
/**
|
||||||
|
* 每題 FAQ 會自動產生 FAQPage JSON-LD,有助於 Perplexity 等 AI 搜尋引擎引用
|
||||||
|
*/
|
||||||
|
faq?:
|
||||||
|
| {
|
||||||
|
question: string;
|
||||||
|
answer: string;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
|
/**
|
||||||
|
* 用於 Article schema 的 keywords 屬性
|
||||||
|
*/
|
||||||
|
keywords?:
|
||||||
|
| {
|
||||||
|
keyword: string;
|
||||||
|
id?: string | null;
|
||||||
|
}[]
|
||||||
|
| null;
|
||||||
meta?: {
|
meta?: {
|
||||||
title?: string | null;
|
title?: string | null;
|
||||||
/**
|
/**
|
||||||
@@ -1136,6 +1155,19 @@ export interface PostsSelect<T extends boolean = true> {
|
|||||||
content?: T;
|
content?: T;
|
||||||
relatedPosts?: T;
|
relatedPosts?: T;
|
||||||
categories?: T;
|
categories?: T;
|
||||||
|
faq?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
question?: T;
|
||||||
|
answer?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
|
keywords?:
|
||||||
|
| T
|
||||||
|
| {
|
||||||
|
keyword?: T;
|
||||||
|
id?: T;
|
||||||
|
};
|
||||||
meta?:
|
meta?:
|
||||||
| T
|
| T
|
||||||
| {
|
| {
|
||||||
|
|||||||
Reference in New Issue
Block a user