Community影像github.com

mohitagw15856/thumbnail-creator

在 Claude Code 中使用 Gemini API 產生文章或電子報的縮圖候選方案。Claude 會閱讀文章內容、提出構圖概念、撰寫包含品牌規格的圖片生成提示、呼叫 Gemini 生成圖片、透過電腦視覺評估結果,並回傳排名後的候選方案與理由。當你被要求建立縮圖、產生封面圖片、或為文章/電子報製作視覺候選方案時使用。

thumbnail-creator 是什麼?

這個技能讓 Claude Code 扮演一個完整的圖片生成代理,專門用於製作文章和電子報的縮圖候選方案。它透過 Gemini API 自動化整個流程:從閱讀文章內容、分析核心論點與關鍵數據、收集品牌色彩與字型規格,到提出量身定制的構圖概念,並撰寫詳細的圖片生成提示。完成提示後,Claude 會呼叫 Gemini Imagen 模型生成圖片,再利用電腦視覺技術評估每張圖片的品牌契合度與文字可讀性,最後產出排名後的候選清單與詳細的評估報告。這個技能支援 Claude Code 平台,需要預先設定 GEMINI_API_KEY 環境變數,並在專案根目錄放置 `generate_image.py` 腳本(範本已包含在技能文件中)。輸出結果會依文章標題 slug 收納在 `./thumbnails/` 目錄下,包含圖片檔案與一份 `evaluation_report.md`,讓使用者可以直接將縮圖用於 CMS、電子報工具或社群媒體排程器中。整體而言,這個技能大幅減少了在不同工具間切換的時間,提升了縮圖製作的效率與品質。

相容平台✓Claude Code~Codex CLI~Cursor✓Gemini CLI
npx skills add https://github.com/mohitagw15856/pm-claude-skills/tree/HEAD/skills/thumbnail-creator

Installed? Explore more 影像 skills: steipete/songsee, affaan-m/frontend-design, mattpocock/improve-codebase-architecture · View all 6 →

在你喜歡的 AI 中提問

開啟一個已預先載入此 Agent Skill 的新對話。

說明文件

縮圖建立技能(透過 Gemini)

在 Claude Code 內部擔任圖片生成代理,產生文章和電子報的縮圖候選方案。您不再需要在不同工具間切換、一個一個在 Gemini 的網頁 UI 中輸入提示;這個技能讓 Claude 完成整個循環:閱讀文案、提出構圖、撰寫客製化提示、呼叫 Gemini API、評估輸出結果,並回傳排名後的候選方案與簡短理由。

產出的縮圖候選方案可直接用於您的 CMS、電子報工具或社群媒體排程器。


前置作業

在技能可以開始生成圖片之前,必須先確定以下兩項都已準備就緒:

1. Gemini API 金鑰

從 Google AI Studio 取得免費金鑰。

設定為環境變數:

export GEMINI_API_KEY=<你的金鑰>

若要跨工作階段保留,請新增至您的 shell 設定檔(~/.zshrc 或 ~/.bashrc):

echo 'export GEMINI_API_KEY=<你的金鑰>' >> ~/.zshrc
source ~/.zshrc

確認已設定:

echo $GEMINI_API_KEY

2. generate_image.py 腳本

此腳本必須存在於專案根目錄下的 ./generate_image.py。完整的範本請參閱下方的「腳本範本」章節。Claude 會檢查此檔案,若遺失則會主動提議建立。

Python 相依套件:

pip install google-generativeai Pillow requests

若使用 uv:

uv pip install google-generativeai Pillow requests

必要輸入

若未提供,Claude 會詢問以下資訊:

