关于 frappe-ops-website-deploy
frappe-ops-website-deploy 是用于将静态 HTML/CSS 网站部署到 ERPNext v15/v16 的技能。内容涵盖 Page Builder、REST API、样式与图片处理及内置讨论功能,并说明 v16 的页面渲染限制。
主要功能
- 01Page Builder 部署指导
- 02原始 HTML 的 Web Template 配置
- 03Web Page 与 Website Settings API 模式
- 04CSS 放置与包装元素修正
- 05讨论论坛集成指导
- 06认证与部署故障排查
适用场景
- 01将静态 HTML 模型页面部署为 ERPNext 页面
- 02通过 REST API 更新页面和站点设置
- 03为网站添加讨论论坛
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ impertio-studio/ frappe_claude_skill_package --skill frappe-ops-website-deploy安装后在 Claude Code 中输入/frappe-ops-website-deploy确认已加载。
附带文件references/frappe-wrapper-elements.mdscripts/deploy.py
详细介绍
在 ERPNext/Frappe 上部署网站
使用 Web Pages、Page Builder 和 REST API,将静态 HTML/CSS 网站部署到 ERPNext v15/v16 的模式。
重要:ERPNext v16 不会渲染 main_section
在 Frappe v16 中,Web Page 上的 main_section 字段会被存储,但不会在浏览器中渲染——即使设置了 content_type: "HTML" 或 dynamic_template: 1 也是如此。Page Builder(page_blocks)是主要的渲染机制。
必须使用 page_blocks 和自定义 Web Template 来渲染 HTML 内容。
决策树
What do you need?
├── Deploy HTML pages to ERPNext
│ ├── Step 1: Create "Raw HTML Section" Web Template (one-time)
│ ├── Step 2: Create Web Pages with page_blocks
│ └── Step 3: Configure Website Settings
│
├── Add a forum / discussion system
│ └── Use Frappe's built-in Discussion Topic/Reply + Discussions Web Template
│
├── Manage CSS
│ ├── Per-page CSS → Web Page `css` field
│ ├── Global CSS → Website Settings `head_html`
│ └── WARNING: Never stack !important overrides (see CSS Management)
│
└── Configure navigation
└── Website Settings: top_bar_items, footer_items, brand_html, home_page
第 1 步:创建 Raw HTML Section Web Template
这是一次性设置。该模板接受原始 HTML 并按原样渲染。
POST /api/resource/Web%20Template
{
"name": "Raw HTML Section",
"type": "Section",
"template": "{{ values.html_content }}",
"fields": [
{
"fieldname": "html_content",
"fieldtype": "Text",
"label": "HTML Content"
}
]
}
重要限制:
fieldtype必须为"Text"——Frappe 不接受 Web Template 字段使用"Code"- 允许的字段类型:
Attach Image、Check、Data、Int、Link、Select、Small Text、Text、Markdown Editor、Section Break、Column Break、Table Break - 模板使用
{{ values.html_content }}(带values.前缀)访问字段数据
第 2 步:使用 Page Builder 创建 Web Pages
每个页面都需要设置 content_type: "Page Builder",并将 HTML 放入 page_blocks。
POST /api/resource/Web%20Page
{
"title": "Page Title",
"route": "my-page",
"published": 1,
"show_title": 0,
"full_width": 1,
"content_type": "Page Builder",
"css": "<per-page CSS here>",
"page_blocks": [
{
"web_template": "Raw HTML Section",
"web_template_values": "{\"html_content\": \"<div>Your HTML here</div>\"}"
}
]
}
重要:web_template_values 是 JSON 字符串,而不是对象。 发送前请使用 json.dumps() 将其序列化。
更新现有页面
PUT /api/resource/Web%20Page/{url_encoded_name}
按路由查找页面:
GET /api/resource/Web%20Page?filters=[["route","=","my-page"]]&fields=["name"]
第 3 步:配置 Website Settings
PUT /api/resource/Website%20Settings/Website%20Settings
{
"home_page": "home",
"brand_html": "<span style=\"...\">NL</span> My Brand",
"head_html": "<link href=\"fonts.css\" rel=\"stylesheet\">\n<style>/* global CSS */</style>",
"top_bar_items": [
{"label": "About", "url": "/about", "right": 0}
],
"footer_items": [
{"label": "About", "url": "/about"}
]
}
head_html:修复 Frappe 包装元素
Frappe 会将页面内容包裹在多个 div 中,从而产生多余的空白。将以下修复添加到 head_html:
<style>
.page-header-wrapper { display: none !important; }
.page-breadcrumbs { display: none !important; }
.page-content-wrapper { padding: 0 !important; margin: 0 !important; }
.page_content { padding: 0 !important; margin: 0 !important; }
.webpage-content { padding: 0 !important; margin: 0 !important; }
.web-page-content { padding: 0 !important; margin: 0 !important; max-width: none !important; }
.section.section-padding-top { padding-top: 0 !important; }
.section.section-padding-bottom { padding-bottom: 0 !important; }
.web-template-section { padding: 0 !important; margin: 0 !important; }
main { padding: 0 !important; margin: 0 !important; }
</style>
这些是你应该使用的唯一 !important 覆盖规则——它们针对的是 Frappe 自身的包装元素,而不是你的内容。
CSS 管理
黄金法则:保留原始样稿 CSS
在每个页面的 css 字段中使用原始样稿 CSS。只在 head_html 中添加 Frappe 包装元素修复。不要在内容 CSS 上叠加 !important 覆盖规则——这会造成层叠冲突和不可预测的布局。
CSS 的放置位置
| CSS 类型 | 位置 | 字段 |
|---|---|---|
| 样稿/页面 CSS | 每个 Web Page | css |
| Google Fonts、Frappe 修复 | Website Settings | head_html |
| CSS 变量(:root) | Website Settings | head_html |
不要这样做
不要为 .card、section、h2 等内容元素添加宽泛的 !important 覆盖规则。如果间距看起来不对,原因几乎总是 Frappe 的某个包装 div——应针对该元素修复,而不是覆盖所有内容样式。
从 HTML 样稿部署
将静态 HTML 样稿转换为 ERPNext Web Pages 时,请按以下流程操作:
1. 提取 body 内容
删除主要内容区域以外的所有内容——通常是 </header> 和 <footer> 之间的内容。移除样稿自带的导航栏和页脚,因为 Frappe 会通过 Website Settings 提供自己的导航栏和页脚。
2. 重写链接
将 .html 文件引用替换为 Frappe 路由:
href="about.html" → href="/about"
href="index.html" → href="/"
3. 处理图片
本地 img/ 引用在 ERPNext 上无法使用。可选方案:
- 通过 Frappe File Manager 上传图片,并使用返回的 URL
- 使用 File API:
POST /api/method/upload_file - 引用外部图片 URL
4. 部署脚本模式
完整的部署脚本请参阅 scripts/deploy.py。核心模式如下:
import requests, json
def deploy_page(title, route, html_content, css):
data = {
"title": title,
"route": route,
"published": 1,
"show_title": 0,
"full_width": 1,
"content_type": "Page Builder",
"css": css,
"page_blocks": [{
"web_template": "Raw HTML Section",
"web_template_values": json.dumps({"html_content": html_content})
}]
}
# Create or update (check 409 conflict for existing pages)
resp = requests.post(f"{BASE_URL}/api/resource/Web%20Page",
headers=HEADERS, json=data)
if resp.status_code == 409:
# Find and update existing
...
将论坛集成到 Frappe Discussions
Frappe 内置了可嵌入任意 Web Page 的讨论 DocType。
可用的 DocType
- Discussion Topic — 与参考文档关联的讨论串/主题
- Discussion Reply — 主题中的回复
创建论坛页面
将内置的 "Discussions" Web Template 用作页面区块:
{
"page_blocks": [
{
"web_template": "Raw HTML Section",
"web_template_values": "{\"html_content\": \"<section><div class=\\\"container\\\"><h1>Forum</h1></div></section>\"}"
},
{
"web_template": "Discussions",
"web_template_values": "{\"title\": \"Discussies\", \"cta_title\": \"Nieuw onderwerp\", \"docname\": \"forum\", \"single_thread\": 0}"
}
]
}
讨论 Web 模板字段
| 字段 | 类型 | 用途 |
|---|---|---|
title | 数据 | 区块标题 |
cta_title | 数据 | 新建主题的按钮文本 |
docname | 链接 | 要关联讨论的网页 |
single_thread | 复选框 | 0 = 多个主题,1 = 单个讨论串 |
通过 API 管理主题
POST /api/resource/Discussion%20Topic
{"subject": "My topic", "reference_doctype": "Web Page", "reference_docname": "forum"}
POST /api/resource/Discussion%20Reply
{"topic": "TOPIC0001", "reply": "My reply text"}
身份验证
所有 API 调用都需要通过令牌标头进行身份验证:
Authorization: token {api_key}:{api_secret}
在 ERPNext 中生成 API 密钥:用户设置 → API 访问 → 生成密钥。
切勿将 API 密钥存储在技能文件、SKILL.md 中,也不要将其提交到 git。 请将其作为环境变量传入,或从安全配置中读取。
故障排除
页面空白 / main_section 未渲染
你遇到了 v16 页面构建器问题。请切换为 content_type: "Page Builder" 和 page_blocks。参见步骤 2。
内容上方出现白条
Frappe 的 .page-header-wrapper 和 .page-breadcrumbs 会增加空白。通过 head_html 隐藏它们。参见步骤 3。
创建 Web 模板时出现字段类型错误
字段类型请使用 "Text",不要使用 "Code"。Frappe Web 模板仅允许使用部分字段类型。
CSS 显示异常 / 间距不正确
检查 Frappe 的 .section.section-padding-top 或 .page-content-wrapper 是否添加了内边距。请针对它们进行修复,不要使用 !important 覆盖内容 CSS。
网格布局折叠为单列
如果你的模型 CSS 中包含会覆盖网格列数的媒体查询,这些规则也会应用于 ERPNext。请检查渲染后的 CSS 是否存在冲突的媒体查询规则。
图片未显示
模型中的本地 img/ 路径无法解析。请将文件上传到 ERPNext,或使用绝对 URL。