og-image-kit 是做什麼的?
目標:每個公開頁面都有一張 1200×630 的分享圖片,並具備正確的 og:* / twitter:* 標籤,且你已透過 scripts/check_og.py 驗證過,而不只是寫入而已。
步驟 1 — 偵測技術棧
在撰寫任何程式碼之前,先檢查儲存庫:
| 訊號 | 技術棧 | 前往 |
|---|---|---|
package.json 中有 next 且存在 app/(或 src/app/)目錄 | Next.js App Router | 步驟 2A |
next 但僅有 pages/ | Next.js Pages Router | 步驟 2C(靜態)或新增 /api/og 搭配 ImageResponse |
package.json 中有 astro | Astro | 步驟 2B |
| 純 HTML、Hugo、Jekyll、Vite SPA 或其他 | 靜態網站 | 步驟 2C |
同時找出:網站的標準基礎 URL(環境變數如 NEXT_PUBLIC_SITE_URL、astro.config.* 中的 site)、品牌顏色、標誌與使用的字型。若找不到任何資訊,才詢問使用者。
步驟 2A — Next.js App Router
- 確保根佈局匯出
metadataBase(OG 網址必須是絕對路徑):export const metadata = { metadataBase: new URL(process.env.NEXT_PUBLIC_SITE_URL ?? "http://localhost:3000") } - 將
assets/nextjs/opengraph-image.tsx複製到app/opengraph-image.tsx(網站預設)。 編輯BRAND、顏色與標語。 - 對於動態路由(部落格文章、產品),將它複製到對應的路由區段中,例如
app/blog/[slug]/opengraph-image.tsx,並使用assets/nextjs/dynamic-opengraph-image.tsx,它會讀取params並從資料來源載入標題。 在 Next.js 15+ 中,params是一個 Promise — 記得await它。 - 僅當 X 卡片必須不同時,才新增
twitter-image.tsx;否則 Next.js 會在 metadata 中設定twitter: { card: "summary_large_image" }時重複使用 OG 圖片。 - 每個頁面的文字:在每個頁面的
metadata/generateMetadata中設定title與description。 - 自訂字型:透過
fetch(new URL("./Inter-Bold.ttf", import.meta.url))或readFile載入 TTF/OTF(非 WOFF2)字型。中日韓(CJK)文字需要 CJK 字型檔案,否則會顯示為方塊 — 對它進行子集化以保持檔案大小。
需遵守的限制(next/og / satori):僅限 flexbox(無 grid),每個有多個子元素的 div 都需要 display: "flex",保持套件小巧 — Next.js 的 ImageResponse 文件指出 JSX + CSS + 字型 + 圖片的限制為 500 KB。大型字型也會減慢渲染速度,因此請進行子集化。
步驟 2B — Astro
使用 assets/astro/og-endpoint.ts 作為 src/pages/og/[...slug].png.ts。它會在構建時使用 satori + @resvg/resvg-js(npm i satori @resvg/resvg-js)為每個頁面渲染 PNG,並從你的佈局中引用它:
<meta property="og:image" content={new URL(`/og/${slug}.png`, Astro.site)} />
```\n`Astro.site` 必須在 `astro.config.mjs` 中設定。字型檔案:將 TTF 字型放入 `src/assets/fonts/`。
## 步驟 2C — 靜態網站 / 其他
一次性產生 PNG 並提交:
```bash
python3 scripts/generate_og.py --pages pages.json --out public/og --brand "Acme" --bg "#0f172a" --fg "#ffffff" --accent "#38bdf8"
pages.json 是一個包含 {"slug": "pricing", "title": "...", "subtitle": "..."} 的清單(請參閱 assets/pages.example.json)。需要 Pillow(pip install pillow)。傳遞 --font path/to/font.ttf 以使用品牌字型或 CJK 文字(例如 Noto Sans SC)。然後為每個頁面加入標籤(範本在 references/meta-tags.md 中)。
步驟 3 — 必備標籤(每個頁面)
<meta property="og:title" content="Page title" />
<meta property="og:description" content="一句話,≤ ~160 字元" />
<meta property="og:image" content="https://example.com/og/page.png" /> <!-- 絕對 URL -->
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:url" content="https://example.com/page" />
<meta property="og:type" content="website" />
<meta name="twitter:card" content="summary_large_image" />
Next.js 會從 metadata + opengraph-image.tsx 自動產生這些標籤;請勿手動重複撰寫。
步驟 4 — 驗證(不可跳過)
針對正在執行的網站(開發伺服器、預覽部署或正式環境)執行:
python3 scripts/check_og.py http://localhost:3000/ http://localhost:3000/pricing
python3 scripts/check_og.py --json https://example.com/ # 機器可讀格式
它會擷取每個頁面,檢查必要的標籤、og:image 是否為絕對 URL、是否可存取、是否為圖片 content-type、長寬比約 1.91:1 且寬度至少 600 像素,以及檔案大小是否小於 5 MB。任何錯誤都會導致退出碼為 1。修正所有標記為 ERROR 的項目;WARN 項目為建議事項。
注意:社交平台會快取預覽。修正後,請使用平台專屬的除錯工具(LinkedIn Post Inspector、Facebook Sharing Debugger)重新爬取。X 已沒有公開驗證器;透過草稿或直接訊息貼文來檢查。localhost 網址無法被這些工具爬取 — 請先部署。
圖片的設計規則
- 1200×630,PNG 格式,文字位於約 60 像素的安全邊距內;標題 ≤ ~60 字元,最多 3 行。
- 高對比度;在資訊流中顯示時約 500 像素寬。請以 50% 縮放測試。
- 包含品牌名稱/標誌;避免過小的文字(在 1200 寬度下小於 28 像素)。
- 請參閱
references/platform-specs.md了解各平台的注意事項。
完成條件
- 每個可索引的頁面都回傳 og:title、og:description、og:image(絕對 URL)、twitter:card
-
check_og.py對首頁及每種路由類型至少一個頁面返回退出碼 0 - 圖片看起來正確(打開一個 PNG 並查看)