輸入項目必要與否備註
文章內容或 URL是貼上完整文章內容,或提供 URL 以供擷取。用來提取主題、鉤子與關鍵主張來進行構圖。
品牌色彩建議提供十六進制色碼或描述性名稱。例如 #1A1A2E(深藍)、#E94560(珊瑚紅)。若未提供,Claude 會使用乾淨的中性預設值。
字型 / 字體風格建議提供例如「粗體無襯線字體」、「編輯襯線字體」、「Neue Haas Grotesk」。用於提示中引導文字處理方式。
風格參考描述建議提供例如「扁平插畫、簡約,像 Stripe 的行銷網站」或「寫實、深色背景、高對比」。也可以提供風格圖片的 URL。
輸出尺寸否預設為 1792x1024(橫向,標準文章縮圖)。可選:1024x1024(正方形)、1024x1792(直向/行動裝置)。
候選數量否預設為 4。最少 1,最多 8(API 限制與成本考量)。
文章標題(若不同於 H1)否用作圖片提示中的主要文字元素。
候選選擇否在提出構圖後,Claude 會詢問要生成哪些。使用者可以回答「全部」或依編號選擇。

輸出結構

第一階段 — 構圖提案(文字,在呼叫 API 之前)

Claude 會呈現 3-4 個構圖概念供使用者核准。格式如下:

「[文章標題]」的構圖概念

1. 大膽主張
   版面:    滿版深色背景、置中大型白色標題、下方以品牌色彩顯示單一重點數據(例如「3 倍快」)
   氛圍:    高度權威、電子報風格
   最適合:  LinkedIn、Substack 頁首
   理由:    文章的核心主張(「X 比 Y 快 3 倍」)夠具體,足以支撐視覺 — 讀者會因為數據而停下。

2. 概念物體
   版面:    中央物體插畫(例如,一篇關於浪費時間的文章可以放一個壞掉的時鐘)、標題在上三分之一處、極簡紋理背景
   氛圍:    編輯風格、Medium 風格
   最適合:  部落格頁首、Medium 封面、電子郵件前導
   理由:    給予藝術總監視覺隱喻的靈活性;適用於各種尺寸。

3. 對比分割
   版面:    左半部品牌色彩、右半部白色或圖片、標題在色彩側、輔助文字在白色側
   氛圍:    整潔、專業、新創品牌感
   最適合:  電子報、LinkedIn 輪播第一張
   理由:    分割版面在電子報 A/B 測試中表現穩定;小尺寸下文字仍可讀。

4. 純文字編排
   版面:    無插畫、超大標題處理、作者姓名以小寫大寫字體置於底部、細線分隔
   氛圍:    高質感、自信、編輯風格
   最適合:  Substack、Ghost、高密度郵件清單
   理由:    當品牌有強烈的字體識別時適用。製作速度最快。


您要生成哪些構圖?(請回覆編號,例如「1, 3」或「all」)

第二階段 — 生成的圖片檔案

生成完成後,Claude 會將檔案儲存至 ./thumbnails/[文章縮寫]/:

thumbnails/
└── 依標題產生的文章縮寫/
    ├── candidate_01_bold_claim.png
    ├── candidate_02_conceptual_object.png
    ├── candidate_03_contrast_split.png
    ├── candidate_04_typographic.png
    └── evaluation_report.md

第三階段 — 評估摘要表

Claude 會透過電腦視覺評估每張回傳的圖片,並產出:

縮圖評估 — 「[文章標題]」
生成日期:2026-05-27 | 模型:Gemini Imagen | 尺寸:1792x1024

| # | 候選方案 | 構圖 | 品牌契合度 /10 | 文字可讀性 /10 | 建議 |
|---|---|---|---|---|---|
| 1 | candidate_01_bold_claim.png | 大膽主張 | 9 | 8 | ★ 首選 — 數據錨點強烈、品牌色彩正確、200px 寬度下標題可讀 |
| 2 | candidate_02_conceptual_object.png | 概念物體 | 7 | 9 | 良好的備選 — 可讀性高、乾淨,但插畫風格略微偏離品牌 |
| 3 | candidate_03_contrast_split.png | 對比分割 | 8 | 7 | 全尺寸時表現良好;發布前請先測試縮圖尺寸 — 右側文字較緊湊 |
| 4 | candidate_04_typographic.png | 純文字編排 | 9 | 10 | 最適合電子郵件 — 零品牌偏移風險、完全基於文字 |


