소스 정보
- 저장소
- publieople/hermes-config-kit
- 최근 소스 활동
- 2026년 7월 4일 22:00
- 감지된 SKILL.md 언어
- 중국어
- 스타
- 0
- 포크
- 0
설치 방법
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
소스 파일 검토
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
메뉴
기본적으로 소스를 먼저 확인하는 Prompt가 선택됩니다. 직접 명령으로 전환하거나 로컬 사본을 다운로드할 수도 있습니다.
설치 여부를 결정하기 전에 SKILL.md와 SkillsMP에 표시된 보조 파일을 읽어 보세요.
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/publieople/hermes-config-kit --skill notionnext-blog명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SOC 직업 분류 기준
SKILL.md 표시 중
| name | notionnext-blog |
| description | 发布文章到 Publieople's Blog(NotionNext 驱动的博客)——搜索数据库、理解 schema、创建文章、验证上线。 |
| category | productivity |
references/notion-blocks.md — 完整 block 构造模板(高级 block、表格、媒体、错误码、限流)references/fork-sync-and-vercel.md — fork ↔ upstream 同步失败 + Vercel build/deploy 失败排查模式(含你 fork 这次恢复的实战参考)Notion API key 在 ~/.config/notion/api_key,格式 ntn_...。
02e0b2a07b164c37abb9cfc3db88c605097e5f674880459d8e1b4407758dc4fb(blog.config.js)| 属性 | 类型 | 可选值 |
|---|---|---|
title | title | — |
status | select | Published, Invisible, Draft |
type | select | Post, Page, Notice, Menu, SubMenu, Config |
category | select | 技术分享, 心情随笔, 差生文具多, 知识分享, 资源整理, 项目经历, 折腾记录, 活动体验 |
slug | rich_text | URL 路径(如 tiez-webdav-debugging) |
tags | multi_select | 自由标签 |
summary | rich_text | 文章摘要(用于 meta description) |
date | date | 发布日期 |
password | rich_text | 文章密码(可选) |
icon | rich_text | 自定义图标 URL(可选) |
import subprocess
key = subprocess.run(["cat", "/home/po/.config/notion/api_key"], capture_output=True, text=True).stdout.strip()
不要用 shell curl——API key 在终端中会被掩码为 *** 导致 auth 失败。
import json, urllib.request
DB = "02e0b2a07b164c37abb9cfc3db88c605"
markdown = """# 文章标题
文章内容(Notion-flavored Markdown)。
"""
payload = {
"parent": {"database_id": DB},
"properties": {
"title": {"title": [{"text": {"content": "文章标题"}}]},
"type": {"select": {"name": "Post"}},
"status": {"select": {"name": "Published"}},
"category": {"select": {"name": "折腾记录"}},
"date": {"date": {"start": "2026-06-08"}},
"slug": {"rich_text": [{"text": {"content": "url-slug"}}]},
"tags": {"multi_select": [{"name": "Tag1"}, {"name": "Tag2"}]},
"summary": {"rich_text": [{"text": {"content": "文章摘要"}}]}
},
"markdown": markdown
}
req = urllib.request.Request(
"https://api.notion.com/v1/pages",
data=json.dumps(payload).encode("utf-8"),
headers={
"Authorization": f"Bearer {key}",
: ,
:
},
method=
)
urllib.request.urlopen(req) resp:
result = json.loads(resp.read())
page_id = result[]
()
NotionNext 默认 revalidate 60 秒。验证:
curl -sI "https://blog.for-people.cn/article/{slug}" | grep HTTP
# HTTP/2 200 → 上线成功
来自用户资料:
<callout> 把结论放在开头<callout>、<details>、代码块等 Notion-flavored MarkdownNotionNext 渲染按 DB 顺序,所以"补充某章节内容"必须插在指定 block 后面,不能 append 到页尾。
API 支持 position 参数,放到 body 顶层(不是 children 里):
# 找到目标 H2 的 block id,作为 anchor
H2_ID = "5a066ad7-c9c4-8304-aaff-81441e0e7744" # 例:「版本控制」H2
payload = {
"children": [/* 任意数量的 block,单次上限 100 */],
"position": {"type": "after_block", "after_block": {"id": H2_ID}}
}
req = urllib.request.Request(
f"https://api.notion.com/v1/blocks/{PAGE_ID}/children",
data=json.dumps(payload).encode(),
headers={"Authorization": f"Bearer {key}", "Notion-Version": "2022-06-28", "Content-Type": "application/json"},
method="PATCH", # 注意是 PATCH 不是 POST
)
插入位置失败会报 400,但错误信息不告诉你具体哪个 block 错了。先用一个标记 callout 验证位置语义,再批量:
📌 [probe] 探针 → fetch 页面 block 列表,确认探针确实出现在目标 H2 之后/v1/blocks/{probe_id})跳过这一步直接批量 = 大概率插错位置,删起来很烦。
numbered_list_item / bulleted_list_item 算 1 个 leaf,但有的端点会算成多个 children)Ponytail: 5 个 helper 覆盖 90% 场景,不要造更复杂的。
def p(text): return {"object":"block","type":"paragraph","paragraph":{"rich_text":[{"type":"text","text":{"content":text}}]}}
def h2(text): return {"object":"block","type":"heading_2","heading_2":{"rich_text":[{"type":"text","text":{"content":text}}]}}
def h3(text): return {"object":"block","type":"heading_3","heading_3":{"rich_text":[{"type":"text","text":{"content":text}}]}}
def bullet(text): return {"object":"block","type":"bulleted_list_item","bulleted_list_item":{"rich_text":[{"type":"text","text":{:text}}]}}
(): {:,:,:{:[{:,:{:text}}]}}
(): {:,:,:{:[{:,:{:text}}],:lang}}
(): {:,:,:{:{:,:emoji},:[{:,:{:text}}]}}
(): {:,:,:{}}
完整 list / 表格 / toggle / image / bookmark 等高级 block 见 references/notion-blocks.md。
language 字段是枚举,传错立刻 400 Bad Request 且错误信息不指出字段名。 常用值:
plain text / bash / shell / powershell / python / javascript / typescript / json / yaml / html / css / markdown / sql / go / rust / java / c / c++ / c# / ruby / php / mermaid ...
没有 "text" 这个值 —— 纯文本框图用 "plain text"。
req = urllib.request.Request(
f"https://api.notion.com/v1/blocks/{block_id}",
headers={"Authorization": f"Bearer {key}", "Notion-Version": "2022-06-28"},
method="DELETE",
)
返回 200 即成功。Notion API 不支持"移动 block",只能 delete + re-append。
comment is not a property that exists数据库中属性名是 comment (尾部有空格),但 API 要求精确匹配。忽略此属性即可,不影响发布。
unauthorized)终端 curl 命令中 $NOTION_KEY 被系统掩码为 ***,导致 auth header 变成字面量 Bearer ***。必须用 Python 脚本读文件取 key。
Could not find database)两种可能:
... → Connections → 添加 Hermes发布文章之外的"博客不工作"问题主要走这两条路径。详细步骤见 references/fork-sync-and-vercel.md。
gh run list --workflow="Upstream Sync" 看最近 10 次结论。conclusion: failure 是信号。gh run view <id> --log-failed | grep -E "CONFLICT|fatal|error processing shallow" 读根因。tangly1024 → notionnext-org 或类似)→ 修 .github/workflows/sync.yaml 的 upstream_sync_repofatal: error processing shallow: 4 → aormsby sync action 的 shallow_since 找不到合并基线,等同分叉前兆gh workflow run "Upstream Sync" 验证一次,只看结论:success → 修好了;failure → log 看新的 reason。curl -sI https://blog.for-people.cn | head -3。200 + Vercel header → production 没事;只关心最近一次失败的 build。vercel login(device code)→ curl -H "Authorization: Bearer $TOKEN" "https://api.vercel.com/v6/deployments?projectId=$PRJ" 拉最近 15 次 list。errorCode: module_not_found 经常是 misnamed。真因要看 events:
curl -s -H "Authorization: Bearer $TOKEN" \
"https://api.vercel.com/v1/deployments/$DID/events" \
| python3 -c "import sys, json; print('\n'.join(e.get('text','') for e in json.load(sys.stdin) if e.get('type')=='stderr'))"
processPostData schema 严格化:TypeError: t.block[l].value.content is not iterable → 某篇 Notion 文章数据不全。会在 yaml 看到多个 [article/<slug>] [resolvePostProps] processPostData failed。gh api .../deployments/$DID/statuses 拿到结论状态。用户有时会盲复制我前一条消息里的 gh 命令 — 在多阶段任务里这经常导致在不合理时机触发 workflow(例:关闭一个 fork main 的 PR 前就先 gh workflow run)。规则:在多阶段任务里,每个 gh 命令前都必须先句子明示"前提是 X 已完成,否则 Y",且要强调当前阶段没用上。例:别顺手说"你也可以试试 gh workflow run verify", — 如果用户真去跑了,就要在下一回合补救而不是解释。
如果 fork 跟 upstream 累积几百个 conflict / 几百个 add/add,直接 git merge upstream/main 会爆炸。最小侵入恢复:
git checkout --orphan reset-fork upstream/main — 工作树 = 上游 HEAD,父历史脱离 fork 完全分叉状态。origin/main(git show origin/main:<path>)拷回 fork-only 个性化文件(典型: blog.config.js、conf/*、public/css/custom.css、public/favicon.ico、.github/workflows/sync.yaml 里的 fork 特定改)。git commit -m "chore(rebase): reapply fork-specific overlays on <upstream version>"。PATCH /repos/{owner}/{repo} 把 default_branch 改成目标 branch(例如 reset-fork)DELETE /repos/{owner}/{repo}/git/refs/heads/<old-main>POST /repos/{owner}/{repo}/git/refs 重建 <new-main> 指到新 commitPATCH /repos/{owner}/{repo} 把 default_branch 改回 maingh workflow run "Upstream Sync" 验证 sync 健康。如果结论 "No new commits to sync. Finishing sync action gracefully." — 修复成功。yarn build 试图验证 Vercel — 让 Vercel 自己 webhook 触发;如果 fork main 出现"删了重建",Vercel 可能错过新 ref,手动 trigger 一次(选项见 references)或等下一个 push。Could not find database)两种可能:
... → Connections → 添加 Hermes