NocoBase Page Building
Core Philosophy: Agent-First Development
This toolkit is designed for AI agents to build and maintain pages. Every tool
prioritizes agent convenience with sensible defaults:
- -
nb_crud_page: One call builds a complete page — agents don't need to
orchestrate 8+ individual tools.
- - Detail popup auto-generation: When
detail_json is omitted, the detail popup
is automatically generated from the edit form's field layout (same fields, same
dividers, minus required markers). Agents ONLY need to specify
detail_json when
they want sub-table tabs or custom blocks beyond the main detail fields.
- -
nb_inspect_page: Compact visual output designed for agent comprehension —
structure at a glance, not raw JSON.
- -
nb_read_node: Deep-dive into any node's event flows, JS code, or linkage
rules when debugging.
Defaults eliminate unnecessary work. If something has a sensible default, the
agent should NOT specify it. The less the agent writes, the fewer mistakes.
You are guiding the user to build pages in NocoBase using FlowModel API. Follow this exact workflow.
Key Concepts
Group vs Page
- - Group (📁): Folder in sidebar. NO content, only holds children.
- Page (📄): Has actual content (tables, forms, etc.). Must be under a group.
FlowModel Tree Structure
CODEBLOCK0
CRITICAL: FlowModel API is Full Replace
The
flowModels:update API does a
full replace, not incremental merge. The client always does GET → deep_merge → PUT internally. Never send partial data.
Recommended: Fast Path (nbcrudpage)
For standard CRUD pages, use nb_crud_page — it creates layout + KPIs + filter + table + forms + popup in ONE call:
CODEBLOCK1
This replaces 8+ individual tool calls with ONE call. Use this for every standard page.
When to use individual tools instead:
- - Non-standard layouts (multiple tables on one page)
- JS blocks, event flows, outlines
- Page modifications after initial build
Manual Path (Individual Tools)
Phase 1: Menu Structure
Use nb_create_menu for the simplest approach:
CODEBLOCK2
This creates a group + pages in one call, returning {"Asset Ledger": "tab_uid_1", "Purchases": "tab_uid_2"}.
Or build manually:
- 1.
nb_create_group("Module Name", parent_id) — creates the folder - INLINECODE10 — creates each page
Phase 2: Page Content (Per Page)
For each page, follow this order:
Step 1: Create Page Layout
nb_page_layout("tab_uid") → returns grid_uid
This cleans existing content (idempotent) and creates a BlockGridModel.
Step 2: Create KPI Cards (Optional)
CODEBLOCK4
Step 3: Create Filter/Search Bar
CODEBLOCK5
Parameters:
- -
label (str, default "Search"): Placeholder label for the search input.
Note: Create filter AFTER table (needs table_uid for target), but place it ABOVE in layout.
Step 4: Create Table Block
CODEBLOCK6
Parameters:
- -
first_click (bool, default true): If true, the first column becomes click-to-open
(users click to view detail popup). Set to
false if no detail popup needed.
- -
title (str, optional): Card header title displayed above the table.
Returns: INLINECODE17
Step 5: Create AddNew Form
CODEBLOCK7
Fields DSL syntax:
- -
name — single field, full width - INLINECODE19 — required field
- INLINECODE20 — two fields side by side (auto 12+12)
- INLINECODE21 — explicit widths (total=24)
- INLINECODE22 — divider with label
- INLINECODE23 — plain divider
Step 6: Create Edit Action
CODEBLOCK8
Step 7: Set Layout
CODEBLOCK9
Layout rules:
- - Each row is an array of
[uid, span] pairs - Spans use Ant Design grid (total = 24 per row)
- INLINECODE25 or
[["uid",24]] = full width - INLINECODE27 = two equal columns
Step 8: Detail Popup (Auto-Generated by Default)
You usually DON'T need to specify detail_json. When omitted in nb_crud_page,
a "详情" tab is auto-generated using the same field layout as the Edit form
(form_fields DSL minus * required markers). This gives every page a meaningful
detail popup with zero extra work.
Only specify detail_json when you need:
- - Sub-table tabs (e.g., customer → contacts, orders)
- JS blocks or custom layout inside the popup
- A different field layout from the edit form
CODEBLOCK10
Detail popup modes:
- -
mode="drawer" + size="large" — side panel, good for business detail pages - INLINECODE34 +
size="medium" — smaller side panel, for reference data - INLINECODE36 +
size="small" — modal dialog, for quick views
Finding the click field UID:
The first column in a table created with first_click=true is clickable. Use the clickfielduid from the column's DisplayFieldModel. The field_name passed to the find function must match the first column's field name.
Multi-tab detail popup with sub-tables:
[
{"title": "Details", "blocks": [
{"type": "details", "fields": "--- Section 1\\nfield1 | field2\\nfield3"}
]},
{"title": "Sub Items", "assoc": "items", "coll": "nb_order_items",
"fields": ["name", "quantity", "price", "createdAt"]}
]
Note: The
assoc sub-table requires an o2m relation to be defined between the parent and child collections.
Step 9: Outlines — Plan JS Capabilities (Recommended)
Use
nb_outline to plan JS blocks/columns without writing actual code.
A dedicated JS agent implements them later.
kind parameter (default "block"):
- -
"block" — creates JSBlockModel on page grid (for KPI cards, charts) - INLINECODE44 — creates JSColumnModel in a table (for status tags, computed columns)
- INLINECODE45 — creates JSItemModel in a form (for computed form fields)
CODEBLOCK12
Step 10: Event Flows (Optional)
CODEBLOCK13
Step 11: JS Columns — Direct Implementation (Alternative to Outlines)
CODEBLOCK14
Parameters:
- -
width (int, optional): Column width in pixels. Omit for auto-width.
Phase 3: Verify & Debug — Three-Level Drill-Down
CODEBLOCK15
Full tree (for raw UIDs): INLINECODE47
Workflow: Debug → Locate → Fix
- 1.
nb_inspect_page — find the problem area (empty popup, wrong layout, hidden-point hints) - INLINECODE49 — see the actual event flow code or configuration
- INLINECODE50 /
nb_patch_field / nb_js_block — fix it
Common Patterns
Standard CRUD Page
- 1.
page_layout → grid - INLINECODE54 × N → kpi cards
- INLINECODE55 → table + addnew + actcol
- INLINECODE56 → search bar (target=table)
- INLINECODE57 → new record form
- INLINECODE58 → edit record form
- INLINECODE59 → arrange: KPIs row → filter → table
- Optionally:
detail_popup, INLINECODE61
KPI Row Pattern
CODEBLOCK16
Multi-Block Detail Popup
CODEBLOCK17
Page Modification & Debugging
For tweaking existing pages or diagnosing issues:
CODEBLOCK18
nb_patch_field common patches:
CODEBLOCK19
nb_patch_column common patches:
CODEBLOCK20
nb_delete_route — remove a menu item:
CODEBLOCK21
Batch inspect — check all pages in a system:
CODEBLOCK22
Ant Design Icons
Common icons for menus:
homeoutlined,
settingoutlined,
databaseoutlined,
shoppingcartoutlined,
bankoutlined,
tooloutlined,
formoutlined,
barchartoutlined,
piechartoutlined,
idcardoutlined,
caroutlined,
containeroutlined,
clusteroutlined,
apartmentoutlined,
environmentoutlined,
shopoutlined,
controloutlined,
appstoreoutlined,
inboxoutlined,
deleteoutlined,
swapoutlined, INLINECODE86
Status Tag Colors
For
ctx.antd.Tag in JS columns/blocks:
- - Green: active, completed, approved →
color: 'green' or INLINECODE89 - Blue: in progress, processing →
color: 'blue' or INLINECODE91 - Orange: pending, warning →
color: 'orange' or INLINECODE93 - Red: error, rejected, overdue →
color: 'red' or INLINECODE95 - Default: draft, inactive → INLINECODE96
NocoBase 页面构建
核心理念:智能体优先开发
本工具包专为AI智能体构建和维护页面而设计。每个工具都通过合理的默认值优先考虑智能体的便利性:
- - nbcrudpage:一次调用即可构建完整页面——智能体无需编排8个以上的独立工具。
- 详情弹窗自动生成:当省略detailjson时,详情弹窗会根据编辑表单的字段布局自动生成(相同字段、相同分隔线,仅去除必填标记)。智能体仅需在需要子表格标签页或主详情字段之外的自定义区块时指定detailjson。
- nbinspectpage:专为智能体理解而设计的紧凑可视化输出——一眼看清结构,而非原始JSON。
- nbreadnode:调试时深入查看任意节点的事件流、JS代码或联动规则。
默认值消除不必要的工作。 如果某功能有合理的默认值,智能体不应指定它。智能体写得越少,错误就越少。
您正在引导用户使用FlowModel API在NocoBase中构建页面。请遵循此精确工作流程。
关键概念
分组 vs 页面
- - 分组 (📁):侧边栏中的文件夹。无内容,仅包含子项。
- 页面 (📄):包含实际内容(表格、表单等)。必须位于分组下。
FlowModel树结构
标签页 (RouteModel)
└── BlockGridModel (布局容器)
├── TableBlockModel (表格)
│ ├── TableColumnModel (列) → DisplayFieldModel
│ ├── AddNewActionModel → ChildPageModel → CreateFormModel
│ ├── TableActionsColumnModel → EditActionModel
│ └── FilterActionModel, RefreshActionModel
├── FilterFormBlockModel (搜索栏)
├── JSBlockModel (自定义JS内容)
└── ...更多区块
关键:FlowModel API为全量替换
flowModels:update API执行的是
全量替换,而非增量合并。客户端内部始终执行GET → deep_merge → PUT。切勿发送部分数据。
推荐:快速路径 (nbcrudpage)
对于标准CRUD页面,使用nbcrudpage——它一次调用即可创建布局 + KPI + 筛选器 + 表格 + 表单 + 弹窗:
nbcrudpage(tabuid, nbcrm_customers,
[name,code,status,industry,phone,createdAt],
--- 基本信息\nname* | code\ncustomer_type | industry\nstatus | level\n--- 联系方式\nphone | email\naddress,
filter_fields=[name,status,industry],
kpis_json=[{title:客户总数},{title:已签约,filter:{status:已签约},color:#52c41a},{title:跟进中,filter:{status:跟进中},color:#1890ff}],
detailjson=[{title:客户详情,fields:name | code\nstatus | level\nindustry | scale\nphone | email\naddress\nremark},{title:联系人,assoc:contacts,coll:nbcrm_contacts,fields:[name,position,mobile,email]}])
这用一次调用取代了8个以上的独立工具调用。每个标准页面都使用此方法。
何时使用独立工具:
- - 非标准布局(一个页面上多个表格)
- JS区块、事件流、大纲
- 初始构建后的页面修改
手动路径(独立工具)
阶段1:菜单结构
使用nbcreatemenu实现最简单的方法:
nbcreatemenu(资产管理, topgroupid,
[[资产台账,databaseoutlined],[采购管理,shoppingcartoutlined]],
group_icon=bankoutlined)
这通过一次调用创建分组+页面,返回{资产台账: tabuid1, 采购管理: tabuid2}。
或手动构建:
- 1. nbcreategroup(模块名称, parentid) — 创建文件夹
- nbcreatepage(页面名称, groupid) — 创建每个页面
阶段2:页面内容(每个页面)
对于每个页面,按以下顺序操作:
步骤1:创建页面布局
nbpagelayout(tabuid) → 返回 griduid
这会清理现有内容(幂等)并创建一个BlockGridModel。
步骤2:创建KPI卡片(可选)
nbkpiblock(grid, 总计, nbpmprojects)
nbkpiblock(grid, 活跃, nbpmprojects, filter_={status:active}, color=#52c41a)
步骤3:创建筛选/搜索栏
nbfilterform(grid, nbpmprojects, [name,code,description], targetuid=tableuid)
参数:
- - label (str, 默认 搜索):搜索输入的占位符标签。
注意:在表格之后创建筛选器(需要table_uid作为目标),但在布局中将其放置在上方。
步骤4:创建表格区块
nbtableblock(grid, nbpmprojects,
[name,code,status,priority,createdAt],
first_click=true, title=项目)
参数:
- - first_click (bool, 默认 true):如果为true,第一列变为可点击打开(用户点击查看详情弹窗)。如果不需要详情弹窗,设置为false。
- title (str, 可选):显示在表格上方的卡片标题。
返回:{tableuid, addnewuid, actcol_uid}
步骤5:创建新增表单
nbaddnewform(addnewuid, nbpm_projects,
--- 基本信息\nname* | code\nstatus | priority\n--- 详细信息\ndescription)
字段DSL语法:
- - name — 单个字段,全宽
- name* — 必填字段
- name | code — 两个字段并排(自动12+12)
- name:16 | code:8 — 显式宽度(总计=24)
- --- 章节标题 — 带标签的分隔线
- --- — 普通分隔线
步骤6:创建编辑操作
nbeditaction(actcoluid, nbpm_projects,
--- 基本信息\nname* | code\nstatus | priority\n--- 详细信息\ndescription)
步骤7:设置布局
nbsetlayout(grid_uid, [
[[kpi1,6],[kpi2,6],[kpi3,6],[kpi4,6]],
[[filter1]],
[[table1]]
])
布局规则:
- - 每行是一个[uid, span]对组成的数组
- 跨度使用Ant Design网格(每行总计=24)
- [[uid]] 或 [[uid,24]] = 全宽
- [[a,12],[b,12]] = 两个等宽列
步骤8:详情弹窗(默认自动生成)
通常不需要指定detailjson。 在nbcrudpage中省略时,会使用与编辑表单相同的字段布局(formfields DSL减去*必填标记)自动生成一个详情标签页。这为每个页面提供了一个有意义的详情弹窗,无需额外工作。
仅在需要以下内容时指定detail_json:
- - 子表格标签页(例如,客户 → 联系人、订单)
- 弹窗内的JS区块或自定义布局
- 与编辑表单不同的字段布局
自定义详情弹窗(仅在需要时)
nb
detailpopup(click
fielduid, nb
pmprojects, [
{title:信息, fields:--- 基本信息\\nname | code\\nstatus},
{title:任务, assoc:tasks, coll:nb
pmtasks, fields:[name,status]}
], mode=drawer, size=large)
详情弹窗模式:
- - mode=drawer + size=large — 侧面板,适合业务详情页面
- mode=drawer + size=medium — 较小侧面板,适合参考数据
- mode=dialog + size=small — 模态对话框,适合快速查看
查找可点击字段UID:
使用firstclick=true创建的表格中的第一列是可点击的。使用该列的DisplayFieldModel中的clickfielduid。传递给查找函数的fieldname必须与第一列的字段名称匹配。
带子表格的多标签页详情弹窗:
json
[
{title: 详情, blocks: [