linebot-notebook-design
SKILL.md
LINE Bot Flex Message 筆記樣式設計指南
概述
本 skill 記錄 LINE Bot Flex Message 圖文筆記的設計規範與最佳實踐,以「元素週期表筆記」專案為範例。適用於教育類、知識卡片類的 LINE Bot 開發。
LINE Bot Flex Message 限制
| 項目 | 限制 |
|---|---|
| JSON 大小 | 最大 50KB |
| Carousel 卡片數 | 最多 12 張 |
| Box 巢狀層級 | 最多 10 層 |
| 單張卡片寬度 | 建議 280px |
| Hero 圖片比例 | 建議 4:3 或 16:9 |
| Hero aspectMode | 只支援 "cover" 或 "fit"(不支援 "contain"!) |
| Button label | 最多 20 字元(超過會截斷) |
| 圖片格式 | JPEG, PNG(不支援 GIF 動圖) |
| 圖片大小 | 建議 < 300KB |
| 圖片來源 | 必須是 HTTPS URL |
aspectMode 血淚教訓
LINE API 回傳 HTTP 400 錯誤:
{"message":"invalid property","property":"/contents/1/hero/aspectMode"}
原因:使用了 "aspectMode": "contain",但 LINE hero 圖片只支援:
"cover"- 填滿區域,可能裁切"fit"- 完整顯示,可能留白
修正:將所有 "contain" 改為 "fit"
不支援的屬性(重要!)
LINE Flex Message 不支援以下屬性,使用會導致 HTTP 400 錯誤:
| 不支援屬性 | 解決方案 |
|---|---|
borderWidth |
移除,改用 separator |
borderColor |
移除,改用 backgroundColor |
aspectMode: "contain" |
改用 "fit" |
| CSS 動畫 | 不支援 |
| SVG 嵌入 | 不支援 |
Bubble Size 限制
| Size | 最大高度 | 適用場景 |
|---|---|---|
| nano | ~120px | 極小卡片 |
| micro | ~165px | 小型通知 |
| kilo | ~300px | 一般用途 |
| mega | ~450px | 內容較多 |
| giga | ~600px | 最大尺寸 |
注意:內容超過限制時會被截斷,按鈕可能無法顯示!
卡片結構設計
標準 Flex Message 卡片結構
┌─────────────────────────┐
│ Hero 區域 │ ← 圖片或漸層背景
│ (圖片/符號/標題) │
├─────────────────────────┤
│ Content 區域 │
│ ┌───────────────────┐ │
│ │ 標題 + 副標題 │ │
│ └───────────────────┘ │
│ ┌───────────────────┐ │
│ │ 資訊表格/內文 │ │
│ └───────────────────┘ │
│ ┌───────────────────┐ │
│ │ 化學式/重點框 │ │
│ └───────────────────┘ │
│ ┌───────────────────┐ │
│ │ 標籤/按鈕 │ │
│ └───────────────────┘ │
└─────────────────────────┘
Hero 區域設計
配色建議(Material Design):
| 用途 | 淺色 | 深色 |
|---|---|---|
| 紅/粉 | #FFCDD2 | #EF9A9A |
| 橘 | #FFE0B2 | #FFCC80 |
| 藍 | #BBDEFB | #90CAF9 |
| 綠 | #C8E6C9 | #A5D6A7 |
| 紫 | #E1BEE7 | #CE93D8 |
| 青 | #B2EBF2 | #80DEEA |
色塊模擬技巧
用 Box + backgroundColor 模擬色塊:
[
'type' => 'box',
'layout' => 'vertical',
'contents' => [],
'width' => '28px',
'height' => '28px',
'backgroundColor' => '#FF5733',
'cornerRadius' => '6px',
]
導航按鈕設計
Flex Message JSON 實作:
{
"type": "separator",
"margin": "lg"
},
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "button",
"action": {
"type": "message",
"label": "📋 元素目錄",
"text": "元素目錄"
},
"style": "primary",
"height": "sm",
"flex": 1
},
{
"type": "button",
"action": {
"type": "message",
"label": "下一個 ➡️",
"text": "元素 2"
},
"style": "secondary",
"height": "sm",
"flex": 1,
"margin": "sm"
}
],
"margin": "lg"
}
兩欄按鈕設計(重要教育原則)
當元素數量較多時,使用兩欄按鈕可節省空間。
閱讀順序原則:必須是「由上到下」(先左欄再右欄),不是「由左至右」!
正確(由上到下): 錯誤(由左至右):
21 Sc | 39 Y 21 Sc | 22 Ti
22 Ti | 40 Zr 23 V | 24 Cr
23 V | 41 Nb 25 Mn | 26 Fe
... ...
閱讀:21→22→23...→39→40 閱讀:21→22→23→24...
奇數元素處理:最後一個元素旁邊加 filler 佔位。
{
"type": "box",
"layout": "horizontal",
"contents": [
{
"type": "button",
"action": { "label": "71 Lu 鎦", "text": "元素 71" },
"style": "secondary",
"flex": 1
},
{
"type": "filler",
"flex": 1
}
]
}
圖片生成規範(matplotlib)
基本設定
# -*- coding: utf-8 -*-
import matplotlib.pyplot as plt
import matplotlib.patches as patches
import os
# 中文字體(必須)
plt.rcParams['font.sans-serif'] = ['Microsoft JhengHei', 'SimHei', 'Arial Unicode MS']
plt.rcParams['axes.unicode_minus'] = False
圖片尺寸標準
| 用途 | figsize | DPI | 輸出尺寸 |
|---|---|---|---|
| 一般圖片 | (14, 10) | 150 | ~2100×1500px |
| 週期表 | (14, 7) | 120 | ~1680×840px |
| 小圖示 | (2, 2) | 150 | ~300×300px |
字體大小標準(LINE Bot 手機可讀)
FONT_TITLE = 30 # 主標題、單字元元素符號
FONT_LARGE = 22 # 雙字元元素符號
FONT_MEDIUM = 18 # 一般文字
FONT_SMALL = 14 # 次要資訊(最小值)
重要:LINE Bot 圖片在手機上無法放大,字體必須足夠大!
儲存函數
def save_fig(fig, filename):
"""儲存圖片"""
filepath = os.path.join(OUTPUT_DIR, filename)
fig.savefig(filepath, dpi=150, bbox_inches='tight',
facecolor='white', edgecolor='none', pad_inches=0.02)
plt.close(fig)
print(f"已儲存: {filename}")
常見錯誤與修正
1. Text 欄位不能為空字串
症狀:LINE Bot 無反應,API 回傳 HTTP 400
// ❌ 錯誤:空字串會導致 HTTP 400
{"type": "text", "text": ""}
// ✅ 正確:使用佔位符
{"type": "text", "text": "-"}
2. 長文字必須加 wrap: true
// ❌ 錯誤:長文字會被截斷
{"type": "text", "text": "很長的化學式..."}
// ✅ 正確:允許折行
{"type": "text", "text": "很長的化學式...", "wrap": true}
3. Button label 太長
改用 Box + Text(支援折行):
// ✅ 改用 box + text
['type' => 'box', 'contents' => [
['type' => 'text', 'text' => '很長的文字...', 'wrap' => true]
], 'action' => [...]]
4. LINE 圖片快取問題
更新圖片後 LINE 仍顯示舊版時,在 URL 加上版本參數:
"image_url": "https://lt4.mynet.com.tw/linebot/images/H.png?v=2"
5. matplotlib 特殊字符顯示為方框
某些 Unicode 字符在微軟正黑體中不支援:
| 問題字符 | 解決方案 |
|---|---|
| − (U+2212) | 改用 - (普通連字符) |
| ₂ (U+2082) | 改用 2 (普通數字) |
| ₃ (U+2083) | 改用 3 (普通數字) |
6. 診斷 LINE API 錯誤
當 LINE Bot 按鈕無反應時:
1. 檢查 debug.log:
tail -50 /path/to/linebot/debug.log
2. 解讀 property 路徑:
/contents/0/body/contents/5/contents/1/text- 代表 → carousel 第 1 張卡片 → body → 第 6 個元素 → 第 2 個子元素 → text
3. 常見 HTTP 狀態碼:
| 狀態碼 | 原因 |
|---|---|
| 400 | JSON 格式錯誤或欄位無效 |
| 401 | Channel Access Token 過期 |
| 429 | 請求次數超限 |
檔案命名規範
圖片檔案
# 週期表(每個元素一張,高亮該元素)
periodic_table_{symbol}.png
例:periodic_table_H.png, periodic_table_He.png
# 價電子圖
electron_{symbol}.png
例:electron_H.png, electron_He.png
# 內容圖片
{element}_{topic}.png
例:H_combustion.png, H_fuel_cell.png
JSON 資料檔
# 元素筆記資料
elements/{atomic_number}_{symbol}.json
例:elements/001_H.json, elements/002_He.json
# 目錄資料
menu/groups.json
導航流程設計
主選單
│
▼
元素目錄(按族分類 Carousel)
│
├── 1A族 → [H] [Li] [Na] [K] ...
├── 2A族 → [Be] [Mg] [Ca] ...
└── ...
│
▼
元素筆記(4張卡片 Carousel)
│
├── 卡片1: 基本資訊
├── 卡片2: 特性1
├── 卡片3: 特性2
└── 卡片4: 特性3 + 導航按鈕
│
├── [⬅️ 上一個] [➡️ 下一個]
├── [📋 元素目錄]
└── [🏠 主選單]
相關 Skills
linebot-architecture:LINE Bot 架構規範(憲法)quiz-builder:題庫系統專用指南linebot-setup:LINE Bot Messaging API 設定與除錯