GemDesign Prototyping
Use the gemdesign CLI to create, save, and modify high-fidelity prototype pages on the GemDesign platform. You generate HTML following the GemDesign Page Spec, validate it, then save via CLI.
When to Invoke
- User wants to create a UI prototype or design a page
- User has a requirements document and wants batch page generation
- User wants to modify an existing GemDesign page
- User wants to view existing GemDesign pages
Prerequisites
CRITICAL: Step 1, Step 2, and Step 2.5 MUST be executed strictly in order BEFORE starting any Workflow. Each step MUST fully complete before proceeding to the next. Do NOT skip, parallelize, or advance until the current step is confirmed successful.
IMPORTANT — Step 3 timing: Step 3 (Start the Local Server) is NOT executed immediately after login. It MUST be executed INSIDE a Workflow, AFTER the app is created or reused (i.e., after gemdesign app create / gemdesign app use + gemdesign app info), and BEFORE any page generation. Starting the server before the app exists is a violation — the server serves pages from the project subdirectory derived from the app, so the app must exist first.
Step 1: Verify & Install GemDesign CLI (MUST complete before Step 2)
ALWAYS verify CLI installation and version first before doing any other work. This step is a hard gate — no other operations (auth, app, page, style, etc.) may run until this step is confirmed complete.
Check if CLI is installed:
npm list -g @gemdesign-ai/cli
Check if CLI is latest version (only after step 1 confirms CLI is installed):
npm outdated -g @gemdesign-ai/cli
After this step is confirmed complete, the gemdesign-ai command is available globally at the latest version. Only then may you advance to Step 2.
Step 2: Verify Login (MUST complete after Step 1, before any Workflow)
ALWAYS verify login status after Step 1 is complete. Run this command:
gemdesign auth whoami
- If it succeeds (returns user info), the user is logged in — proceed to a Workflow (A/B/C). Step 3 (local server) will be executed INSIDE the workflow, after the app is created/reused.
- If it fails (returns an error like "GemDesign令牌 无效" or "未提供 GemDesign令牌"), the user is NOT authenticated. You MUST:
- Tell the user: if they don't have an account or GemDesign令牌 yet, go to https://design.gemcoder.com to register an account and get a GemDesign令牌. The GemDesign令牌 retrieval path is: log in to the platform -> click 个人中心 (Personal Center) -> get the GemDesign令牌 (GemDesign令牌).
- Ask the user for their GemDesign令牌 (use
AskUserQuestion tool to prompt the user to input their GemDesign令牌).
- Once the user provides their GemDesign令牌, automatically run the login command for them:
gemdesign auth login --token <user_provided_token>
- Re-verify with
gemdesign auth whoami to confirm login succeeded.
- If login still fails, repeat from step 2 (ask the user to provide their GemDesign令牌 again).
- Only proceed to a Workflow after login is confirmed.
HARD GATE: Until login is confirmed via gemdesign auth whoami, you MUST NOT perform ANY page-generation work — this includes CLI commands (app, page, style, validate) AND local file operations (writing .html, streaming write, creating the ./output/ directory). Local HTML generation is NOT a workaround for the login gate; a page can only be saved to the platform by an authenticated user, so generating it before login is wasted work. If login fails, stop and resolve authentication first — do not start writing any HTML.
Step 2.5: Clean Up and Configure htmlWorkdir (MUST complete after Step 2, before any Workflow)
After login is confirmed, FIRST clean up stale empty project directories left over from previous interrupted sessions, THEN configure the HTML working directory (htmlWorkdir). The order is MANDATORY: cleanup MUST run BEFORE workdir --path, never after. Both operations MUST complete before starting any Workflow (in particular, before app create).
CRITICAL — Why cleanup MUST run BEFORE workdir (order is non-negotiable): gemdesign server workdir --path ./output creates the ./output directory — at this moment it is an empty workdir with NO project subdirectories ({projectName}__{appuuid}) yet, because app create has not run. gemdesign server cleanup runs pruneEmptyWorkdirs(), which deletes any workdir directory that contains zero project subdirectories AND removes it from the htmlWorkdir config. If you run workdir first and then cleanup, the freshly-created empty ./output is treated as a stale empty workdir — cleanup deletes the directory and wipes it from config, leaving htmlWorkdir empty. Downstream effect: app create skips local folder creation (returns a warning), and server start refuses to start ("未配置 htmlWorkdir..."), causing "page generated but canvas not showing". Running cleanup FIRST avoids this: it clears stale state from previous sessions, then workdir creates ./output LAST so it survives. (Note: cleanup does NOT require htmlWorkdir to be pre-configured — when unconfigured it simply returns "未配置 htmlWorkdir,无需清理" and exits cleanly.)
Clean up empty project directories (MUST run FIRST, before configuring htmlWorkdir):
gemdesign server cleanup
- If
htmlWorkdir is not configured yet, the command returns {"success":true,"message":"未配置 htmlWorkdir,无需清理","removedDirs":[],"removedLocks":[],"removedWorkdirs":[],"removedWorkdirDirs":[]} — this is normal, continue to step 2.
- If
htmlWorkdir is already configured from a previous session, the command scans each configured workdir for project subdirectories (named {projectName}__{appuuid}) and:
- Deletes empty project directories: project subdirectories that contain zero
.html files (created by app create but never had a page saved — e.g., the session was interrupted).
- Cleans orphaned streaming files:
.stream.lock files left over from streaming write that was started but never completed.
- Removes empty workdirs: workdir directories that contain zero project subdirectories are deleted and removed from config (this is exactly why
workdir --path MUST run AFTER cleanup, not before).
- Returns JSON:
{"success":true,"message":"清理完成:删除 N 个空项目目录,清理 M 个遗留文件,移除 K 个无项目的 htmlWorkdir","removedDirs":[...],"removedLocks":[...],"removedWorkdirs":[...],"removedWorkdirDirs":[...]}
- This step is non-blocking: cleanup failures do not prevent proceeding to a Workflow. The command always returns
success: true unless an unexpected error occurs.
Configure htmlWorkdir (MUST run AFTER step 1; run once, persists across sessions):
CRITICAL - app create sync-creates the local project folder under htmlWorkdir, and server start validates htmlWorkdir before launching. If htmlWorkdir is not configured, app create skips local folder creation (returns a warning), and server start returns {"success":false,"error":"未配置 htmlWorkdir,请先执行 gemdesign server workdir --path <path> 设置 HTML 工作目录"} and refuses to start. This prevents the background process's cwd from mismatching the actual HTML generation directory, which would cause fileWatcher to miss .html changes and the canvas to stay blank ("page generated but canvas not showing").
gemdesign server workdir --path ./output
- Relative paths are resolved against the current working directory to an absolute path.
- Verify with
gemdesign server workdir (no flags) - returns {"success":true,"htmlWorkdir":["<absolute path>"]}.
- The
./output directory created here will NOT be deleted by cleanup within this same Step 2.5, because cleanup already ran in step 1. Do NOT re-run cleanup after this step — re-running it would delete the freshly-created empty ./output (since app create has not run yet and there are no project subdirectories).
Step 3: Start the Local Server (MUST complete after app is created/reused, before any page generation)
CRITICAL - HARD GATE: You MUST open the browser in this step. This is NON-NEGOTIABLE and MUST NOT be skipped, deferred, or treated as optional. Generating any page before the browser is open is a SERIOUS VIOLATION - the user needs the real-time preview surface to see pages as they are generated. You MUST actively open the browser yourself using your platform's built-in browser/preview tool (see step 3 below for the fallback strategy). Do NOT just output a URL in chat text and wait for the user to click it — you MUST programmatically open the browser.
TIMING — Execute INSIDE a Workflow, NOT immediately after login. Step 3 is invoked from within Workflow A/B/C (see each workflow's "Start the local server" step), AFTER the app has been created or reused via gemdesign app create / gemdesign app use and confirmed via gemdesign app info. Do NOT start the server right after Step 2 (login) — the server serves pages from the project subdirectory derived from the app (<projectDir> = {projectName}__{appuuid}), so the app must exist first. Starting the server before the app exists is a violation.
After Step 1 (CLI installed), Step 2 (Login verified), AND the app is created/reused (inside a Workflow) are all confirmed complete, start the local server for real-time streaming preview.
The local server provides real-time streaming preview of HTML pages as they are being generated. The server is built into the CLI and managed via the gemdesign server commands. The server runs on port 4056 by default; if that port is occupied it auto-retries the next available port (up to 4066).
Ensure htmlWorkdir is configured (MUST complete before app create in a Workflow, and before server start):
htmlWorkdir is configured in Step 2.5 (persists across sessions). app create sync-creates the local project folder under htmlWorkdir, and server start validates htmlWorkdir before launching — if it is not configured, app create skips local folder creation (returns a warning) and server start refuses to start, causing fileWatcher to miss .html changes and the canvas to stay blank ("page generated but canvas not showing").
If Step 2.5 was skipped (e.g. resuming a session), verify now: gemdesign server workdir (no flags) returns {"success":true,"htmlWorkdir":"<absolute path>"}. If it returns an empty htmlWorkdir, run gemdesign server workdir --path ./output before proceeding.
Stop any previously running server (MANDATORY before every server start, CANNOT be skipped):
CRITICAL — 执行 server start 之前必须先执行 server stop 终止之前启动的服务,无论应用是新建还是复用都不可跳过。这确保 fileWatcher 绑定到正确的项目目录,避免残留进程干扰新会话。
HARD GATE - 严禁跳过此步:无论你认为当前是否已有服务在运行,都必须执行 gemdesign server stop 命令。禁止以"服务器未运行"、"上一次会话已启动"、"浏览器预览已打开"、"为了节省时间"等任何理由跳过 stop。必须以 gemdesign server stop 的实际返回结果作为唯一判定依据。
gemdesign server stop
- 返回
{"success":true,"message":"本地服务已停止"} 表示已停止,继续下一步。
- 返回
{"success":false,"error":"未发现运行中的本地服务"} 表示无运行中的服务,忽略此错误继续下一步。
- 必须等待上述命令返回结果后才能进入第 2 步。在 stop 命令未返回前,不得执行任何
server start 操作。
Start the local server using the CLI command:
gemdesign server start
必须在执行此命令前先完成上一步的 gemdesign server stop,不得在未停止旧服务的情况下直接 start。
HARD GATE - 顺序约束:server start 必须在 server stop 命令返回结果(成功或"未发现运行中的本地服务"错误)之后才能执行。严禁以下行为:
- 将
server stop 与 server start 并行执行(例如在同一个并行工具调用批次中);
- 在
server stop 命令尚未返回结果时就发起 server start;
- 先执行
server start 再执行 server stop;
- 因为"觉得没必要 stop"而跳过 stop 直接 start。
正确顺序:执行 gemdesign server stop -> 等待命令返回结果 -> 执行 gemdesign server start。这是不可逆的串行依赖关系。
- If the server starts successfully, the command returns JSON:
{"success":true,"port":<port>,"url":"http://localhost:<port>"}
- If the server fails to start, the command returns JSON with an error:
{"success":false,"error":"<error message>"}
- On error: Read the error message carefully. Common errors:
"服务文件不存在": The CLI installation is incomplete — reinstall the CLI.
"服务启动失败,进程已退出": Possible port conflict or config file error — check ~/.gemdesign/config.json.
- Record the
<port> from the success response for subsequent steps.
Check server status (optional, for debugging):
gemdesign server status
Returns: {"success":true,"status":"running","port":<port>,"url":"http://localhost:<port>"} or {"success":true,"status":"stopped"}
Open the preview (MANDATORY — HARD GATE, DO NOT SKIP): After the server is confirmed running (the server start command returned success), you MUST open the browser and navigate to the service page named GemDesign设计器 (URL: http://localhost:<port> - use the port from the server start response).
This step is NON-NEGOTIABLE. Do NOT proceed to any page generation workflow (Workflow A/B/C) until the browser is open at http://localhost:<port>. The server being up is NOT the same as the preview being open - the user must SEE the preview surface in the browser.
DO NOT just output a URL in chat text. You MUST use a tool to actually open the browser. Outputting something like "服务器启动成功!请在浏览器中打开 http://localhost:4056" is a VIOLATION — the browser must be opened programmatically, not by asking the user to click a link.
How to open the browser — use the following methods in priority order:
Try the following methods in priority order. Use the FIRST one that is available and succeeds. If a method fails, skip it and try the next:
| Priority |
Method |
How to use |
| 1 |
Your platform's built-in browser/preview tool |
You MUST check what browser/preview tools are available on your current agent platform and use the most appropriate one. Different platforms provide different built-in tools — use whichever one your platform offers. Examples of platform-specific tools: Trae provides OpenPreview and the integrated_browser MCP's browser_navigate; Cursor provides its own preview mechanism; other platforms may have equivalent tools. The key requirement is: you MUST use a tool to programmatically open the browser, not just output a URL in chat. Navigate to http://localhost:<port>/ using the tool. |
| 2 |
OS default browser command |
If no built-in browser/preview tool is available (or it failed), open the default browser via OS command: Windows start http://localhost:<port>/, macOS open http://localhost:<port>/, Linux xdg-open http://localhost:<port>/. |
| 3 |
Tell the user to open the URL |
If ALL above methods fail or are unavailable, as a last resort, clearly tell the user: "请在浏览器中打开 http://localhost:/ 查看设计器预览" and wait for the user to confirm before proceeding. |
How to find your platform's built-in tool: Check your available tools list — look for tools with names like OpenPreview, browser_navigate, preview, browser, or similar. Any tool that can open a URL in a browser panel qualifies. Use it with the URL http://localhost:<port>/.
Ensuring success:
- If the highest-priority method returned an error or you're unsure whether it succeeded, immediately fall back to the next method in the table.
- After opening the browser, verify the server is still accessible by re-checking the debug endpoint (
http://localhost:<port>/api/local/stream/debug returns 200).
- Only proceed to page generation after you have made a best-effort attempt to open the browser using at least one available method.
After the preview is open, you may proceed to page generation workflows.
CRITICAL - The browser is opened EXACTLY ONCE, only here in Step 3. Once the browser is open at http://localhost:<port> (the designer SPA root), you MUST NEVER open the browser again — not during page generation (Workflows A/B/C), not during modification flows, not to "refresh" or "show" a generated page. The designer SPA stays open for the entire session; generated HTML is loaded into an iframe INSIDE the designer via SSE (see "Streaming Write Workflow"), NOT by navigating the browser to a new URL.
Opening the browser again will navigate it away from the designer to whatever URL you passed — this OVERWRITES the designer with the generated HTML (or a 404), destroying the preview surface the user needs. The URL used to open the browser MUST ALWAYS be the designer root URL http://localhost:<port>/ — NEVER a path to a generated .html file (e.g. http://localhost:<port>/output/<projectDir>/<pageuuid>.html), NEVER a page-specific URL. Generated pages have no direct browser URL; they are only viewable through the designer's iframe via SSE.
CLI Command Reference
Server Management
gemdesign server start [--port <port>] # 启动本地设计器服务(默认端口 4056)
gemdesign server stop # 停止本地设计器服务
gemdesign server status # 查看服务运行状态
gemdesign server workdir --path <path> # 保存 HTML 工作目录(htmlWorkdir,相对路径基于当前目录解析为绝对路径)
gemdesign server workdir # 查看当前 htmlWorkdir
gemdesign server workdir --clear # 清除 htmlWorkdir 配置
gemdesign server cleanup # 清理空项目目录和遗留的流式文件
server workdir 保存 HTML 工作目录到 ~/.gemdesign/config.json 的 htmlWorkdir 字段。本地服务启动后通过 fileWatcher 监听此目录下的 .html 文件变更,并经 SSE 推送到浏览器画布。app create 会在此目录下同步创建项目子目录 {projectName}__{appuuid},server start 也会在启动前校验 htmlWorkdir 是否已配置--未配置时 app create 跳过本地目录创建(返回 warning),server start 拒绝启动并返回错误提示,避免后台进程 cwd 与实际 HTML 生成目录不一致导致"页面生成但画布不显示"。建议在登录后、app create 之前执行一次 gemdesign server workdir --path ./output(路径通常是 ./output,即页面 HTML 的根目录)。配置一次后持久化,后续无需重复设置。
server start 以后台进程方式启动本地服务。执行 server start 之前必须先执行 server stop 终止之前的服务,不得在未停止旧服务的情况下直接 start。server stop 严禁跳过(即使你认为没有运行中的服务也必须执行该命令),且 server start 必须等 server stop 命令返回结果后才能执行——禁止将两者并行执行、或在 stop 未返回时就发起 start。启动成功返回含 port 和 url 的 JSON;失败返回含 error 的 JSON,需仔细阅读错误信息诊断并修复后再重试(重试前同样要先 stop)。
server stop stops the running server. On Windows, uses taskkill to terminate the process tree. Returns error if no server is running or if the process cannot be terminated — 此时该错误可忽略(表示本就无运行中的服务),但仍视为 stop 步骤已执行完成,可继续 start。
server status returns the current status (running or stopped), port, and URL if running.
Authentication
gemdesign auth login --token <token> # 配置 GemDesign 令牌
gemdesign auth whoami # Verify identity
App Management
gemdesign app create --name "MyApp" --workdir <path> [--type web|app] [--width <px>] [--height <px>] # Create new app (sync-creates local project folder under --workdir), --type defaults to web
gemdesign app list # List all apps
gemdesign app info [--appuuid <id>] # App details
gemdesign app use --appuuid <id> --workdir <path> # Switch current default app (creates/locates local project folder under --workdir)
app create 画布尺寸: --width/--height 用于指定画布像素尺寸。不传时按 --type 取默认值:web -> 1920×1080,app -> 440×956。传入的尺寸会随应用信息同步到本地设计器画布(覆盖默认值)。示例:gemdesign app create --name "PadApp" --type app --width 768 --height 1024。
CRITICAL - app create and app use require --workdir: app create 和 app use 的 --workdir <path> 是必填参数,指定本地项目子目录 {projectName}__{appuuid} 的父目录。路径由 agent 显式给出,CLI 不再通过配置自动猜测。--workdir 会自动追加到 htmlWorkdir 配置数组(去重),local-server 据此扫描所有项目目录。建议传入 ./output(即 gemdesign server workdir --path ./output 配置的同一目录)。page create 的 --file <path> 同理:lock 文件直接写入 --file 推导出的项目子目录,保证 lock 与 html 同目录。
appuuid priority: --appuuid flag > defaultAppUuid (set by app create/app use) > GEMDESIGN_APPUUID env
Once you run app create or app use, subsequent page commands don't need --appuuid.
IMPORTANT: Always check gemdesign app list BEFORE creating a new app. Reuse existing apps to keep all pages in the same project folder. Only create a new app when the user explicitly asks for one.
CRITICAL - Never create duplicate apps: Never call gemdesign app create more than once in a single session/task. If you have already run app create in this session, you MUST NOT run it again — even if a later workflow step or retry seems to require app setup. Instead, reuse the existing app by running gemdesign app list to find it, then gemdesign app use --appuuid <id> --workdir ./output. Creating a second app leaves the first one empty and orphaned on the platform.
CRITICAL - Session lock error handling: The CLI now automatically verifies session locks via appuuid. If app create returns stage: "appCreateSession" (session lock exists and the app still exists on remote), do NOT retry with --force. Instead: (1) Run gemdesign app use --appuuid <existingApp.appuuid> --workdir ./output to reuse the app. (2) If the existing app is from a different completed task, run gemdesign app end-session, then app create (without --force). (3) Only use --force if you have verified via app list that the session-lock app was deleted from the remote — note that the CLI now auto-cleans stale session locks (app deleted from remote), so --force should rarely be needed. (4) If app create returns stage: "appCreateSessionVerify" (unable to verify app existence due to network error), wait and retry — do NOT use --force.
CRITICAL - Restart the server around every app create or app use: 正确顺序为:gemdesign server stop -> (等待 stop 命令返回结果) -> (确保 htmlWorkdir 已配置) -> gemdesign app create / gemdesign app use -> gemdesign server start。该顺序由 workflow 步骤强制执行,不要作为独立序列重复执行。执行 server start 之前必须先执行 server stop 终止之前的服务,无论应用是新建还是复用,否则旧服务的 fileWatcher 仍绑定在前一个 app 的 <projectDir>,新页面不会推送到画布。server stop 这一步严禁跳过(即使你认为没有运行中的服务也必须执行),且 server start 必须等 server stop 命令返回结果后才能执行,禁止并行执行或先 start 后 stop。
IMPORTANT - Output app info to user: After selecting/switching/creating an app (i.e., after any app create, app use, or app info call that establishes the working app), you MUST clearly tell the user in your text response which app is now the active target for page generation. At minimum, output the app name and appuuid (and ideally the computed <projectDir>). This ensures the user always knows which app pages will be generated/modified in, and can interrupt if the wrong app was picked. See the "Output current app info to user" step in each workflow for the exact format.
CRITICAL - App type determines page type: Apps have a type - web (桌面端) or app (移动端) - returned by app info as the pageScene field. When generating new pages, the page type MUST match the app type: a web app can only contain web pages (desktop layout, wide screen), and an app app can only contain app pages (mobile layout, narrow screen). Before generating any HTML, check the app's pageScene from app info and design the page accordingly. Do NOT generate a desktop-width page for an app type app, or a mobile-width page for a web type app.
Style Search (optional helper)
gemdesign style search --keywords "科技,深蓝,企业" --limit 5 # Search styles
gemdesign style get --id <styleId> --format html # Get full style
Style search is optional. You can also design styles yourself or use other UI design skills.
Page - View
gemdesign page list [--appuuid <id>] # List pages
gemdesign page get --pageuuid <id> --file ./output/<projectDir>/<subfolder>/<id>.html # Get page HTML (auto-creates projectDir)
gemdesign page doc get --pageuuid <id> --file ./output/<projectDir>/<subfolder>/<id>.md # Get requirement doc
CRITICAL - 同步远程页面时必须保留文件夹结构:page list 返回的每个页面包含 dirName 字段(远程所在文件夹,多级用 / 分隔,根级页面为 null/空)。将远程页面同步到本地(尤其是"同步后编辑"场景)时,page get --file 的 <subfolder> 必须与该页面的 dirName 一致,即落盘到 ./output/<projectDir>/<dirName>/<pageuuid>.html。严禁将所有页面统一放到项目根目录——否则后续编辑保存时本地推导的目录与远程不一致,可能导致页面脱离远程文件夹。例:page list 返回页面 report-sales 的 dirName 为 reports,则必须执行 gemdesign page get --pageuuid report-sales --file ./output/<projectDir>/reports/report-sales.html。
Page - Create (streaming mode)
gemdesign page create --pageuuid <readable-id> --name "<pageName>" --file ./output/<projectDir>/<subfolder>/<readable-id>.html # Create page + enter streaming mode (.stream.lock written next to --file)
page create signals the local server to start streaming mode for this page, enabling real-time HTML preview as you write to the .html file. This command should be called BEFORE writing the HTML file, and the streaming mode is automatically ended when page save completes.
【CRITICAL - HTML 文件名必须等于 pageuuid】 --file 中的文件名部分必须与 --pageuuid 完全一致。例如 --pageuuid customers-list 必须搭配 --file .../customers-list.html。local-server 的 fileWatcher、streamPoller、pageCache 全部基于“文件名 = pageUuid”的假设工作。不一致会导致:lock 文件与 HTML 文件脱钩、前端流式状态异常、.meta.json 与远程 pageuuid 不匹配。page create 响应会在检测到不一致时发出 WARNING,务必按建议修正路径。
Page - Save (with validation)
gemdesign page save --pageuuid <id> --file ./output/<projectDir>/<subfolder>/<id>.html # Update existing
gemdesign page save --new --pageuuid <readable-id> --name "Login" --file ./output/<projectDir>/<subfolder>/<readable-id>.html # Create new
gemdesign page doc save --pageuuid <id> --file ./output/<projectDir>/<subfolder>/doc.md # Save requirement doc
page save automatically validates the HTML against the GemDesign Page Spec before uploading. After a successful save, it automatically ends streaming mode, triggering the browser to fetch the final render.
page doc save saves an agent-generated requirement document to the platform.
--pageuuid for --new: Use a human-readable id (e.g. filename without .html). Ensure uniqueness within the app. This id is used directly as data-uuid in navigation elements - no need to change them after saving.
Project subdirectory: Always use ./output/<projectDir>/ in paths. The CLI is idempotent - if the path already contains <projectDir>, it won't duplicate it. See "Local File Management" for details.
Folder organization: Include the folder path directly in --file (e.g. --file ./output/<projectDir>/crm/客户管理/page.html). The CLI automatically derives the remote dirName from the file path.
Validate Only
gemdesign validate --file ./output/<projectDir>/<subfolder>/page.html # Validate without saving
Local File Management
For every page, save HTML files locally under ./output/, organized by project subdirectory:
| File |
Purpose |
How to generate |
./output/<projectDir>/<subfolder>/<pageuuid>.html |
Page HTML (contains DSL, for editing and saving) |
Written by the agent only after page create has created the .stream.lock (direct creation without the lock is FORBIDDEN; can include multi-level folder path in <subfolder>) |
./output/<projectDir>/<subfolder>/<pageuuid>.meta.json |
Page position metadata (stores { position: { x, y } } for canvas layout) |
CLI-managed exclusively — auto-generated by page get; used by page save to read position. The agent MUST NEVER create or modify this file manually. Located in the same directory as the HTML file. |
.meta.json follows the HTML file's directory: The .meta.json file is always generated in the same directory as its corresponding .html file, regardless of folder depth. For example:
--file ./output/<projectDir>/page.html → meta.json at ./output/<projectDir>/page.meta.json
--file ./output/<projectDir>/crm/page.html → meta.json at ./output/<projectDir>/crm/page.meta.json
--file ./output/<projectDir>/crm/客户管理/page.html → meta.json at ./output/<projectDir>/crm/客户管理/page.meta.json
You MUST NOT manually create or modify .meta.json files — the CLI manages them exclusively (page get generates them, page save reads them). When page save is called, it reads the position from the .meta.json in the same directory as the HTML file (falling back to --x/--y flags if no meta.json exists).
Directory consistency check (automatic): Before page get or page save writes any files, the CLI automatically scans the project directory to check if a same-name .html file already exists in a DIFFERENT directory than where --file points to. If a mismatch is detected (e.g., HTML exists in customers/ but --file points to root), the CLI returns an error with a suggestedFilePath — you MUST use the suggested path to re-execute the command. This check runs BEFORE any file writes to prevent dirty data. If you receive this error, do NOT ignore it — re-run the command with the exact suggestedFilePath from the error response.
Project subdirectory naming: <projectDir> = {projectName}__{appuuid}
projectName comes from app info (illegal filesystem chars \/:*?"<>| removed, whitespace collapsed to _)
- Empty
projectName falls back to 默认项目; empty appuuid falls back to local
- Examples:
CRM系统__abc-123, 电商App__9f3e, 默认项目__local
- Directory creation: This subdirectory is sync-created by
app create under htmlWorkdir (requires htmlWorkdir configured first via server workdir); page get/page save also create it idempotently when writing files.
How to write files:
- Always use
./output/<projectDir>/<subfolder>/<pageuuid>.html in all file paths, whether writing files directly or passing to CLI commands. Include folder path in <subfolder> if needed (e.g. ./output/<projectDir>/crm/客户管理/page.html). HTML 文件名必须等于 pageuuid(如 --pageuuid customers-list → 文件名必须是 customers-list.html,不能用 list.html)。
- The CLI is idempotent: if the path already contains
<projectDir>, it will NOT duplicate it. You can safely pass ./output/CRM系统__abc-123/home.html to page get --file or page save --file without worrying about nesting.
- Compute
<projectDir> first: Run gemdesign app info -> get {appuuid} and {projectName} -> compute <projectDir> = {projectName}__{appuuid} (sanitize projectName).
- Validate
<projectDir> before creating files: Ensure <projectDir> is non-empty and matches {nonEmptyName}__{nonEmptyUuid}. If projectName or appuuid is empty/undefined, re-run gemdesign app info. Never create files with an empty or partial <projectDir> (e.g. __abc or MyApp__) - this creates orphaned unnamed directories.
The local server automatically serves pages from the project subdirectory path.
Page Folder Organization
Pages can be organized into sub-folders within the project directory. Simply include the folder path in --file:
- Root-level pages:
--file ./output/<projectDir>/page.html → placed in project root
- Sub-folder pages:
--file ./output/<projectDir>/crm/page.html → placed in crm sub-folder
- Multi-level folders:
--file ./output/<projectDir>/crm/客户管理/page.html → nested directory structure
# Single-level folder
gemdesign page create --pageuuid customer-list --name "客户列表" --file ./output/<projectDir>/crm/customer-list.html
gemdesign page save --new --pageuuid customer-list --name "客户列表" --file ./output/<projectDir>/crm/customer-list.html
# Multi-level folder
gemdesign page create --pageuuid customer-detail --name "客户详情" --file ./output/<projectDir>/crm/客户管理/customer-detail.html
gemdesign page save --new --pageuuid customer-detail --name "客户详情" --file ./output/<projectDir>/crm/客户管理/customer-detail.html
When to use folders: Use folders when the user describes organizing pages into modules/categories. For example, if the user says "put the customer pages under crm/客户", use --file ./output/<projectDir>/crm/客户/page.html.
Folder names: Illegal filesystem characters (\/:*?"<>|) are automatically cleaned. Folder names should be descriptive and human-readable.
Local server: The local server automatically recursively scans all sub-folders and displays them in a tree structure in the designer.
Remote sync: When page save is called, the CLI automatically derives the folder path from --file and sends it to the remote server as dirName. You do NOT need to specify any extra parameter — the CLI handles this transparently.
Streaming Write Workflow (Real-time Display)
When generating HTML pages, use the streaming write workflow to enable real-time display in the browser. The GemDesign local server watches for file changes and pushes incremental content to the browser via Server-Sent Events (SSE).
CRITICAL — Do NOT open the browser again during streaming write (or at any point after Step 3). The designer SPA (already open in the browser from Step 3) watches for .html file changes and auto-loads the generated HTML into its inner iframe via SSE. You do NOT need to "open" or "refresh" anything — just write the files and the designer updates itself in real time. Navigating the browser to the generated .html URL (e.g. via a preview tool or OS browser command with a page-specific URL) will OVERWRITE the designer with the generated HTML and break the preview surface. The only valid URL for opening the browser is the designer root http://localhost:<port>/, and even that should NOT be re-used after Step 3.
HARD GATE — 本地文件生成后必须调用 page save 命令:写入 HTML 文件后,必须调用 gemdesign page save 命令将页面保存到远程服务器。严禁只写入本地文件而跳过 page save——这会导致页面只存在于本地但不会出现在平台上,用户无法看到或使用该页面。完整流程为:page create → 写入 HTML → page save。page save 内置了规范验证,验证失败会返回错误,修复后重新执行 page save 即可。只写入本地文件而不调用 page save 是严重违规。
注意:page create 的 JSON 响应中包含 warning 和 requiredNextSteps 字段,明确列出后续必须执行的步骤。你在收到该响应后,必须按照 requiredNextSteps 中的步骤依次执行,不可在写入 HTML 后停止。
HARD GATE — 严禁直接创建 .html 和 .meta.json 文件:不允许智能体使用文件工具(Write/Edit 等)直接创建 .html 或 .meta.json 文件——这两类文件的创建必须由 CLI 命令驱动:
- 新建页面:必须先执行
gemdesign page create(它会在 --file 同目录创建 .stream.lock 并进入流式模式),之后才允许写入 HTML。没有 lock 就写入 HTML 文件是严重违规——local-server 无法进入流式模式,实时预览失效,兜底保存也无法识别该页面尚未保存。
- 修改已有页面:必须先执行
gemdesign page get 拉取 HTML(由 CLI 生成 .html 和 .meta.json),之后才允许修改。
.meta.json 为 CLI 专属文件:由 page get 自动生成、由 page save 读取,任何情况下智能体都严禁手动创建或修改 .meta.json 文件。
自检标准:在写入任何 .html 之前,必须先存在该页面的 .stream.lock(新建,由 page create 创建)或 page get 的输出(修改已有页面)。违反该顺序(先写文件、后补命令,或完全跳过命令)都是严重违规。
How It Works
The CLI automatically manages the streaming lifecycle for you. The gemdesign page create command starts streaming mode, and gemdesign page save automatically ends it. The browser receives incremental HTML as you append to the .html file:
gemdesign page create → browser enters streaming mode for that page
- Append to
.html → browser receives incremental HTML and re-renders in real-time
gemdesign page save → browser fetches the complete HTML and switches to final render
Steps
For each page you generate, follow this workflow. The workflow has 3 required steps — page create, write HTML, and page save. You MUST complete all 3 steps for every page. Stopping after writing HTML is a SERIOUS VIOLATION — the page will NOT appear on the platform.
Compute path:
htmlPath = ./output/<projectDir>/<subfolder>/<pageuuid>.html (include folder path in <subfolder>, or omit <subfolder> for root-level pages)
Create the page (enter streaming mode):
gemdesign page create --pageuuid <pageuuid> --name "<pageName>" --file ./output/<projectDir>/<subfolder>/<pageuuid>.html
This signals the local server to start streaming mode for this page. The .stream.lock is written next to --file, so the lock and HTML share the same directory. The browser will enter streaming mode and prepare to receive incremental HTML.
The response contains requiredNextSteps — you MUST follow them. After calling page create, you MUST write the HTML file and then call page save. Do NOT stop after writing HTML.
Write the HTML file (append-only after the first write, NEVER overwrite with shorter content):
- Precondition: step 2's
page create MUST have succeeded (the .stream.lock exists next to --file). NEVER create/write the HTML file without the lock — see the "严禁直接创建 .html 和 .meta.json 文件" HARD GATE above.
- You may write the HTML in one shot or in multiple appends — the local server detects file changes and pushes each append to the browser in real-time.
- The HTML must be a complete document:
<!DOCTYPE html> + <head> (with all dependencies and styles) + <body>...</body> + </html>.
- If writing in multiple appends, ensure the first write includes the
<body> tag so the browser can start rendering immediately (the browser only renders after <body> appears).
CRITICAL RULES:
- Always append to the file after the first write. Never overwrite with shorter content during streaming — this triggers a
pageReset event and forces the browser to re-render from scratch.
- If you must rewrite from scratch, delete the
.html file first, then start over.
- The first write creates the file (length goes from 0 to N), subsequent writes append (length goes from N to N+M).
- No delays or chunk-size limits: Write as fast as you like, in any size. The local server pushes every file change to the browser within ~10ms.
- Clean up on failure: If streaming write fails or is interrupted, delete any partial
.html file for that page. You can also run gemdesign server cleanup to clean up orphaned files and empty project directories.
(Optional) Validate the HTML — only if you want early error detection before saving:
gemdesign validate --file ./output/<projectDir>/<subfolder>/<pageuuid>.html
If validation fails, fix the HTML and re-validate. Note: page save also validates internally — if validation fails during save, fix the HTML and re-run page save.
Save to platform (MANDATORY — MUST call after writing HTML):
gemdesign page save --new --pageuuid <pageuuid> --name "<pageName>" --file ./output/<projectDir>/<subfolder>/<pageuuid>.html
page save automatically validates the HTML before saving — if validati
…(truncated)
1---2name: gemdesign-skill3description: Generate, save, and modify GemDesign prototype pages via CLI. Invoke when user wants to create UI prototypes, design pages, or batch-generate pages from requirements.4license: MIT5---67# GemDesign Prototyping89Use the `gemdesign` CLI to create, save, and modify high-fidelity prototype pages on the GemDesign platform. You generate HTML following the GemDesign Page Spec, validate it, then save via CLI.1011## When to Invoke1213- User wants to create a UI prototype or design a page14- User has a requirements document and wants batch page generation15- User wants to modify an existing GemDesign page16- User wants to view existing GemDesign pages1718## Prerequisites1920> **CRITICAL: Step 1, Step 2, and Step 2.5 MUST be executed strictly in order BEFORE starting any Workflow. Each step MUST fully complete before proceeding to the next. Do NOT skip, parallelize, or advance until the current step is confirmed successful.**21>22> **IMPORTANT — Step 3 timing**: Step 3 (Start the Local Server) is NOT executed immediately after login. It MUST be executed INSIDE a Workflow, AFTER the app is created or reused (i.e., after `gemdesign app create` / `gemdesign app use` + `gemdesign app info`), and BEFORE any page generation. Starting the server before the app exists is a violation — the server serves pages from the project subdirectory derived from the app, so the app must exist first.2324### Step 1: Verify & Install GemDesign CLI (MUST complete before Step 2)2526**ALWAYS verify CLI installation and version first** before doing any other work. This step is a hard gate — no other operations (`auth`, `app`, `page`, `style`, etc.) may run until this step is confirmed complete.27281. **Check if CLI is installed**:29 ```bash30 npm list -g @gemdesign-ai/cli31 ```32 - If the command returns version info (e.g., `@gemdesign-ai/cli@1.2.3`), CLI is installed - proceed to step 2.33 - If the command returns empty or error (e.g., `(empty)` or `ERR!`), CLI is NOT installed. Run:34 ```bash35 npm install -g @gemdesign-ai/cli36 ```37 Wait for the installation to finish, then re-verify with `npm list -g @gemdesign-ai/cli`. Do NOT proceed until re-verification confirms the installed version.38392. **Check if CLI is latest version** (only after step 1 confirms CLI is installed):40 ```bash41 npm outdated -g @gemdesign-ai/cli42 ```43 - If the command returns empty or shows `Current=Latest`, CLI is up-to-date - this step is complete, proceed to Step 2.44 - If the command shows version info with different `Current` and `Latest` values, CLI is outdated. Update to latest:45 ```bash46 npm update -g @gemdesign-ai/cli47 ```48 Wait for the update to finish, then re-verify with `npm outdated -g @gemdesign-ai/cli`. Do NOT proceed until re-verification confirms the CLI is up-to-date.4950After this step is confirmed complete, the `gemdesign-ai` command is available globally at the latest version. **Only then** may you advance to Step 2.5152### Step 2: Verify Login (MUST complete after Step 1, before any Workflow)5354**ALWAYS verify login status** after Step 1 is complete. Run this command:55```bash56gemdesign auth whoami57```58- If it succeeds (returns user info), the user is logged in — proceed to a Workflow (A/B/C). Step 3 (local server) will be executed INSIDE the workflow, after the app is created/reused.59- If it fails (returns an error like "GemDesign令牌 无效" or "未提供 GemDesign令牌"), the user is NOT authenticated. You MUST:60 1. Tell the user: if they don't have an account or GemDesign令牌 yet, go to **https://design.gemcoder.com** to register an account and get a GemDesign令牌. The GemDesign令牌 retrieval path is: log in to the platform -> click **个人中心** (Personal Center) -> get the **GemDesign令牌** (GemDesign令牌).61 2. Ask the user for their GemDesign令牌 (use `AskUserQuestion` tool to prompt the user to input their GemDesign令牌).62 3. Once the user provides their GemDesign令牌, **automatically run** the login command for them:63 ```bash64 gemdesign auth login --token <user_provided_token>65 ```66 4. Re-verify with `gemdesign auth whoami` to confirm login succeeded.67 5. If login still fails, repeat from step 2 (ask the user to provide their GemDesign令牌 again).68 6. Only proceed to a Workflow after login is confirmed.6970**HARD GATE**: Until login is confirmed via `gemdesign auth whoami`, you MUST NOT perform ANY page-generation work — this includes CLI commands (`app`, `page`, `style`, `validate`) AND local file operations (writing `.html`, streaming write, creating the `./output/` directory). Local HTML generation is NOT a workaround for the login gate; a page can only be saved to the platform by an authenticated user, so generating it before login is wasted work. If login fails, stop and resolve authentication first — do not start writing any HTML.7172### Step 2.5: Clean Up and Configure htmlWorkdir (MUST complete after Step 2, before any Workflow)7374After login is confirmed, FIRST clean up stale empty project directories left over from previous interrupted sessions, THEN configure the HTML working directory (`htmlWorkdir`). The order is MANDATORY: `cleanup` MUST run BEFORE `workdir --path`, never after. Both operations MUST complete before starting any Workflow (in particular, before `app create`).7576> **CRITICAL — Why cleanup MUST run BEFORE workdir (order is non-negotiable):** `gemdesign server workdir --path ./output` creates the `./output` directory — at this moment it is an empty workdir with NO project subdirectories (`{projectName}__{appuuid}`) yet, because `app create` has not run. `gemdesign server cleanup` runs `pruneEmptyWorkdirs()`, which deletes any workdir directory that contains zero project subdirectories AND removes it from the `htmlWorkdir` config. If you run `workdir` first and then `cleanup`, the freshly-created empty `./output` is treated as a stale empty workdir — `cleanup` deletes the directory and wipes it from config, leaving `htmlWorkdir` empty. Downstream effect: `app create` skips local folder creation (returns a `warning`), and `server start` refuses to start (`"未配置 htmlWorkdir..."`), causing "page generated but canvas not showing". Running `cleanup` FIRST avoids this: it clears stale state from previous sessions, then `workdir` creates `./output` LAST so it survives. (Note: `cleanup` does NOT require `htmlWorkdir` to be pre-configured — when unconfigured it simply returns `"未配置 htmlWorkdir,无需清理"` and exits cleanly.)77781. **Clean up empty project directories** (MUST run FIRST, before configuring htmlWorkdir):79 ```bash80 gemdesign server cleanup81 ```82 - If `htmlWorkdir` is not configured yet, the command returns `{"success":true,"message":"未配置 htmlWorkdir,无需清理","removedDirs":[],"removedLocks":[],"removedWorkdirs":[],"removedWorkdirDirs":[]}` — this is normal, continue to step 2.83 - If `htmlWorkdir` is already configured from a previous session, the command scans each configured workdir for project subdirectories (named `{projectName}__{appuuid}`) and:84 - Deletes **empty project directories**: project subdirectories that contain zero `.html` files (created by `app create` but never had a page saved — e.g., the session was interrupted).85 - Cleans **orphaned streaming files**: `.stream.lock` files left over from streaming write that was started but never completed.86 - Removes **empty workdirs**: workdir directories that contain zero project subdirectories are deleted and removed from config (this is exactly why `workdir --path` MUST run AFTER `cleanup`, not before).87 - Returns JSON: `{"success":true,"message":"清理完成:删除 N 个空项目目录,清理 M 个遗留文件,移除 K 个无项目的 htmlWorkdir","removedDirs":[...],"removedLocks":[...],"removedWorkdirs":[...],"removedWorkdirDirs":[...]}`88 - **This step is non-blocking**: cleanup failures do not prevent proceeding to a Workflow. The command always returns `success: true` unless an unexpected error occurs.89902. **Configure htmlWorkdir** (MUST run AFTER step 1; run once, persists across sessions):91 > **CRITICAL - `app create` sync-creates the local project folder under `htmlWorkdir`, and `server start` validates `htmlWorkdir` before launching.** If `htmlWorkdir` is not configured, `app create` skips local folder creation (returns a `warning`), and `server start` returns `{"success":false,"error":"未配置 htmlWorkdir,请先执行 gemdesign server workdir --path <path> 设置 HTML 工作目录"}` and refuses to start. This prevents the background process's cwd from mismatching the actual HTML generation directory, which would cause fileWatcher to miss `.html` changes and the canvas to stay blank ("page generated but canvas not showing").9293 ```bash94 gemdesign server workdir --path ./output95 ```96 - Relative paths are resolved against the current working directory to an absolute path.97 - Verify with `gemdesign server workdir` (no flags) - returns `{"success":true,"htmlWorkdir":["<absolute path>"]}`.98 - The `./output` directory created here will NOT be deleted by `cleanup` within this same Step 2.5, because `cleanup` already ran in step 1. Do NOT re-run `cleanup` after this step — re-running it would delete the freshly-created empty `./output` (since `app create` has not run yet and there are no project subdirectories).99100### Step 3: Start the Local Server (MUST complete after app is created/reused, before any page generation)101102> **CRITICAL - HARD GATE: You MUST open the browser in this step.** This is NON-NEGOTIABLE and MUST NOT be skipped, deferred, or treated as optional. Generating any page before the browser is open is a SERIOUS VIOLATION - the user needs the real-time preview surface to see pages as they are generated. You MUST actively open the browser yourself using your platform's built-in browser/preview tool (see step 3 below for the fallback strategy). Do NOT just output a URL in chat text and wait for the user to click it — you MUST programmatically open the browser.103104> **TIMING — Execute INSIDE a Workflow, NOT immediately after login.** Step 3 is invoked from within Workflow A/B/C (see each workflow's "Start the local server" step), AFTER the app has been created or reused via `gemdesign app create` / `gemdesign app use` and confirmed via `gemdesign app info`. Do NOT start the server right after Step 2 (login) — the server serves pages from the project subdirectory derived from the app (`<projectDir> = {projectName}__{appuuid}`), so the app must exist first. Starting the server before the app exists is a violation.105106After Step 1 (CLI installed), Step 2 (Login verified), AND the app is created/reused (inside a Workflow) are all confirmed complete, start the local server for real-time streaming preview.107108The local server provides real-time streaming preview of HTML pages as they are being generated. The server is built into the CLI and managed via the `gemdesign server` commands. The server runs on port `4056` by default; if that port is occupied it auto-retries the next available port (up to `4066`).1091100. **Ensure htmlWorkdir is configured** (MUST complete before `app create` in a Workflow, and before `server start`):111 > htmlWorkdir is configured in Step 2.5 (persists across sessions). `app create` sync-creates the local project folder under `htmlWorkdir`, and `server start` validates `htmlWorkdir` before launching — if it is not configured, `app create` skips local folder creation (returns a `warning`) and `server start` refuses to start, causing fileWatcher to miss `.html` changes and the canvas to stay blank ("page generated but canvas not showing").112 >113 > If Step 2.5 was skipped (e.g. resuming a session), verify now: `gemdesign server workdir` (no flags) returns `{"success":true,"htmlWorkdir":"<absolute path>"}`. If it returns an empty `htmlWorkdir`, run `gemdesign server workdir --path ./output` before proceeding.1141151. **Stop any previously running server** (MANDATORY before every `server start`, CANNOT be skipped):116 > **CRITICAL — 执行 `server start` 之前必须先执行 `server stop` 终止之前启动的服务**,无论应用是新建还是复用都不可跳过。这确保 fileWatcher 绑定到正确的项目目录,避免残留进程干扰新会话。117 >118 > **HARD GATE - 严禁跳过此步**:无论你认为当前是否已有服务在运行,都必须执行 `gemdesign server stop` 命令。禁止以"服务器未运行"、"上一次会话已启动"、"浏览器预览已打开"、"为了节省时间"等任何理由跳过 stop。必须以 `gemdesign server stop` 的实际返回结果作为唯一判定依据。119 >120 > ```bash121 > gemdesign server stop122 > ```123 - 返回 `{"success":true,"message":"本地服务已停止"}` 表示已停止,继续下一步。124 - 返回 `{"success":false,"error":"未发现运行中的本地服务"}` 表示无运行中的服务,忽略此错误继续下一步。125 - **必须等待上述命令返回结果后才能进入第 2 步**。在 stop 命令未返回前,不得执行任何 `server start` 操作。1261272. **Start the local server** using the CLI command:128 ```bash129 gemdesign server start130 ```131 > **必须在执行此命令前先完成上一步的 `gemdesign server stop`**,不得在未停止旧服务的情况下直接 start。132 >133 > **HARD GATE - 顺序约束**:`server start` 必须在 `server stop` 命令返回结果(成功或"未发现运行中的本地服务"错误)之后才能执行。严禁以下行为:134 > - 将 `server stop` 与 `server start` 并行执行(例如在同一个并行工具调用批次中);135 > - 在 `server stop` 命令尚未返回结果时就发起 `server start`;136 > - 先执行 `server start` 再执行 `server stop`;137 > - 因为"觉得没必要 stop"而跳过 stop 直接 start。138 >139 > 正确顺序:执行 `gemdesign server stop` -> 等待命令返回结果 -> 执行 `gemdesign server start`。这是不可逆的串行依赖关系。140 - If the server starts successfully, the command returns JSON: `{"success":true,"port":<port>,"url":"http://localhost:<port>"}`141 - If the server fails to start, the command returns JSON with an error: `{"success":false,"error":"<error message>"}`142 - **On error**: Read the error message carefully. Common errors:143 - `"服务文件不存在"`: The CLI installation is incomplete — reinstall the CLI.144 - `"服务启动失败,进程已退出"`: Possible port conflict or config file error — check `~/.gemdesign/config.json`.145 - Record the `<port>` from the success response for subsequent steps.1461473. **Check server status** (optional, for debugging):148 ```bash149 gemdesign server status150 ```151 Returns: `{"success":true,"status":"running","port":<port>,"url":"http://localhost:<port>"}` or `{"success":true,"status":"stopped"}`1521534. **Open the preview (MANDATORY — HARD GATE, DO NOT SKIP)**: After the server is confirmed running (the `server start` command returned success), you MUST open the browser and navigate to the service page named **GemDesign设计器** (URL: `http://localhost:<port>` - use the port from the `server start` response).154155 > **This step is NON-NEGOTIABLE.** Do NOT proceed to any page generation workflow (Workflow A/B/C) until the browser is open at `http://localhost:<port>`. The server being up is NOT the same as the preview being open - the user must SEE the preview surface in the browser.156 >157 > **DO NOT just output a URL in chat text.** You MUST use a tool to actually open the browser. Outputting something like "服务器启动成功!请在浏览器中打开 http://localhost:4056" is a VIOLATION — the browser must be opened programmatically, not by asking the user to click a link.158159 **How to open the browser — use the following methods in priority order:**160161 Try the following methods in priority order. Use the FIRST one that is available and succeeds. If a method fails, skip it and try the next:162163 | Priority | Method | How to use |164 |----------|--------|------------|165 | 1 | **Your platform's built-in browser/preview tool** | **You MUST check what browser/preview tools are available on your current agent platform and use the most appropriate one.** Different platforms provide different built-in tools — use whichever one your platform offers. Examples of platform-specific tools: Trae provides `OpenPreview` and the `integrated_browser` MCP's `browser_navigate`; Cursor provides its own preview mechanism; other platforms may have equivalent tools. **The key requirement is: you MUST use a tool to programmatically open the browser, not just output a URL in chat.** Navigate to `http://localhost:<port>/` using the tool. |166 | 2 | **OS default browser command** | If no built-in browser/preview tool is available (or it failed), open the default browser via OS command: Windows `start http://localhost:<port>/`, macOS `open http://localhost:<port>/`, Linux `xdg-open http://localhost:<port>/`. |167 | 3 | **Tell the user to open the URL** | If ALL above methods fail or are unavailable, as a **last resort**, clearly tell the user: "请在浏览器中打开 http://localhost:<port>/ 查看设计器预览" and wait for the user to confirm before proceeding. |168169 **How to find your platform's built-in tool:** Check your available tools list — look for tools with names like `OpenPreview`, `browser_navigate`, `preview`, `browser`, or similar. Any tool that can open a URL in a browser panel qualifies. Use it with the URL `http://localhost:<port>/`.170171 **Ensuring success:**172 - If the highest-priority method returned an error or you're unsure whether it succeeded, immediately fall back to the next method in the table.173 - After opening the browser, verify the server is still accessible by re-checking the debug endpoint (`http://localhost:<port>/api/local/stream/debug` returns 200).174 - Only proceed to page generation after you have made a best-effort attempt to open the browser using at least one available method.175 >176 > After the preview is open, you may proceed to page generation workflows.177178 > **CRITICAL - The browser is opened EXACTLY ONCE, only here in Step 3.** Once the browser is open at `http://localhost:<port>` (the designer SPA root), you MUST NEVER open the browser again — not during page generation (Workflows A/B/C), not during modification flows, not to "refresh" or "show" a generated page. The designer SPA stays open for the entire session; generated HTML is loaded into an iframe INSIDE the designer via SSE (see "Streaming Write Workflow"), NOT by navigating the browser to a new URL.179 >180 > Opening the browser again will navigate it away from the designer to whatever URL you passed — this OVERWRITES the designer with the generated HTML (or a 404), destroying the preview surface the user needs. The URL used to open the browser MUST ALWAYS be the designer root URL `http://localhost:<port>/` — NEVER a path to a generated `.html` file (e.g. `http://localhost:<port>/output/<projectDir>/<pageuuid>.html`), NEVER a page-specific URL. Generated pages have no direct browser URL; they are only viewable through the designer's iframe via SSE.181182## CLI Command Reference183184### Server Management185```bash186gemdesign server start [--port <port>] # 启动本地设计器服务(默认端口 4056)187gemdesign server stop # 停止本地设计器服务188gemdesign server status # 查看服务运行状态189gemdesign server workdir --path <path> # 保存 HTML 工作目录(htmlWorkdir,相对路径基于当前目录解析为绝对路径)190gemdesign server workdir # 查看当前 htmlWorkdir191gemdesign server workdir --clear # 清除 htmlWorkdir 配置192gemdesign server cleanup # 清理空项目目录和遗留的流式文件193```194> **server workdir** 保存 HTML 工作目录到 `~/.gemdesign/config.json` 的 `htmlWorkdir` 字段。本地服务启动后通过 fileWatcher 监听此目录下的 `.html` 文件变更,并经 SSE 推送到浏览器画布。**`app create` 会在此目录下同步创建项目子目录 `{projectName}__{appuuid}`**,**`server start` 也会在启动前校验 htmlWorkdir 是否已配置**--未配置时 `app create` 跳过本地目录创建(返回 `warning`),`server start` 拒绝启动并返回错误提示,避免后台进程 cwd 与实际 HTML 生成目录不一致导致"页面生成但画布不显示"。建议在登录后、**`app create` 之前**执行一次 `gemdesign server workdir --path ./output`(路径通常是 `./output`,即页面 HTML 的根目录)。配置一次后持久化,后续无需重复设置。195> **server start** 以后台进程方式启动本地服务。**执行 `server start` 之前必须先执行 `server stop` 终止之前的服务**,不得在未停止旧服务的情况下直接 start。**`server stop` 严禁跳过**(即使你认为没有运行中的服务也必须执行该命令),且 **`server start` 必须等 `server stop` 命令返回结果后才能执行**——禁止将两者并行执行、或在 stop 未返回时就发起 start。启动成功返回含 `port` 和 `url` 的 JSON;失败返回含 `error` 的 JSON,需仔细阅读错误信息诊断并修复后再重试(重试前同样要先 stop)。196> **server stop** stops the running server. On Windows, uses `taskkill` to terminate the process tree. Returns error if no server is running or if the process cannot be terminated — 此时该错误可忽略(表示本就无运行中的服务),但仍视为 stop 步骤已执行完成,可继续 start。197> **server status** returns the current status (`running` or `stopped`), port, and URL if running.198199### Authentication200```bash201gemdesign auth login --token <token> # 配置 GemDesign 令牌202gemdesign auth whoami # Verify identity203```204205### App Management206```bash207gemdesign app create --name "MyApp" --workdir <path> [--type web|app] [--width <px>] [--height <px>] # Create new app (sync-creates local project folder under --workdir), --type defaults to web208gemdesign app list # List all apps209gemdesign app info [--appuuid <id>] # App details210gemdesign app use --appuuid <id> --workdir <path> # Switch current default app (creates/locates local project folder under --workdir)211```212> **app create 画布尺寸**: `--width`/`--height` 用于指定画布像素尺寸。不传时按 `--type` 取默认值:`web` -> 1920×1080,`app` -> 440×956。传入的尺寸会随应用信息同步到本地设计器画布(覆盖默认值)。示例:`gemdesign app create --name "PadApp" --type app --width 768 --height 1024`。213> **CRITICAL - `app create` and `app use` require `--workdir`**: `app create` 和 `app use` 的 `--workdir <path>` 是**必填**参数,指定本地项目子目录 `{projectName}__{appuuid}` 的父目录。路径由 agent 显式给出,CLI 不再通过配置自动猜测。`--workdir` 会自动追加到 `htmlWorkdir` 配置数组(去重),local-server 据此扫描所有项目目录。建议传入 `./output`(即 `gemdesign server workdir --path ./output` 配置的同一目录)。`page create` 的 `--file <path>` 同理:lock 文件直接写入 `--file` 推导出的项目子目录,保证 lock 与 html 同目录。214> **appuuid priority**: `--appuuid` flag > `defaultAppUuid` (set by `app create`/`app use`) > `GEMDESIGN_APPUUID` env215> Once you run `app create` or `app use`, subsequent `page` commands don't need `--appuuid`.216> **IMPORTANT**: Always check `gemdesign app list` BEFORE creating a new app. Reuse existing apps to keep all pages in the same project folder. Only create a new app when the user explicitly asks for one.217> **CRITICAL - Never create duplicate apps**: Never call `gemdesign app create` more than once in a single session/task. If you have already run `app create` in this session, you MUST NOT run it again — even if a later workflow step or retry seems to require app setup. Instead, reuse the existing app by running `gemdesign app list` to find it, then `gemdesign app use --appuuid <id> --workdir ./output`. Creating a second app leaves the first one empty and orphaned on the platform.218> **CRITICAL - Session lock error handling**: The CLI now automatically verifies session locks via appuuid. If `app create` returns `stage: "appCreateSession"` (session lock exists and the app still exists on remote), do NOT retry with `--force`. Instead: (1) Run `gemdesign app use --appuuid <existingApp.appuuid> --workdir ./output` to reuse the app. (2) If the existing app is from a different completed task, run `gemdesign app end-session`, then `app create` (without `--force`). (3) Only use `--force` if you have verified via `app list` that the session-lock app was deleted from the remote — note that the CLI now auto-cleans stale session locks (app deleted from remote), so `--force` should rarely be needed. (4) If `app create` returns `stage: "appCreateSessionVerify"` (unable to verify app existence due to network error), wait and retry — do NOT use `--force`.219> **CRITICAL - Restart the server around every `app create` or `app use`**: 正确顺序为:`gemdesign server stop` -> (等待 stop 命令返回结果) -> (确保 `htmlWorkdir` 已配置) -> `gemdesign app create` / `gemdesign app use` -> `gemdesign server start`。该顺序由 workflow 步骤强制执行,不要作为独立序列重复执行。**执行 `server start` 之前必须先执行 `server stop` 终止之前的服务**,无论应用是新建还是复用,否则旧服务的 fileWatcher 仍绑定在前一个 app 的 `<projectDir>`,新页面不会推送到画布。**`server stop` 这一步严禁跳过**(即使你认为没有运行中的服务也必须执行),且 **`server start` 必须等 `server stop` 命令返回结果后才能执行**,禁止并行执行或先 start 后 stop。220> **IMPORTANT - Output app info to user**: After selecting/switching/creating an app (i.e., after any `app create`, `app use`, or `app info` call that establishes the working app), you MUST clearly tell the user in your text response which app is now the active target for page generation. At minimum, output the **app name** and **appuuid** (and ideally the computed `<projectDir>`). This ensures the user always knows which app pages will be generated/modified in, and can interrupt if the wrong app was picked. See the "Output current app info to user" step in each workflow for the exact format.221> **CRITICAL - App type determines page type**: Apps have a type - `web` (桌面端) or `app` (移动端) - returned by `app info` as the `pageScene` field. **When generating new pages, the page type MUST match the app type**: a `web` app can only contain `web` pages (desktop layout, wide screen), and an `app` app can only contain `app` pages (mobile layout, narrow screen). Before generating any HTML, check the app's `pageScene` from `app info` and design the page accordingly. Do NOT generate a desktop-width page for an `app` type app, or a mobile-width page for a `web` type app.222223### Style Search (optional helper)224```bash225gemdesign style search --keywords "科技,深蓝,企业" --limit 5 # Search styles226gemdesign style get --id <styleId> --format html # Get full style227```228> Style search is optional. You can also design styles yourself or use other UI design skills.229230### Page - View231```bash232gemdesign page list [--appuuid <id>] # List pages233gemdesign page get --pageuuid <id> --file ./output/<projectDir>/<subfolder>/<id>.html # Get page HTML (auto-creates projectDir)234gemdesign page doc get --pageuuid <id> --file ./output/<projectDir>/<subfolder>/<id>.md # Get requirement doc235```236237> **CRITICAL - 同步远程页面时必须保留文件夹结构**:`page list` 返回的每个页面包含 `dirName` 字段(远程所在文件夹,多级用 / 分隔,根级页面为 null/空)。将远程页面同步到本地(尤其是"同步后编辑"场景)时,`page get --file` 的 `<subfolder>` **必须与该页面的 `dirName` 一致**,即落盘到 `./output/<projectDir>/<dirName>/<pageuuid>.html`。严禁将所有页面统一放到项目根目录——否则后续编辑保存时本地推导的目录与远程不一致,可能导致页面脱离远程文件夹。例:`page list` 返回页面 `report-sales` 的 `dirName` 为 `reports`,则必须执行 `gemdesign page get --pageuuid report-sales --file ./output/<projectDir>/reports/report-sales.html`。238239### Page - Create (streaming mode)240```bash241gemdesign page create --pageuuid <readable-id> --name "<pageName>" --file ./output/<projectDir>/<subfolder>/<readable-id>.html # Create page + enter streaming mode (.stream.lock written next to --file)242```243> `page create` signals the local server to start streaming mode for this page, enabling real-time HTML preview as you write to the `.html` file. This command should be called BEFORE writing the HTML file, and the streaming mode is automatically ended when `page save` completes.244>245> **【CRITICAL - HTML 文件名必须等于 pageuuid】** `--file` 中的文件名部分必须与 `--pageuuid` 完全一致。例如 `--pageuuid customers-list` 必须搭配 `--file .../customers-list.html`。local-server 的 fileWatcher、streamPoller、pageCache 全部基于“文件名 = pageUuid”的假设工作。不一致会导致:lock 文件与 HTML 文件脱钩、前端流式状态异常、.meta.json 与远程 pageuuid 不匹配。`page create` 响应会在检测到不一致时发出 WARNING,务必按建议修正路径。246247### Page - Save (with validation)248```bash249gemdesign page save --pageuuid <id> --file ./output/<projectDir>/<subfolder>/<id>.html # Update existing250gemdesign page save --new --pageuuid <readable-id> --name "Login" --file ./output/<projectDir>/<subfolder>/<readable-id>.html # Create new251gemdesign page doc save --pageuuid <id> --file ./output/<projectDir>/<subfolder>/doc.md # Save requirement doc252```253> `page save` automatically validates the HTML against the GemDesign Page Spec before uploading. After a successful save, it automatically ends streaming mode, triggering the browser to fetch the final render.254> `page doc save` saves an agent-generated requirement document to the platform.255> **`--pageuuid` for `--new`**: Use a human-readable id (e.g. filename without `.html`). Ensure uniqueness within the app. This id is used directly as `data-uuid` in navigation elements - no need to change them after saving.256> **Project subdirectory**: Always use `./output/<projectDir>/` in paths. The CLI is idempotent - if the path already contains `<projectDir>`, it won't duplicate it. See "Local File Management" for details.257> **Folder organization**: Include the folder path directly in `--file` (e.g. `--file ./output/<projectDir>/crm/客户管理/page.html`). The CLI automatically derives the remote `dirName` from the file path.258259### Validate Only260```bash261gemdesign validate --file ./output/<projectDir>/<subfolder>/page.html # Validate without saving262```263264### Local File Management265266For every page, save HTML files locally under `./output/`, organized by project subdirectory:267268| File | Purpose | How to generate |269|------|---------|-----------------|270| `./output/<projectDir>/<subfolder>/<pageuuid>.html` | **Page HTML** (contains DSL, for editing and saving) | Written by the agent **only after `page create` has created the `.stream.lock`** (direct creation without the lock is FORBIDDEN; can include multi-level folder path in `<subfolder>`) |271| `./output/<projectDir>/<subfolder>/<pageuuid>.meta.json` | **Page position metadata** (stores `{ position: { x, y } }` for canvas layout) | **CLI-managed exclusively** — auto-generated by `page get`; used by `page save` to read position. The agent MUST NEVER create or modify this file manually. Located in the **same directory** as the HTML file. |272273> **`.meta.json` follows the HTML file's directory**: The `.meta.json` file is always generated in the same directory as its corresponding `.html` file, regardless of folder depth. For example:274> - `--file ./output/<projectDir>/page.html` → meta.json at `./output/<projectDir>/page.meta.json`275> - `--file ./output/<projectDir>/crm/page.html` → meta.json at `./output/<projectDir>/crm/page.meta.json`276> - `--file ./output/<projectDir>/crm/客户管理/page.html` → meta.json at `./output/<projectDir>/crm/客户管理/page.meta.json`277>278> You MUST NOT manually create or modify `.meta.json` files — the CLI manages them exclusively (`page get` generates them, `page save` reads them). When `page save` is called, it reads the position from the `.meta.json` in the same directory as the HTML file (falling back to `--x`/`--y` flags if no meta.json exists).279280> **Directory consistency check (automatic)**: Before `page get` or `page save` writes any files, the CLI automatically scans the project directory to check if a same-name `.html` file already exists in a DIFFERENT directory than where `--file` points to. If a mismatch is detected (e.g., HTML exists in `customers/` but `--file` points to root), the CLI returns an error with a `suggestedFilePath` — **you MUST use the suggested path to re-execute the command**. This check runs BEFORE any file writes to prevent dirty data. If you receive this error, do NOT ignore it — re-run the command with the exact `suggestedFilePath` from the error response.281282> **Project subdirectory naming**: `<projectDir> = {projectName}__{appuuid}`283> - `projectName` comes from `app info` (illegal filesystem chars `\/:*?"<>|` removed, whitespace collapsed to `_`)284> - Empty `projectName` falls back to `默认项目`; empty `appuuid` falls back to `local`285> - Examples: `CRM系统__abc-123`, `电商App__9f3e`, `默认项目__local`286> - **Directory creation**: This subdirectory is sync-created by `app create` under `htmlWorkdir` (requires `htmlWorkdir` configured first via `server workdir`); `page get`/`page save` also create it idempotently when writing files.287>288> **How to write files**:289> - **Always use `./output/<projectDir>/<subfolder>/<pageuuid>.html`** in all file paths, whether writing files directly or passing to CLI commands. Include folder path in `<subfolder>` if needed (e.g. `./output/<projectDir>/crm/客户管理/page.html`). **HTML 文件名必须等于 pageuuid**(如 `--pageuuid customers-list` → 文件名必须是 `customers-list.html`,不能用 `list.html`)。290> - The CLI is **idempotent**: if the path already contains `<projectDir>`, it will NOT duplicate it. You can safely pass `./output/CRM系统__abc-123/home.html` to `page get --file` or `page save --file` without worrying about nesting.291> - **Compute `<projectDir>` first**: Run `gemdesign app info` -> get `{appuuid}` and `{projectName}` -> compute `<projectDir> = {projectName}__{appuuid}` (sanitize projectName).292> - **Validate `<projectDir>` before creating files**: Ensure `<projectDir>` is non-empty and matches `{nonEmptyName}__{nonEmptyUuid}`. If `projectName` or `appuuid` is empty/undefined, re-run `gemdesign app info`. Never create files with an empty or partial `<projectDir>` (e.g. `__abc` or `MyApp__`) - this creates orphaned unnamed directories.293>294> The local server automatically serves pages from the project subdirectory path.295296### Page Folder Organization297298Pages can be organized into sub-folders within the project directory. Simply include the folder path in `--file`:299300- **Root-level pages**: `--file ./output/<projectDir>/page.html` → placed in project root301- **Sub-folder pages**: `--file ./output/<projectDir>/crm/page.html` → placed in `crm` sub-folder302- **Multi-level folders**: `--file ./output/<projectDir>/crm/客户管理/page.html` → nested directory structure303304```bash305# Single-level folder306gemdesign page create --pageuuid customer-list --name "客户列表" --file ./output/<projectDir>/crm/customer-list.html307gemdesign page save --new --pageuuid customer-list --name "客户列表" --file ./output/<projectDir>/crm/customer-list.html308309# Multi-level folder310gemdesign page create --pageuuid customer-detail --name "客户详情" --file ./output/<projectDir>/crm/客户管理/customer-detail.html311gemdesign page save --new --pageuuid customer-detail --name "客户详情" --file ./output/<projectDir>/crm/客户管理/customer-detail.html312```313314> **When to use folders**: Use folders when the user describes organizing pages into modules/categories. For example, if the user says "put the customer pages under crm/客户", use `--file ./output/<projectDir>/crm/客户/page.html`.315> **Folder names**: Illegal filesystem characters (`\/:*?"<>|`) are automatically cleaned. Folder names should be descriptive and human-readable.316> **Local server**: The local server automatically recursively scans all sub-folders and displays them in a tree structure in the designer.317> **Remote sync**: When `page save` is called, the CLI automatically derives the folder path from `--file` and sends it to the remote server as `dirName`. You do NOT need to specify any extra parameter — the CLI handles this transparently.318319## Streaming Write Workflow (Real-time Display)320321When generating HTML pages, use the **streaming write workflow** to enable real-time display in the browser. The GemDesign local server watches for file changes and pushes incremental content to the browser via Server-Sent Events (SSE).322323> **CRITICAL — Do NOT open the browser again during streaming write (or at any point after Step 3).** The designer SPA (already open in the browser from Step 3) watches for `.html` file changes and auto-loads the generated HTML into its inner iframe via SSE. You do NOT need to "open" or "refresh" anything — just write the files and the designer updates itself in real time. Navigating the browser to the generated `.html` URL (e.g. via a preview tool or OS browser command with a page-specific URL) will OVERWRITE the designer with the generated HTML and break the preview surface. The only valid URL for opening the browser is the designer root `http://localhost:<port>/`, and even that should NOT be re-used after Step 3.324325> **HARD GATE — 本地文件生成后必须调用 `page save` 命令**:写入 HTML 文件后,**必须**调用 `gemdesign page save` 命令将页面保存到远程服务器。**严禁**只写入本地文件而跳过 `page save`——这会导致页面只存在于本地但不会出现在平台上,用户无法看到或使用该页面。完整流程为:`page create` → 写入 HTML → `page save`。`page save` 内置了规范验证,验证失败会返回错误,修复后重新执行 `page save` 即可。只写入本地文件而不调用 `page save` 是严重违规。326327> **注意:`page create` 的 JSON 响应中包含 `warning` 和 `requiredNextSteps` 字段,明确列出后续必须执行的步骤。你在收到该响应后,必须按照 `requiredNextSteps` 中的步骤依次执行,不可在写入 HTML 后停止。**328329> **HARD GATE — 严禁直接创建 `.html` 和 `.meta.json` 文件**:不允许智能体使用文件工具(Write/Edit 等)直接创建 `.html` 或 `.meta.json` 文件——这两类文件的创建**必须由 CLI 命令驱动**:330> - **新建页面**:必须先执行 `gemdesign page create`(它会在 `--file` 同目录创建 `.stream.lock` 并进入流式模式),之后才允许写入 HTML。**没有 lock 就写入 HTML 文件是严重违规**——local-server 无法进入流式模式,实时预览失效,兜底保存也无法识别该页面尚未保存。331> - **修改已有页面**:必须先执行 `gemdesign page get` 拉取 HTML(由 CLI 生成 `.html` 和 `.meta.json`),之后才允许修改。332> - **`.meta.json` 为 CLI 专属文件**:由 `page get` 自动生成、由 `page save` 读取,**任何情况下智能体都严禁手动创建或修改 `.meta.json` 文件**。333>334> **自检标准**:在写入任何 `.html` 之前,必须先存在该页面的 `.stream.lock`(新建,由 `page create` 创建)或 `page get` 的输出(修改已有页面)。违反该顺序(先写文件、后补命令,或完全跳过命令)都是严重违规。335336### How It Works337338The CLI automatically manages the streaming lifecycle for you. The `gemdesign page create` command starts streaming mode, and `gemdesign page save` automatically ends it. The browser receives incremental HTML as you append to the `.html` file:3393401. **`gemdesign page create`** → browser enters streaming mode for that page3412. **Append to `.html`** → browser receives incremental HTML and re-renders in real-time3423. **`gemdesign page save`** → browser fetches the complete HTML and switches to final render343344### Steps345346For each page you generate, follow this workflow. The workflow has **3 required steps** — `page create`, write HTML, and `page save`. You MUST complete all 3 steps for every page. **Stopping after writing HTML is a SERIOUS VIOLATION — the page will NOT appear on the platform.**3473481. **Compute path**:349 - `htmlPath = ./output/<projectDir>/<subfolder>/<pageuuid>.html` (include folder path in `<subfolder>`, or omit `<subfolder>` for root-level pages)3503512. **Create the page (enter streaming mode)**:352 ```bash353 gemdesign page create --pageuuid <pageuuid> --name "<pageName>" --file ./output/<projectDir>/<subfolder>/<pageuuid>.html354 ```355 This signals the local server to start streaming mode for this page. The `.stream.lock` is written next to `--file`, so the lock and HTML share the same directory. The browser will enter streaming mode and prepare to receive incremental HTML.356 > **The response contains `requiredNextSteps` — you MUST follow them.** After calling `page create`, you MUST write the HTML file and then call `page save`. Do NOT stop after writing HTML.3573583. **Write the HTML file** (append-only after the first write, NEVER overwrite with shorter content):359 - **Precondition**: step 2's `page create` MUST have succeeded (the `.stream.lock` exists next to `--file`). NEVER create/write the HTML file without the lock — see the "严禁直接创建 `.html` 和 `.meta.json` 文件" HARD GATE above.360 - You may write the HTML in one shot or in multiple appends — the local server detects file changes and pushes each append to the browser in real-time.361 - The HTML must be a complete document: `<!DOCTYPE html>` + `<head>` (with all dependencies and styles) + `<body>...</body>` + `</html>`.362 - If writing in multiple appends, ensure the first write includes the `<body>` tag so the browser can start rendering immediately (the browser only renders after `<body>` appears).363364 > **CRITICAL RULES**:365 > - Always **append** to the file after the first write. Never overwrite with shorter content during streaming — this triggers a `pageReset` event and forces the browser to re-render from scratch.366 > - If you must rewrite from scratch, delete the `.html` file first, then start over.367 > - The first write creates the file (length goes from 0 to N), subsequent writes append (length goes from N to N+M).368 > - **No delays or chunk-size limits**: Write as fast as you like, in any size. The local server pushes every file change to the browser within ~10ms.369 > - **Clean up on failure**: If streaming write fails or is interrupted, delete any partial `.html` file for that page. You can also run `gemdesign server cleanup` to clean up orphaned files and empty project directories.3703714. **(Optional) Validate the HTML** — only if you want early error detection before saving:372 ```bash373 gemdesign validate --file ./output/<projectDir>/<subfolder>/<pageuuid>.html374 ```375 If validation fails, fix the HTML and re-validate. Note: `page save` also validates internally — if validation fails during save, fix the HTML and re-run `page save`.3763775. **Save to platform (MANDATORY — MUST call after writing HTML)**:378 ```bash379 gemdesign page save --new --pageuuid <pageuuid> --name "<pageName>" --file ./output/<projectDir>/<subfolder>/<pageuuid>.html380 ```381 `page save` **automatically validates the HTML before saving** — if validati382383…(truncated)