模型化 Croct 內容
設計元件和插槽,編寫它們的結構,並填入隨著模型演進而保持有效的內容定義。結構所能表達的一切也都能在儀表板視覺編輯器中實現;JSON 是相同的模型,只是以手寫方式完成。
心智模型
| 概念 | 說明 | 範圍 |
|---|---|---|
| 元件 (Component) | 一個具名、可重複使用的結構。只有 structure 和 union 可以成為元件(頂層結構)。 | 可在不同插槽和其他元件間重複使用 |
| 常規元件 | 具有固定屬性集的 structure。 | |
| 聯合元件 | 最多 10 個常規元件的 union;編輯器會為每個內容挑選一個變體。 | |
| 插槽 (Slot) | 應用程式中的佔位符(例如主視覺、公告列),與一個元件繫結。為每個語言環境保留預設內容。 | 與上下文相關;一個元件可以支援多個插槽 |
| 內容定義 | 包含結構實際值的 JSON,可以是靜態或動態 (CQL) 值。 |
內容層次,從底層到頂層:插槽預設內容(當沒有符合的體驗或實驗、對機器人過濾排除的機器人、靜態渲染以及發生錯誤時顯示)-> 體驗內容(依受眾而定)-> 實驗內容(依變體而定,至少兩個變體)-> 內容群組(在體驗或實驗變體內,為子區段提供的額外變化)。備援內容存在於應用程式的原始碼中,並在擷取失敗或服務暫停時渲染;CLI 會下載插槽預設內容作為備援。
決定形狀
| 如果你需要... | 使用 |
|---|---|
| 一個固定佈局(所有地方都有相同的欄位) | 常規元件 (structure) |
| 編輯器可以在其中選擇的變化(文字橫幅 vs 圖片橫幅 vs 表單橫幅) | 聯合元件,參考常規元件 |
| 在多處保持一致(例如在各地使用的一個 CTA 按鈕) | 一個獨立的元件,用 {"type": "reference", "id": "..."} 嵌入 |
| 在一個地方具有彈性(例如標題 + 圖片對) | 巢狀 structure 屬性或原始屬性,而不是一個新元件 |
| 一個頁面有數個獨立區塊 | 每個區塊一個元件和一個插槽,而不是一個巨型元件 |
| 一組預定義的選項 | 帶有 choices 的 text(列舉) |
| 圖片、影片、音訊或文件上傳 | 參考 @croct/file(檔案上限為 5 MB;對於較長的影片,請考慮使用 url 文字屬性) |
| 在工具列編輯器中編輯的格式化文字 | 參考 @croct/richText |
| 在純文字欄位中進行輕量格式化 | text + 應用程式中的 Markdown 解析器(請參閱下方的 Markdown 部分) |
| 僅用於計算其他值的值(例如動態變數) | 具有 "private": true 的屬性 |
文件中的經驗法則:問自己「我需要彈性還是一致性?」彈性 -> 結構屬性。一致性 -> 新元件。
工作流程
- 列出頁面的區塊;每個獨立放置的區塊成為一個插槽。
- 對於每個插槽,選擇一個常規或聯合元件。在結構旨在保持一致的地方重複使用現有元件。
- 編寫結構:具有
type、label、description、position和optional(當內容可以不存在時)的屬性。根據實際 UI 的限制新增驗證(maximumLength、minimum、pattern、allowedTypes、列表上的maximumLength)。 - 在新增巢狀結構之前檢查限制(如下)。計算複雜度分數。
- 為每個插槽和每個支援的語言環境編寫預設內容定義。
- 如果元件已在使用了,在進行重大變更時預期會有一個新版本;在更新受影響的內容後,在應用程式中提升插槽版本(請參閱版本控制)。
結構骨架
一個常規元件是一個 structure。每個屬性將其結構包裝在 type 中:
{
"type": "structure",
"title": "CTA 按鈕",
"description": "一個連結到頁面的行動召喚按鈕。",
"attributes": {
"label": {
"label": "標籤",
"description": "按鈕上顯示的文字。",
"position": 0,
"type": {
"type": "text"
}
},
"link": {
"label": "連結",
"description": "要連結到的頁面 URL。",
"position": 1,
"type": {
"type": "text"
}
}
}
}
一個聯合元件將元件 ID 對應到參考。鍵必須等於被參考的 ID:
{
"type": "union",
"types": {
"text-hero": {"type": "reference", "id": "text-hero"},
"image-hero": {"type": "reference", "id": "image-hero"}
}
}
在應用程式中,聯合插槽內容是一個區分聯合:每個變體都有一個設定為元件 ID(上述的 text-hero 或 image-hero)的 _type 屬性。根據 _type 進行分支以渲染它;請參閱 croct-integrate-sdk 技能。
屬性類型一覽
| 儀表板類型 | 結構 JSON |
|---|---|
| 文字 | {"type": "text"} (+ minimumLength、maximumLength、pattern) |
| 多行文字 | {"type": "text", "format": "multiline"} |
| URL | {"type": "text", "format": "url"} |
| 顏色 | {"type": "text", "format": "color"} |
| 日期/時間 | {"type": "text", "format": "instant"} (也支援 local-date、local-time、local-date-time、zoned-date-time) |
| 列舉 | {"type": "text", "choices": {"left": {"label": "左"}}} |
| 富文本 | {"type": "reference", "id": "@croct/richText", "properties": {}} |
| 檔案 | {"type": "reference", "id": "@croct/file", "properties": {}} |
| 數字 | {"type": "number"} (+ integer、minimum、maximum) |
| 布林 | {"type": "boolean"} (+ label.true、label.false、default) |
| 列表 | {"type": "list", "items": {...}} (+ itemLabel、minimumLength、maximumLength) |
| 結構 | {"type": "structure", "attributes": {...}} |
| 元件 | {"type": "reference", "id": "<元件-id>"} |
format 和 choices 不能與除 type 之外的任何其他文字屬性結合。完整的屬性列表、預設值和限制:references/schema.md。
結構限制
| 限制 | 值 |
|---|---|
| 每個結構的屬性 | 30 |
| 巢狀深度 | 6 層 |
| 聯合中的元件 | 10 |
| 結構複雜度分數 | 50 |
列表項目(結構預設 maximumLength) | 30 |
文字 maximumLength | 300(單行);1000(多行和 URL)(隱含上限:純 text 不能將 format 與 maximumLength 結合;富文本可以) |
文字 choices | 20 |
| 檔案大小 | 5 MB (5242880 位元組) |
| 標籤/描述 | 60 / 160 字元 |
複雜度分數:structure = 1 + 其屬性;list = 1 + 其項目類型;primitive = 1;union = 其最複雜的成員;reference = 被參考的元件。一個包含標題、圖片和價格的產品列表分數為 5。
內容定義骨架
每個值都是 {"type": "<內容類型>", "value": {"type": "static" | "dynamic", ...}}。結構巢狀 attributes;列表包含 items;聯合內容是一個將 name 設定為聯合鍵的結構。
{
"type": "structure",
"attributes": {
"message": {
"type": "text",
"value": {"type": "static", "value": "歡迎, {{variable}}!"}
},
"variable": {
"type": "text",
"value": {
"type": "dynamic",
"expression": "user's name",
"nullable": true,
"default": "訪客"
}
}
}
}
expression是 CQL(請參閱croct-cql技能)。當評估失敗、回傳null或回傳不相容的類型時,使用default。nullable必須與結構中的optional標誌相符。- 將輔助屬性(如
variable)標記為結構中的"private": true,使它們不會出現在傳遞給應用程式的內容中。 - 內容限制:最多 30 個列表項目、最多 10 個動態值、複雜度分數 50。
- 動態值是 Scale 計劃的功能;本地化是附加元件。
佔位符、相對路徑、備援以及每種內容類型:references/definition.md。
本地化
- 語言環境是依工作區配置的。本地化是附加元件。
- 為每個支援的語言環境提供每個插槽的預設內容。沒有預設內容的語言環境將使用預設語言環境的內容。體驗和實驗也為每個語言環境保存內容;沒有特定語言環境內容的體驗將提供該插槽的預設內容。
- 當請求的語言環境缺失時的備援:SDK 文件說是工作區的預設語言環境;Content API 文件說是插槽的預設語言環境。文件存在歧義;在這種情況下請說明,而不是選擇其中一個。
- 在程式碼中使用
preferredLocale(每次擷取)或defaultPreferredLocale(應用程式級別)來請求語言環境,或在 Next.js/Hydrogen 中使用localeResolver;請參閱croct-integrate-sdk技能。 croct.json包含defaultLocale和locales;croct install會下載每個插槽、版本和語言環境的備援內容。請參閱croct-use-cli技能。
版本控制與重大變更
- 變更元件結構,例如新增一個屬性或變更一個現有屬性(文件中的範例)。
- 當變更影響內容結構,可能導致應用程式無法運作時,Croct 會建立一個新版本,並繼續向應用程式提供舊版本。
- 更新每個受影響插槽和體驗的內容(儀表板會標記它們)。
- 在應用程式程式碼中提升插槽版本,例如
fetchContent('home-hero@2')。
可以做的事:
- 在應用程式碼中固定插槽版本(
home-hero@1)。未設定版本的 ID 會使用最新版本,因此重大變更會立即生效,可能導致應用程式出錯。 - 同時更新體驗和實驗內容,而不僅僅是插槽預設內容。
- 在變更後保持備援內容同步(
croct-use-cli技能涵蓋了同步)。
不可以做的事:
- 假設哪些編輯是重大變更。文件並未列出它們;請依賴儀表板的插槽影響警示。
重構
| 情況 | 技術 |
|---|---|
| 一個變更應該套用於大多數但不全部的使用情況 | 複製並修改:複製元件,將少數例外指向副本,然後變更原始元件 |
| 一個變更應該只套用於少數使用情況 | 複製並取代:複製,變更副本,將這些使用情況指向副本 |
| 元件已達到最大巢狀層級 | 扁平化並合併:將巢狀結構的屬性合併到父層級,然後更新使用它的所有地方的內容 |
| 元件接近複雜度限制 | 拆分為由單獨插槽渲染的較小組件 |
| 結構已達到 30 個屬性的限制 | 指導方針(文件對此沒有指引):將相關屬性分組為巢狀結構(保持在 6 層巢狀結構內),或拆分為單獨的元件和插槽。固定的插槽版本(home-hero@1)可在您遷移時讓線上應用程式保持使用舊結構 |
詳細資訊、步驟和最佳實踐:references/design-and-refactoring.md.
文字屬性中的 Markdown
- 富文本 (
@croct/richText) 儲存由工具列編輯器產生的 Markdown;使用allowedFormatting限制它。 - 純
text屬性儲存原始字串。為了在那裡支援 Markdown,請在應用程式中解析它,例如使用@croct/md-lite(粗體、斜體、刪除線、程式碼、連結、圖片、段落)。 - 保持簡單的格式化。將 CTA 標籤、URL 和產品資料建模為單獨的屬性。
- 在屬性的
description中說明支援的語法,例如「支援 Markdown 語法用於 **粗體**、*斜體* 和 [連結](https://example.com\)。」
渲染程式碼:references/design-and-refactoring.md.
常見陷阱
- 為單一標題或圖片建立元件。請使用原始屬性或結構。
- 使用通用名稱(「產品卡片」)。請使用目的名稱(「產品功能列表」)。
- 聯合
types鍵與被參考的元件 ID 不同:結構無效。 - 多個
choices條目具有"default": true:結構無效。 - 日期/時間值沒有秒數:
10:15無效,10:15:00有效。 - 具有
nullable的動態值與結構的optional標誌不一致。 - 當體驗的插槽版本與應用程式的版本不同時,預覽會顯示過時的內容。
即時文件
- 索引:
https://docs.croct.com/llms.txt - 任何頁面(作為 Markdown):
https://docs.croct.com/reference/content/schema/introduction.md - 搜尋:
https://docs.croct.com/api/search.md?term=<terms>