Install
openclaw skills install mofang-page-builderBuild Magicflu/Mofang web-table custom pages from the jsonv2 records API. Use when users ask for Magicflu/Mofang forms, records, lists, create/edit/detail/admin CRUD pages, H5 extension pages, React/Vue/vanilla JS examples, local jsonv2 mock/proxy debugging, or same-origin publishing to Magicflu websites. Works as a standalone skill for Codex/OpenAI, OpenClaw, Claude Code, Trae, and Trae CN.
openclaw skills install mofang-page-builderUse this skill to generate and publish Magicflu/Mofang web-table pages. The safe path is:
spaceId, formId, and page type.fielddef.name values from fielddef.fields[].mock-jsonv2 or proxy.CONFIG.apiBase to '' before same-origin publishing.Copy the whole mofang-page-builder/ folder, not only SKILL.md.
| Client | Project install | Global install |
|---|---|---|
| Claude Code | .claude/skills/mofang-page-builder/ | ~/.claude/skills/mofang-page-builder/ |
| Trae | .trae/skills/mofang-page-builder/ | ~/.trae/skills/mofang-page-builder/ |
| Trae CN | .trae/skills/mofang-page-builder/ | ~/.trae-cn/skills/mofang-page-builder/ |
Keep these directories with the skill: examples/, assets/, references/, and scripts/.
Never guess real form field names from Chinese labels. For real data:
spaceId and formId.
/magicflu/service/json/spaces/feed./magicflu/service/json/spaces/feed?start=0&limit=-1&bq=(created,orderby,desc)./magicflu/service/s/json/{spaceId}/forms/feed.scripts/fetch-form-spec.mjs, or ask the user for an exported fielddef JSON and import it.fielddef.fields[].name as API keys, submit keys, and filter field names.fielddef.fields[].label only for UI text.Example fields in examples/ and assets/mock-data/ are demos only.
Generated pages must include:
const CONFIG = {
apiBase: '', // local debug: 'http://127.0.0.1:3847'; same-origin production: ''
spaceId: 'YOUR_SPACE_ID',
formId: 'YOUR_FORM_ID',
};
function apiUrl(path) {
const origin = CONFIG.apiBase ? CONFIG.apiBase.replace(/\/$/, '') : '';
return `${origin}${path}`;
}
Same-origin pages rely on browser Cookie auth. Do not set an Authorization header in page code.
Read references/api-summary.md when you need endpoint details, bq syntax, response shape, or field value formats.
Core paths:
| Capability | Method | Path |
|---|---|---|
| List all spaces | GET | /magicflu/service/json/spaces/feed?start=0&limit=-1&bq=(created,orderby,desc) |
| Find spaces by label | GET | /magicflu/service/json/spaces/feed?start=0&limit=10&bq=(label,eq,{spaceLabel}) |
| List forms in a space | GET | /magicflu/service/s/json/{spaceId}/forms/feed?start=0&limit=-1 |
| Find forms by label | GET | /magicflu/service/s/json/{spaceId}/forms/feed?start=0&limit=10&bq=(label,eq,{formLabel}) |
| Field definition | GET | /magicflu/service/s/jsonv2/{spaceId}/forms/{formId}?selector=fielddef&lng=en |
| List records | GET | /magicflu/service/s/jsonv2/{spaceId}/forms/{formId}/records/entry |
| Create record | POST | /magicflu/service/s/jsonv2/{spaceId}/forms/{formId}/records |
| Update record | PUT | /magicflu/service/s/jsonv2/{spaceId}/forms/{formId}/records/entry/{recordId} |
| Delete record | DELETE | /magicflu/service/s/jsonv2/{spaceId}/forms/{formId}/records/entry/{recordId} |
Use the spaces endpoint when the user gives only a space name. The returned space id is items[].id; the display name is items[].label. Use the form-list endpoint when the user gives only a spaceId or form label. The returned form id is feed.entry[].id; the display name is feed.entry[].content.form.label; the English form key is feed.entry[].content.form.name.
Field rules:
name, not label."" for number fields.Account/password:
BASE_URL="http://appdev.com.magicflu.com:9999" \
MOFANG_USERNAME="你的账号" \
MOFANG_PASSWORD='你的密码' \
node scripts/fetch-form-spec.mjs \
--spaceId <空间UUID> \
--formId <表单UUID> \
--out ./mock-data
If only names are known, resolve and fetch in one command:
BASE_URL="http://appdev.com.magicflu.com:9999" \
MOFANG_USERNAME="你的账号" \
MOFANG_PASSWORD='你的密码' \
node scripts/fetch-form-spec.mjs \
--spaceLabel "空间名称" \
--formLabel "表单名称" \
--out ./mock-data
Cookie:
node scripts/fetch-form-spec.mjs \
--baseUrl https://你的魔方域名 \
--spaceId <空间UUID> \
--formId <表单UUID> \
--out ./mock-data \
--cookie "浏览器 Cookie"
Offline import:
node scripts/fetch-form-spec.mjs \
--spaceId <空间UUID> \
--formId <表单UUID> \
--out ./mock-data \
--import-json ./fielddef-export.json
Output: mock-data/manifest.json, mock-data/<formId>/fielddef.json, records.seed.json, typesnippets.md, and api-outline.md.
Use the bundled demo data:
cp -R assets/mock-data ./mock-data
node scripts/mock-jsonv2.mjs --port 3847 --dir ./mock-data
Set page config:
CONFIG.apiBase = 'http://127.0.0.1:3847';
Proxy to a real environment only when the user explicitly wants real data behavior:
BASE_URL="http://appdev.com.magicflu.com:9999" \
MOFANG_USERNAME="你的账号" \
MOFANG_PASSWORD='你的密码' \
node scripts/mock-jsonv2.mjs --mode proxy --port 3847
Proxy mode forwards supported space, json, and jsonv2 calls to the real environment. POST, PUT, and DELETE will change real records.
Before publishing, set page CONFIG.apiBase to ''.
BASE_URL="http://appdev.com.magicflu.com:9999" \
MOFANG_USERNAME="你的账号" \
MOFANG_PASSWORD='你的密码' \
node scripts/deploy.mjs \
--spaceId <空间UUID> \
--label "站点名称" \
--shortcut custom-page \
--files index.html
The deploy script logs in, creates a website, warms the session, uploads files through filemanager.jsp, and prints the final URL:
{BASE_URL}/magicflu/html/sites/userfiles/{spaceId}/{websiteId}/index.html
Read references/design.md, references/requirements.md, and references/filemanager.js only when debugging implementation details.
| Stack | File | Purpose |
|---|---|---|
| Vanilla HTML+JS | examples/vanilla/list-page.html | Same-origin list page |
| Vanilla HTML+JS | examples/vanilla/list-page-with-apibase.html | List page wired to local mock |
| Vanilla HTML+JS | examples/vanilla/form-page.html | Create-record form |
| React | examples/react/MagicfluList.tsx | List component |
| Vue | examples/vue/MagicfluForm.md | Text-safe create-record form component |
Run these from the skill root:
npm run check:scripts
npm run smoke:fetch-import
npm run smoke:mock
npm run smoke:upload