推薦用於網頁:          candidate_01_bold_claim.png
推薦用於電子郵件/行動裝置:candidate_04_typographic.png
推薦用於社群媒體:       candidate_03_contrast_split.png

檔案儲存於:./thumbnails/文章縮寫/

Claude 應如何執行此技能

步驟 1 — 輸入並分析文章

接受以貼上文字或 URL 形式提供的文章內容。

若提供 URL,則擷取頁面並提取:

  • H1 標題
  • 前 3-5 個段落(鉤子、核心主張與關鍵論點)
  • 任何值得注意的統計數據或提及的知名架構
  • 作者姓名(用於純文字編排構圖)

若貼上文字,則直接閱讀。重點關注:

  • 鉤子: 開頭的主張或張力是什麼?
  • 核心論點: 文章論證或教導的一件事是什麼?
  • 關鍵細節: 任何能夠作為視覺錨點的數字、知名架構或具體例子
  • 語氣: 這是正式/權威、口語/平易近人、還是挑釁/挑戰性?

在提出構圖之前先在內部總結這些發現 —— 提案應針對這篇特定文章量身定制,而非泛泛而談。

步驟 2 — 收集品牌規格

若未提供品牌規格,則詢問使用者:

要產生符合品牌風格的縮圖,我需要以下資訊:

1. 品牌色彩(十六進制色碼或描述)——例如 #1A1A2E、#E94560
2. 字型風格偏好——例如「粗體無襯線字體」、「編輯襯線字體」、「幾何字體」
3. 視覺風格——例如「扁平極簡」、「寫實」、「插畫」、「純文字編排」
4. 任何風格參考——描述一個您想比照其美學的品牌或刊物,或分享圖片 URL

如果您還沒有品牌規格,請說「使用乾淨的預設值」,我將使用專業的深色文字配白色背景的編輯風格。

若使用者說「使用乾淨的預設值」,則套用:

  • 背景:#FFFFFF 或 #0F0F0F(深色模式預設)
  • 強調色:#2563EB(藍色)
  • 字型風格:粗體幾何無襯線字體
  • 風格:極簡扁平、無紋理、高對比

步驟 3 — 提出構圖概念

針對文章的語氣與內容撰寫 3-4 個構圖概念。每個概念必須:

  • 有名稱(簡短、好記的標籤)
  • 精確描述版面(標題位置、支撐畫面的視覺元素、背景處理方式)
  • 註明氛圍及其最適合的使用情境
  • 包含一句理由說明,解釋為什麼此構圖適合這篇特定文章

呈現概念後,詢問要生成哪些。在進行任何 API 呼叫之前,等待使用者確認。

步驟 4 — 撰寫 Gemini 圖片生成提示

針對每個選定的構圖,撰寫詳細的圖片生成提示。圖片生成提示的語法與文字提示不同 —— 它們是描述性的,而非指令性的。

提示結構:

[主體/構圖] + [風格] + [色彩調色盤] + [氛圍/燈光] +
[文字處理(若有)] + [應避免的內容]

大膽主張構圖的提示範例:

