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: The following steps MUST be executed strictly in order. Each step MUST fully complete before proceeding to the next. Do NOT skip, parallelize, or advance until the current step is confirmed successful.
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- If the command returns version info (e.g.,
@gemdesign-ai/cli@1.2.3), CLI is installed - proceed to step 2. - If the command returns empty or error (e.g.,
(empty)orERR!), CLI is NOT installed. Run:
Wait for the installation to finish, then re-verify withnpm install -g @gemdesign-ai/clinpm list -g @gemdesign-ai/cli. Do NOT proceed until re-verification confirms the installed version.
- If the command returns version info (e.g.,
Check if CLI is latest version (only after step 1 confirms CLI is installed):
npm outdated -g @gemdesign-ai/cli- If the command returns empty or shows
Current=Latest, CLI is up-to-date - this step is complete, proceed to Step 2. - If the command shows version info with different
CurrentandLatestvalues, CLI is outdated. Update to latest:
Wait for the update to finish, then re-verify withnpm update -g @gemdesign-ai/clinpm outdated -g @gemdesign-ai/cli. Do NOT proceed until re-verification confirms the CLI is up-to-date.
- If the command returns empty or shows
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 Step 3)
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 Step 3.
- If it fails (returns an error like "token 无效" or "未提供 token"), the user is NOT authenticated. You MUST:
- Tell the user: if they don't have an account or token yet, go to https://design.gemcoder.com to register an account and get an API token. The token retrieval path is: log in to the platform -> click 个人中心 (Personal Center) -> get the MCP 令牌 (MCP token).
- Ask the user for their API token (use
AskUserQuestiontool to prompt the user to input their token). - Once the user provides their token, automatically run the login command for them:
gemdesign auth login --token <user_provided_token> - Re-verify with
gemdesign auth whoamito confirm login succeeded. - If login still fails, repeat from step 2 (ask the user to provide their token again).
- Only proceed to Step 3 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, creating .stream.lock, 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 3: Start the Local Server (MUST complete after Step 2, 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.
After Step 1 (CLI installed) and Step 2 (Login verified) are both 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).
Start the local server using the CLI command:
CRITICAL — If Step 1 updated the CLI, stop the old server first. If you ran
npm update -g @gemdesign-ai/cliin Step 1, any previously running server is still using the OLD CLI code. You MUST stop it before starting a new one, otherwise the new server code will not be loaded:gemdesign server stop- If it returns
{"success":true,"message":"本地服务已停止"}, the old server has been stopped — continue to start a fresh server below. - If it returns an error like
{"success":false,"error":"未发现运行中的本地服务"}, no server was running — ignore this error and continue. - If Step 1 did NOT update the CLI (CLI was already up-to-date), skip the stop command and let
server startreuse the existing running server (if any).
gemdesign server start- If a server is already running, the command will detect it and return the existing port — no duplicate server will be started.
- 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.
- If it returns
Check server status (optional, for debugging):
gemdesign server statusReturns:
{"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 startcommand returned success), you MUST open the browser and navigate to the service page named GemDesign设计器 (URL:http://localhost:<port>- use the port from theserver startresponse).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 OpenPreviewand theintegrated_browserMCP'sbrowser_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 tohttp://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>/, macOSopen http://localhost:<port>/, Linuxxdg-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 URLhttp://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/debugreturns 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.htmlfile (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 # 查看服务运行状态
server start starts the local server as a background process. If a server is already running, it returns the existing port. On success, returns JSON with
portandurl. On failure, returns JSON witherrormessage — read it carefully to diagnose and fix the issue before retrying. server stop stops the running server. On Windows, usestaskkillto terminate the process tree. Returns error if no server is running or if the process cannot be terminated. server status returns the current status (runningorstopped), port, and URL if running.
Authentication
gemdesign auth login --token <token> # Configure API token
gemdesign auth whoami # Verify identity
App Management
gemdesign app create --name "MyApp" [--type web|app] # Create new app, --type defaults to web
gemdesign app list # List all apps
gemdesign app info [--appuuid <id>] # App details
gemdesign app use --appuuid <id> # Switch current default app
appuuid priority:
--appuuidflag >defaultAppUuid(set byapp create/app use) >GEMDESIGN_APPUUIDenv Once you runapp createorapp use, subsequentpagecommands don't need--appuuid. IMPORTANT: Always checkgemdesign app listBEFORE 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 callgemdesign app createmore than once in a single session/task. If you have already runapp createin 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 runninggemdesign app listto find it, thengemdesign app use --appuuid <id>. Creating a second app leaves the first one empty and orphaned on the platform. IMPORTANT - Output app info to user: After selecting/switching/creating an app (i.e., after anyapp create,app use, orapp infocall 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(桌面端) orapp(移动端) - returned byapp infoas thepageScenefield. When generating new pages, the page type MUST match the app type: awebapp can only containwebpages (desktop layout, wide screen), and anappapp can only containapppages (mobile layout, narrow screen). Before generating any HTML, check the app'spageScenefromapp infoand design the page accordingly. Do NOT generate a desktop-width page for anapptype app, or a mobile-width page for awebtype 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>/<id>.html # Get page HTML (auto-creates projectDir)
gemdesign page doc get --pageuuid <id> --file ./output/<projectDir>/<id>.md # Get requirement doc
Page - Save (with validation)
gemdesign page save --pageuuid <id> --file ./output/<projectDir>/<id>.html # Update existing
gemdesign page save --new --pageuuid <readable-id> --name "Login" --file ./output/<projectDir>/<readable-id>.html # Create new
gemdesign page doc save --pageuuid <id> --file ./doc.md # Save requirement doc
page saveautomatically validates the HTML against the GemDesign Page Spec before uploading.page doc savesaves an agent-generated requirement document to the platform.--pageuuidfor--new: Use a human-readable id (e.g. filename without.html). Ensure uniqueness within the app. This id is used directly asdata-uuidin 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.
Validate Only
gemdesign validate --file ./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>/<pageuuid>.html |
Page HTML (contains DSL, for editing and saving) | The file you generate and write |
Project subdirectory naming:
<projectDir> = {projectName}__{appuuid}
projectNamecomes fromapp info(illegal filesystem chars\/:*?"<>|removed, whitespace collapsed to_)- Empty
projectNamefalls back to默认项目; emptyappuuidfalls back tolocal- Examples:
CRM系统__abc-123,电商App__9f3e,默认项目__localHow to write files:
- Always use
./output/<projectDir>/<pageuuid>.htmlin all file paths, whether writing files directly or passing to CLI commands.- The CLI is idempotent: if the path already contains
<projectDir>, it will NOT duplicate it. You can safely pass./output/CRM系统__abc-123/home.htmltopage get --fileorpage save --filewithout worrying about nesting.- Compute
<projectDir>first: Rungemdesign 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}. IfprojectNameorappuuidis empty/undefined, re-rungemdesign app info. Never create files with an empty or partial<projectDir>(e.g.__abcorMyApp__) - this creates orphaned unnamed directories.The local server automatically serves pages from the project subdirectory path.
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
.stream.lockand.htmlfile 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.htmlURL (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 roothttp://localhost:<port>/, and even that should NOT be re-used after Step 3.
How It Works
The local server watches .stream.lock files and .html files:
- Create
.stream.lock→ browser enters streaming mode for that page - Append to
.html→ browser receives incremental HTML and re-renders - Delete
.stream.lock→ browser fetches the complete HTML and switches to final render
Steps
For each page you generate, follow this workflow instead of writing the complete HTML in one shot:
Compute paths:
htmlPath = ./output/<projectDir>/<pageuuid>.htmllockPath = ./output/<projectDir>/<pageuuid>.stream.lock
Create the stream lock file (signals browser to enter streaming mode AND triggers designer to switch to this project):
# Windows PowerShell: Set-Content -Path "./output/<projectDir>/<pageuuid>.stream.lock" -Value '{"pageUuid":"<pageuuid>","startTime":"<iso-timestamp>"}' # macOS/Linux: echo '{"pageUuid":"<pageuuid>","startTime":"<iso-timestamp>"}' > ./output/<projectDir>/<pageuuid>.stream.lockWait ~300ms for the browser to subscribe to the SSE channel.
CRITICAL - Designer auto-switches project: When the
.stream.lockfile is created, the local server pushes aswitchevent via theproject:listSSE channel. The designer SPA (already open in the browser) receives this event and automatically switches to the project being generated (matching byappuuidextracted from the<projectDir>path). This ensures the designer's SSE subscriptions (page:list:<appuuid>andpage:stream:<pageUuid>) are aligned with the project whose page is being generated. No manual action is needed - the switch happens automatically as part of creating the stream lock. If this is the first page being generated for a different project than what the designer currently shows, allow ~1-2 seconds for the designer to complete the project switch (destroy old canvas, reinitialize, re-subscribe SSE) before writing HTML content.Write the HTML file (append-only after the first write, NEVER overwrite with shorter content):
- You may write the HTML in one shot or in multiple appends — the stream poller detects file changes every 10ms 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
pageResetevent and forces the browser to re-render from scratch. - If you must rewrite from scratch, delete the
.htmlfile 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 stream poller pushes every file change to the browser within ~10ms.
- Clean up on failure: If streaming write fails or is interrupted, delete the
.stream.lockfile and any partial.htmlfile for that page. Never leave orphaned lock files - they keep the browser in streaming mode indefinitely. The local server also cleans up orphaned lock files and empty project directories on startup.
Validate the HTML (while streaming is still active — this ensures the browser stays in streaming mode until validation passes):
gemdesign validate --file ./output/<projectDir>/<pageuuid>.htmlIf validation fails, fix the HTML and re-validate. The browser continues to show the streaming state, giving immediate feedback on fixes. Do NOT delete the
.stream.lockfile until validation passes.Delete the stream lock file (only after validation passes — signals browser that streaming is complete):
# Windows PowerShell: Remove-Item "./output/<projectDir>/<pageuuid>.stream.lock" # macOS/Linux: rm ./output/<projectDir>/<pageuuid>.stream.lockThe browser will automatically fetch the complete HTML and switch to the final rendered version.
Save to platform:
gemdesign page save --new --pageuuid <pageuuid> --name "<pageName>" --file ./output/<projectDir>/<pageuuid>.html
Example (Streaming Write for a "home" page)
# 1. Create stream lock
Set-Content -Path "./output/MyApp__abc-123/home.stream.lock" -Value '{"pageUuid":"home","startTime":"2026-07-22T10:00:00Z"}'
# Wait ~300ms
# 2. Write the HTML file (one shot or multiple appends — your choice)
# Use Write tool to create ./output/MyApp__abc-123/home.html with the complete HTML:
# <!DOCTYPE html><html><head>...<script src="tailwind"></script>...</head><body>...content...</body></html>
# Or write in multiple appends (ensure first write includes <body> tag).
# 3. Validate (while streaming is still active)
gemdesign validate --file ./output/MyApp__abc-123/home.html
# Fix any validation errors and re-validate before proceeding
# 4. Delete stream lock (only after validation passes)
Remove-Item "./output/MyApp__abc-123/home.stream.lock"
# 5. Save to platform
gemdesign page save --new --pageuuid home --name "首页" --file ./output/MyApp__abc-123/home.html
Workflows
PRECONDITION FOR ALL WORKFLOWS: Step 1 (CLI installed & up-to-date), Step 2 (Login verified via
gemdesign auth whoami), AND Step 3 (local server running AND browser preview opened) MUST ALL be confirmed complete BEFORE starting any workflow. If login is not confirmed, do NOT generate HTML, do NOT create./output/files, do NOT start streaming write - stop and resolve authentication first. If the browser preview is NOT open yet, do NOT start generating any page — go back and complete Step 3 (open the browser) first. This applies to Workflow A, B, and C alike.
Workflow A: Batch Generation from Requirements
- Complete Prerequisites: Ensure Step 1 (CLI install/update), Step 2 (Login), AND Step 3 (local server running + browser preview opened) are ALL confirmed complete before proceeding. If the browser preview is not open yet, go back to Step 3 and open the browser ONCE to the designer at
http://localhost:<port>. If the preview is ALREADY open, do NOT open the browser again - the designer stays open and auto-loads generated pages via SSE for the entire session. Never open the browser with a generated-page URL (e.g.http://localhost:<port>/output/<projectDir>/<pageuuid>.html) - that overwrites the designer with the generated HTML and destroys the preview surface. - Ensure app exists (reuse first!):
- Run
gemdesign app listto check existing apps - If apps already exist: Run
gemdesign app use --appuuid <id>to set the target app as default. Do NOT create a new app unless the user explicitly asks for a new one. - If no apps exist: Run
gemdesign app create --name "<AppName>" [--type web|app]to create one (default type isweb). After creating, immediately rungemdesign app infoto confirm the app exists and record its appuuid. Do NOT runapp createagain for any reason in this session. - CRITICAL - No duplicate apps: If you already ran
app createearlier in this session (even in a previous workflow attempt), do NOT run it again. Reuse the existing app viaapp list+app use. Creating a second app leaves the first one empty and orphaned. - CRITICAL: All pages in the same batch MUST go into the same app. Reusing an existing app prevents pages from being scattered across different project folders.
- Run
- Get project directory name:
- Run
gemdesign app infoto get{appuuid}and{projectName} - Compute
<projectDir> = {projectName}__{appuuid}(remove illegal chars\/:*?"<>|from projectName, collapse whitespace to_) - Example: project name "电商 App" with appuuid "abc-123" →
<projectDir> = "电商_App__abc-123"
- Run
- Output current app info to user (CRITICAL — user must know which app pages will be generated into):
- Before generating any HTML, clearly tell the user in your text response which app you are generating pages into. At minimum, output:
- App name (
projectNamefromapp info) - App UUID (
appuuidfromapp info) - App type (
pageScenefromapp info-webfor 桌面端,appfor 移动端) - Project directory (
<projectDir>computed in step 3) - Page count to be generated in this batch (from step 5 analysis)
- App name (
- Example output format:
📦 当前应用信息 - 应用名称:电商 App - 应用 ID:abc-123 - 应用类型:app(移动端) - 项目目录:电商_App__abc-123 - 本次将生成页面数:5 - Type matching: The
pageScenevalue determines the page layout you MUST follow. Generateweb(desktop, wide-screen) pages forwebapps,app(mobile, narrow-screen) pages forappapps. Do NOT mix types - a web app cannot contain app pages, and vice versa. - If the user did not explicitly specify an app and you reused an existing app, also tell the user which app was selected (e.g. "已复用现有应用:电商 App") so they can interrupt if it's the wrong one.
- Pause-friendly: This is informational only - no user reply is required unless the user wants to switch apps. Continue to the next step immediately after outputting.
- Before generating any HTML, clearly tell the user in your text response which app you are generating pages into. At minimum, output:
- Search style (optional):
gemdesign style search --keywords "电商,现代,简洁"→ select one →gemdesign style get --id <id> - Analyze requirements: Read the requirements doc, break down into individual pages. Assign each page a readable
pageuuid(e.g.home,product-list,cart). - Generate design system page (only for newly created apps): If a new app was created in step 2 (not reused), generate a design system page as the visual style baseline before generating business pages. All subsequent business pages should follow this style. Determine the design system type based on
pageScenefromapp info, and generate the page following the type table and page structure in the dedicated "Design System Page Spec" section below. The pageuuid is fixed asdesign-systemand is NOT counted as a business page. You MUST save the design system page to the platform (not just write it locally) - otherwise it will not appear in the app and cannot serve as the style baseline. Use the Streaming Write Workflow with these explicit steps (same create-validate-save process as business pages):- Create
./output/<projectDir>/design-system.stream.lock(wait ~300ms for the browser to subscribe to SSE) - Write the HTML file to
./output/<projectDir>/design-system.html(follow the Design System Page Spec; pageuuid isdesign-system) - Validate:
gemdesign validate --file ./output/<projectDir>/design-system.html(fix errors and re-validate; do NOT delete.stream.lockuntil validation passes) - Delete
./output/<projectDir>/design-system.stream.lock(only after validation passes) - Save to platform (MANDATORY - do NOT skip):
gemdesign page save --new --pageuuid design-system --name "设计系统" --file ./output/<projectDir>/design-system.html(uploads the design system page into the app so it persists on the platform and shows up inpage list) - Verify it was saved:
gemdesign page list(confirmdesign-systemappears in the list) If the app was reused (switched viaapp usein step 2), skip this step AND skip step 8.
- Create
- Design System Review Gate (CRITICAL — only when step 7 generated a design system page): Before generating any business page, you MUST apply the "Design System Review Gate" rules (see that section below). Evaluate the continue conditions; if none apply, STOP and ask the user for confirmation/feedback on the design system using the format specified in that section. Do not proceed to step 9 until the design system is confirmed by the user or a continue condition is met. If the app was reused (step 7 was skipped), skip this step too.
- For each page (use Streaming Write Workflow above for real-time display):
- Generate HTML following the Page Spec below (incorporate style if available). Use the assigned
pageuuidasdata-uuidin navigation elements. All business pages MUST follow the style baseline established (and, if applicable, confirmed) in the design system page. - Use streaming write: Create
<pageuuid>.stream.lock→ write the HTML file (see "Streaming Write Workflow" section for details). Save HTML locally to:./output/<projectDir>/<pageuuid>.html(create the directory if it doesn't exist; use the<projectDir>computed in step 3) - Validate:
gemdesign validate --file ./output/<projectDir>/<pageuuid>.html - Fix any validation errors, re-validate (do NOT delete
.stream.lockuntil validation passes) - Delete
<pageuuid>.stream.lock(only after validation passes — signals browser that streaming is complete) - Save to platform:
gemdesign page save --new --pageuuid <pageuuid> --name "页面名" --file ./output/<projectDir>/<pageuuid>.html(uploads to platform)
- Generate HTML following the Page Spec below (incorporate style if available). Use the assigned
- Verify:
gemdesign page list
Workflow B: Conversational Generation
When user asks for a page in conversation:
- Complete Prerequisites: Ensure Step 1 (CLI install/update), Step 2 (Login), AND Step 3 (local server running + browser preview opened) are ALL confirmed complete before proceeding. If the browser preview is not open yet, go back to Step 3 and open the browser ONCE to the designer at
http://localhost:<port>. If the preview is ALREADY open, do NOT open the browser again - the designer stays open and auto-loads generated pages via SSE for the entire session. Never open the browser with a generated-page URL (e.g.http://localhost:<port>/output/<projectDir>/<pageuuid>.html) - that overwrites the designer with the generated HTML and destroys the preview surface. - Ensure app exists (reuse first!):
- Run
gemdesign app listto check existing apps - If apps already exist: Run
gemdesign app use --appuuid <id>to set the target app as default. Do NOT create a new app unless the user explicitly asks for a new one. - If no apps exist: Run
gemdesign app create --name "<AppName>" [--type web|app]to create one (default type isweb). After creating, immediately rungemdesign app infoto confirm the app exists and record its appuuid. Do NOT runapp createagain for any reason in this session. - CRITICAL - No duplicate apps: If you already ran
app createearlier in this session (even in a previous workflow attempt), do NOT run it again. Reuse the existing app viaapp list+app use. Creating a second app leaves the first one empty and orphaned. - CRITICAL: All pages MUST go into the same app. Reusing an existing app prevents pages from being scattered across different project folders.
- Run
- Get project directory name:
- Run
gemdesign app infoto get{appuuid}and{projectName} - Compute
<projectDir> = {projectName}__{appuuid}(remove illegal chars\/:*?"<>|from projectName, collapse whitespace to_)
- Run
- Output current app info to user (CRITICAL — user must know which app the page will be generated into):
- Before generating any HTML, clearly tell the user in your text response which app you are generating the page into. At minimum, output:
- App name (
projectNamefromapp info) - App UUID (
appuuidfromapp info) - App type (
pageScenefromapp info-webfor 桌面端,appfor 移动端) - Project directory (
<projectDir>computed in step 3)
- App name (
- Example output format:
📦 当前应用信息 - 应用名称:电商 App - 应用 ID:abc-123 - 应用类型:app(移动端) - 项目目录:电商_App__abc-123 - Type matching: The
pageScenevalue determines the page layout you MUST follow. Generateweb(desktop, wide-screen) pages forwebapps,app(mobile, narrow-screen) pages forappapps. Do NOT mix types - a web app cannot contain app pages, and vice versa. - If the user did not explicitly specify an app and you reused an existing app, also tell the user which app was selected (e.g. "已复用现有应用:电商 App") so they can interrupt if it's the wrong one.
- Pause-friendly: This is informational only — no user reply is required unless the user wants to switch apps. Continue to the next step immediately after outputting.
- Before generating any HTML, clearly tell the user in your text response which app you are generating the page into. At minimum, output:
- Generate design system page (only for newly created apps): If a new app was created in step 2 (not reused), generate a design system page as the visual style baseline before generating business pages. All subsequent business pages should follow this style. Determine the design system type based on
pageScenefromapp info, and generate the page following the type table and page structure in the dedicated "Design System Page Spec" section below. The pageuuid is fixed asdesign-systemand is NOT counted as a business page. You MUST save the design system page to the platform (not just write it locally) - otherwise it will not appear in the app and cannot serve as the style baseline. Use the Streaming Write Workflow with these explicit steps (same create-validate-save process as business pages):- Create
./output/<projectDir>/design-system.stream.lock(wait ~300ms for the browser to subscribe to SSE) - Write the HTML file to
./output/<projectDir>/design-system.html(follow the Design System Page Spec; pageuuid isdesign-system) - Validate:
gemdesign validate --file ./output/<projectDir>/design-system.html(fix errors and re-validate; do NOT delete.stream.lockuntil validation passes) - Delete
./output/<projectDir>/design-system.stream.lock(only after validation passes) - Save to platform (MANDATORY - do NOT skip):
gemdesign page save --new --pageuuid design-system --name "设计系统" --file ./output/<projectDir>/design-system.html(uploads the design system page into the app so it persists on the platform and shows up inpage list) - Verify it was saved:
gemdesign page list(confirmdesign-systemappears in the list) If the app was reused (switched viaapp usein step 2), skip this step AND skip step 6.
- Create
- Design System Review Gate (CRITICAL — only when step 5 generated a design system page): Apply the "Design System Review Gate" rules (see that section below). If no continue condition applies, STOP and ask the user for confirmation/feedback before proceeding. Do not proceed to step 7 until the design system is confirmed or a continue condition is met. If the app was reused (step 5 was skipped), skip this step too.
- Determine a readable
pageuuid(e.g. filename without.html, unique within the app) - Generate HTML following the Page Spec, using
pageuuidasdata-uuidin navigation elements. Follow the style baseline established (and, if applicable, confirmed) in the design system page. - Use streaming write (see "Streaming Write Workflow" section): Create
<pageuuid>.stream.lock→ write the HTML file to./output/<projectDir>/<pageuuid>.html(create the directory if it doesn't exist; use the<projectDir>computed in step 3) gemdesign validate --file ./output/<projectDir>/<pageuuid>.html- Fix errors if any, re-validate (do NOT delete
.stream.lockuntil validation passes) - Delete
<pageuuid>.stream.lock(only after validation passes — signals browser that streaming is complete) gemdesign page save --new --pageuuid <pageuuid> --name "<pageName>" --file ./output/<projectDir>/<pageuuid>.html(uploads to platform)- Describe the result to the user
When user requests modifications:
gemdesign page get --pageuuid <id> --file ./output/<projectDir>/<id>.htmlto retrieve HTML+DSL for editing- Modify the HTML (adjust DOM, add/remove interaction DSL, update jsHandle)
- For substantial modifications, use the Streaming Write Workflow: create
<id>.stream.lock→ rewrite the HTML (delete the old file first if starting fresh, or append if only adding)
- For substantial modifications, use the Streaming Write Workflow: create
gemdesign validate --file ./output/<projectDir>/<id>.html- Fix errors if any, re-validate (do NOT delete
.stream.lockuntil validation passes) - Delete
<id>.stream.lock(only after validation passes — signals browser that streaming is complete) gemdesign page save --pageuuid <id> --file ./output/<projectDir>/<id>.html- If requirement doc needs updating:
gemdesign page doc save --pageuuid <id> --file <updated-doc.md>
Workflow C: Modify Existing Page
- **Com
…(truncated)