文章縮圖圖片。大型粗體白色無襯線字體標題顯示「比傳統方法快 3 倍」在深海軍藍背景(#1A1A2E)上置中。下方以珊瑚紅強調色文字(#E94560)顯示副標題。極簡扁平設計,無漸層、無圖庫照片元素、無人物。乾淨專業的編輯風格、高對比、電子報頁首格式、16:9 橫向畫面。構圖為純文字編排 — 文字是主角,不需要插畫。避免:剪貼畫、投影、低對比、擁擠的版面。

提示規則:

  • 當提供品牌色彩時,須包含確切的十六進制色碼
  • 指定要在圖片中顯示的確切標題文字
  • 明確說明風格(「扁平設計」、「編輯風格」、「寫實」)—— Gemini 對風格類別名稱反應良好
  • 在結尾加入負面提示(「避免:...」)以減少偏離品牌風格的情況
  • 將提示控制在 300 字以下 —— 較長的提示不一定能產生更好的結果

步驟 5 — 檢查前置條件並執行生成腳本

在呼叫 API 之前,請確認:

# 檢查 API 金鑰是否已設定
echo $GEMINI_API_KEY

# 檢查腳本是否存在
ls -la ./generate_image.py

# 檢查相依套件
python3 -c "import google.generativeai, PIL, requests; print('Dependencies OK')"

若腳本遺失,主動提議使用下方「腳本範本」章節中的範本來建立。

為每個提示執行生成腳本:

python3 generate_image.py \
  --prompt "您的完整提示" \
  --output "./thumbnails/文章縮寫/candidate_01_bold_claim.png" \
  --width 1792 \
  --height 1024

或將所有提示透過批次設定檔傳入:

python3 generate_image.py --config ./thumbnails/文章縮寫/prompts.json

步驟 6 — 評估生成的圖片

每張圖片儲存後,使用電腦視覺進行檢查。從兩個維度評估:

品牌契合度(分數 /10):

  • 品牌色彩是否正確?(各 1-2 分)
  • 風格是否符合要求的美感?(2 分)
  • 版面是否與構圖簡報一致?(2 分)
  • 是否有任何 AI 偽影、扭曲文字或非預期元素?(每項扣 1 分)

文字可讀性(分數 /10):

  • 全解析度下標題文字是否可讀?(3 分)
  • 圖片縮放至 300px 寬(縮圖尺寸)時,標題文字是否可讀?(3 分)
  • 文字與背景之間是否有足夠的對比?(2 分)
  • 文字是否位於安全區域內(未被邊緣裁切)?(2 分)

注意:Gemini Imagen 有時會渲染出有拼寫錯誤或字母形狀扭曲的文字。如果發生這種情況,請在評估中註明,並建議使用者在 Canva 或 Figma 中手動加上文字疊加層。

步驟 7 — 產出評估報告

撰寫評估摘要表(格式如「輸出結構」章節所示),並將其儲存為輸出資料夾中的 evaluation_report.md。

包含:

  • 每個分數的一行理由說明
  • 每個使用情境(網頁、電子郵件/行動裝置、社群媒體)的首選推薦
  • 任何製作備註(例如「候選方案 2 的文字渲染不完美 — 請手動疊加文字」)
  • 所使用的完整提示,以便使用者可以直接在 AI Studio 中迭代(如有需要)

步驟 8 — 提供迭代選項

交付候選方案後,提供一次迭代循環:

想要我對任何一個進行迭代嗎?

選項:
- 調整特定候選方案的色彩或風格
- 嘗試不同的構圖概念
- 更改標題文字
- 使用不同的 Gemini 參數重新執行(不同的 temperature / seed)
- 為首選生成更多變體

只要告訴我要改什麼即可。

腳本範本

如果 generate_image.py 不存在,Claude 應主動提議寫入此檔案。這是應使用的標準範本。

#!/usr/bin/env python3
"""
generate_image.py — Gemini Imagen wrapper for Thumbnail Creator skill.

Usage:
    python3 generate_image.py --prompt "..." --output "./out.png" [--width 1792] [--height 1024]
    python3 generate_image.py --config ./prompts.json

Config JSON format:
    [
      {
        "prompt": "...",
        "output": "./thumbnails/slug/candidate_01.png",
        "width": 1792,
        "height": 1024
      }
    ]

Requirements:
    pip install google-generativeai Pillow
"""

import os
import sys
import json
import argparse
import base64
from pathlib import Path

try:
    import google.generativeai as genai
    from google.generativeai import types as genai_types
except ImportError:
    print("ERROR: google-generativeai not installed. Run: pip install google-generativeai")
    sys.exit(1)

try:
    from PIL import Image
    import io
except ImportError:
    print("ERROR: Pillow not installed. Run: pip install Pillow")
    sys.exit(1)


def get_api_key() -> str:
    key = os.environ.get("GEMINI_API_KEY", "")
    if not key:
        print("ERROR: GEMINI_API_KEY environment variable is not set.")
        print("Get a key at: https://aistudio.google.com/app/apikey")
        print("Then run: export GEMINI_API_KEY=<your-key>")
        sys.exit(1)
    return key


def generate_image(
    prompt: str,
    output_path: str,
    width: int = 1792,
    height: int = 1024,
) -> bool:
    """
    Call Gemini Imagen to generate a single image and save it to output_path.
    Returns True on success, False on failure.
    """
    key = get_api_key()
    genai.configure(api_key=key)

    output = Path(output_path)
    output.parent.mkdir(parents=True, exist_ok=True)

    try:
        model = genai.GenerativeModel("models/imagen-3.0-generate-001")

        response = model.generate_content(
            prompt,
            generation_config=genai_types.GenerationConfig(
                temperature=0.4,
                candidate_count=1,
            ),
            safety_settings=[
                {
                    "category": genai_types.HarmCategory.HARM_CATEGORY_HARASSMENT,
                    "threshold": genai_types.HarmBlockThreshold.BLOCK_NONE,
                },
                {
                    "category": genai_types.HarmCategory.HARM_CATEGORY_HATE_SPEECH,
                    "threshold": genai_types.HarmBlockThreshold.BLOCK_NONE,
                },
                {
                    "category": genai_types.HarmCategory.HARM_CATEGORY_SEXUALLY_EXPLICIT,
                    "threshold": genai_types.HarmBlockThreshold.BLOCK_NONE,
                },
                {
                    "category": genai_types.HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
                    "threshold": genai_types.HarmBlockThreshold.BLOCK_NONE,
                },
            ],
        )

        if not response.candidates:
            print(f"ERROR: No candidates returned for prompt: {prompt[:60]}...")
            if response.prompt_feedback:
                print(f"Block reason: {response.prompt_feedback}")
            return False

        image_data = None
        for part in response.candidates[0].content.parts:
            if part.inline_data and part.inline_data.mime_type.startswith("image"):
                image_data = part.inline_data.data
                break

        if not image_data:
            print(f"ERROR: No image data in response for prompt: {prompt[:60]}...")
            print(f"Response text (if any): {response.text[:200] if hasattr(response, 'text') and response.text else 'N/A'}")
            return False

        img = Image.open(io.BytesIO(image_data))
        img = img.resize((width, height), Image.Resampling.LANCZOS)
        img.save(output_path, "PNG")
        print(f"OK: {output_path} ({width}x{height})")
        return True

    except Exception as e:
        print(f"ERROR generating image: {e}")
        return False


def main():
    parser = argparse.ArgumentParser(description="Generate image via Gemini Imagen")
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument("--prompt", type=str, help="Image generation prompt")
    group.add_argument("--config", type=str, help="Path to JSON config file with batch of prompts")
    parser.add_argument("--output", type=str, help="Output image path (required with --prompt)")
    parser.add_argument("--width", type=int, default=1792, help="Image width (default: 1792)")
    parser.add_argument("--height", type=int, default=1024, help="Image height (default: 1024)")

    args = parser.parse_args()

    if args.config:
        config_path = Path(args.config)
        if not config_path.exists():
            print(f"ERROR: Config file not found: {config_path}")
            sys.exit(1)

        with open(config_path, "r") as f:
            jobs = json.load(f)

        success_count = 0
        for job in jobs:
            if generate_image(
                prompt=job["prompt"],
                output_path=job["output"],
                width=job.get("width", 1792),
                height=job.get("height", 1024),
            ):
                success_count += 1

        total = len(jobs)
        print(f"\nDone: {success_count}/{total} images generated successfully.")
        sys.exit(0 if success_count == total else 1)

    elif args.prompt:
        if not args.output:
            print("ERROR: --output is required when using --prompt")
            sys.exit(1)

        success = generate_image(
            prompt=args.prompt,
            output_path=args.output,
            width=args.width,
            height=args.height,
        )
        sys.exit(0 if success else 1)


if __name__ == "__main__":
    main()

常見問題

  • Gemini 在縮圖中產生拼寫錯誤的文字。 這是已知的限制。在評估報告中指出,並建議使用者在 Canva 或 Figma 中手動疊加正確文字。
  • 生成的圖片完全偏離品牌風格。 為提示加入更明確的負面指示。確認品牌色彩已正確傳入。
  • API 金鑰錯誤。 執行 echo $GEMINI_API_KEY 確認金鑰已正確設定。若金鑰包含特殊字元,請檢查您的 shell 設定檔中是否有正確的引號。
  • 批次中的某些提示失敗。 重新單獨執行失敗的提示。有時 Gemini 基於不明原因會拒絕某個特定提示;修改措辭通常可以解決問題。

限制

  • 文字渲染: Gemini Imagen 產生的文字並非 100% 可靠。讀者不應期望產生可發布的文字 —— 將此技能視為構圖產生器,而非最終排版工具。
  • 成本: Imagen 是付費 API。1792x1024 尺寸的每次生成會使用固定配額。大量批次可能產生費用。
  • 風格一致性: 不同生成之間無法保證完全一致的風格。若需要重現相同外觀,請考慮使用種子值或風格參照圖片。

Individual skills in this repo

This repo contains 8 individual skills — each has its own dedicated page.

mohitagw15856/pm-claude-skills

Create a structured brief for an influencer or creator partnership campaign. Use when asked to brief an influencer, plan a creator collaboration, set up a paid partnership, or define deliverables for a sponsored content campaign. Produces a complete campaign brief with objectives, deliverables, creative guidelines, approval process, and performance metrics.

mohitagw15856/pm-claude-skills

Write full landing-page copy that converts — section by section. Use when asked to write a landing page, homepage copy, a product page, or copy for a marketing site. Produces complete copy for every section (hero, problem, solution, social proof, features-as-benefits, objections/FAQ, final CTA) with a clear single conversion goal and one primary call to action.

mohitagw15856/pm-claude-skills

Write a short-form video script for TikTok, Instagram Reels, or YouTube Shorts — built on the hook→retention→payoff structure that drives watch-time. Use when asked to script a Reel, TikTok, Short, or any 15–60s vertical video. Produces a timed script with a 0–3s hook, retention beats with on-screen text and B-roll cues, a payoff, and a CTA — plus a caption and on-screen-text list. Distinct from long-form YouTube scripting.

mohitagw15856/pm-claude-skills

Plan and write a paid social advertising campaign. Use when asked to build a paid social campaign, create Meta/LinkedIn/TikTok/X ad copy, define a social ad strategy, or plan an advertising funnel across social platforms. Produces a complete campaign plan with audience targeting, ad set structure, copy for each ad format, budget allocation, and measurement framework.

mohitagw15856/pm-claude-skills

Build a framework for creating shareable, high-reach social media content. Use when asked to plan viral content, develop a shareable content strategy, create a hook writing system, or build a repeatable process for content that gets shared. Produces a platform-specific viral content framework with hook formulas, content structures, shareability triggers, and a content testing system.

mohitagw15856/pm-claude-skills

Build boolean and X-ray search strings to source candidates. Use when asked to build a boolean search, source candidates on LinkedIn/Google, write an X-ray search, or find people with specific skills. Produces ready-to-paste boolean strings (with synonyms, must-haves, and exclusions), X-ray variants for LinkedIn/GitHub, and a refinement plan to widen or narrow the result set.

mohitagw15856/pm-claude-skills

Write pricing page copy that helps buyers self-select the right plan and convert. Use when asked to write or improve a pricing page, name and describe pricing tiers, write plan feature lists, pricing CTAs, or a pricing FAQ. Produces complete pricing page copy — a header, tier cards with names, prices, audiences, feature lists, CTAs, an add-on/enterprise section, and an objection-handling FAQ.

mohitagw15856/pm-claude-skills

Audit an existing social media presence across all active platforms. Use when asked to review social media performance, analyse a brand's social presence, benchmark against competitors, or identify what's working and what isn't. Produces a scored audit with platform-by-platform analysis, content performance review, competitive benchmarking, and a prioritised action plan.

相關技能