Skip to content

snice/app-page-studio

Repository files navigation

App Page Studio

English | 简体中文

App Page Studio is a workspace for turning design inputs into structured AI implementation prompts for Flutter, React Native, and UniApp page restoration.

It supports HTML exports, PNG/JPG/WebP design images, PSD previews and layer slicing, page grouping, interaction/slice/feature annotations, design-system metadata, and multi-user collaboration.

Demo Site

Features

  • Multi-source design input: Upload HTML ZIP files, image ZIP files or standalone images, PSD or PSD ZIP files, and imports from Figma/Pixso plugins.
  • AI HTML IR generation: Generate previewable HTML IR from PNG/JPG/WebP or PSD previews, then refine it through AI chat.
  • Page workspace: Use a left file list, center phone preview or PSD canvas, and right page configuration panel.
  • Page grouping: Group default, loading, empty, and other states of the same page.
  • Page configuration: Configure state name, development status, route, source path, tab bar, data sources, and more.
  • Element picker: Pick elements in HTML mode, or drag regions in design-image mode.
  • Interaction annotations: Add tap, swipe, and other interaction descriptions to elements or regions.
  • Slice annotations: Upload slice assets to __assets__/, or mark slices in PSD layers and canvas.
  • PSD workflow: Generate PSD previews, inspect layers, mark slices, and keep slice data synchronized.
  • Feature annotations: Mark native-capability areas such as scanning, maps, and camera usage.
  • Design system: Maintain colors, spacing, radii, and other design rules for prompt generation.
  • Prompt generation: Generate prompts for Flutter, React Native, or UniApp by development status or current page.
  • Login and permissions: Support admins, users, project members, and owner/editor/viewer roles.
  • Multi-user collaboration: Use WebSocket presence and synchronization for uploads, deletes, and saves.
  • Fine-grained saves: Save the current page or the full project config to reduce collaboration conflicts.
  • Dark and light themes: Switch between UI themes.

Architecture

App Page Studio architecture diagram

Quick Start

Install Dependencies

The dev and build scripts run pnpm install automatically. You can also install manually:

pnpm install

Development Mode

The repository uses a pnpm workspace for the backend and frontend. The Vite frontend proxies /api, /html, and /ws to the backend:

# Start the backend API / WebSocket server (3000) and Vite frontend (5173)
pnpm run dev

Open http://localhost:5173

Build

Create a release ZIP package:

pnpm run build

Build output is written to release/. After extracting the release package, follow the bundled README.txt to start it.

First Login

On first startup, if the database has no users, the server creates an admin account:

  • Default username: admin
  • Default password: if no environment variable is set, startup logs print a random password

You can set the initial admin account with environment variables:

BOOTSTRAP_ADMIN_USERNAME=admin BOOTSTRAP_ADMIN_PASSWORD=123456 pnpm --filter server start

Reset a specific account password to the default value 123456:

pnpm --filter server reset-password -- -u <username>

AI HTML IR Configuration

HTML IR generation is optional and requires an OpenAI-compatible Chat Completions API. The server reads packages/server/.env first, then falls back to process environment variables.

Create packages/server/.env from packages/server/.env.example:

AI_AGENT_BASE_URL=https://api.openai.com/v1
AI_AGENT_API_KEY=sk-...
AI_AGENT_MODEL=gpt-4o
AI_AGENT_MAX_TOKENS=12000

For OpenAI-compatible gateways, AI_AGENT_BASE_URL must expose the /v1/chat/completions interface.

Workflow

1. Log In and Create a Project

After login, you enter the project home. Admins can manage users. Project owners and admins can manage project members.

When creating a project, you can upload a ZIP:

  • HTML/HTM files are extracted to __html__/
  • PNG/JPG/WebP files are extracted to __design__/
  • PSD files are extracted to __psd__/

You can also create an empty project first, then upload HTML, design images, or PSD files in the workspace.

Figma/Pixso import:

  • The plugin lives in packages/figma-plugin/; load manifest.json in Figma.
  • The Pixso plugin lives in packages/pixso-plugin/; load manifest.json in Pixso.
  • In the workspace, click Figma/Pixso, generate an upload token, then paste both the server URL and token into the plugin settings.
  • The plugin reads the token scope and lets you choose the target project and page group.
  • The plugin imports page PNGs into the selected project's __design__/, slice PNGs into __assets__/, and writes slice regions into page config.

2. Open the Workspace and Refresh Files

Open a project through /dashboard?pid=<projectId>. The refresh action scans the current project for:

  • HTML files under __html__/
  • Design images under __design__/
  • PSD files and previews under __psd__/

When other users upload or delete files, WebSocket broadcasts files:changed, and clients in the same project rescan the file list automatically.

3. Configure Page Groups

Select related files and create a page group. For example, group the default, loading, and empty states of the home page as "Home".

A page group can define:

  • Name and description
  • Route path
  • Flutter / React Native / UniApp source paths
  • Marker color

Page groups and file assignments share one conflict dimension, guarded by the group hash during save.

4. Configure a Single Page

After selecting a file, configure page information in the right panel:

  • State name
  • Page description
  • Development status: todo / in progress / done
  • Page group
  • Tab bar configuration
  • Data source configuration
  • Interactions, slices, and feature descriptions

Single-page configuration uses a per-file conflict dimension. Multiple users can save different pages independently.

5. Mark Interactions, Slices, and Features

HTML mode:

  • Click "Add interaction" and pick an element in the iframe
  • Add interactions, slice annotations, feature descriptions, or inspect styles

Design-image mode:

  • Drag a region on the image
  • Add interactions, slices, or feature descriptions to the region

PSD mode:

  • Use the PSD canvas and layer panel to locate content
  • Mark slices on the canvas
  • Save slice data to the current PSD page configuration

6. Generate and Refine HTML IR

For PNG/JPG/WebP design images and PSD previews, switch the preview mode to HTML IR. The right-side AI panel is shown only in this mode.

The MVP supports:

  • Generate or regenerate HTML IR from the source design image.
  • Stream AI progress stages while the HTML is being generated.
  • Save generated output as a self-contained preview page:
    • __design__/xxx.png -> __design__/xxx/index.html
    • __psd__/xxx.png -> __psd__/xxx/index.html
  • Keep img/, css/, and js/ subdirectories in the generated page directory for future local assets.
  • Preview the generated HTML online in the iframe.
  • Refine generated HTML through AI chat.
  • Select one or more preview elements before sending a refinement instruction, so the AI receives the target selectors and element summaries.

The backend validates AI output before saving:

  • The response must be valid HTML.
  • SVG tags are rejected.
  • pointer-events: none and user-select: none declarations are removed so elements remain selectable in preview.
  • Local image references are checked against real project files; when an AI-invented filename can be matched by asset hash, it is repaired automatically.

Local smoke test:

pnpm --filter server test-ai-html-agent -- --projectId 1 --path __design__/figma_page_d8e2c82aab.png

7. Save Configuration

The top bar provides two save entry points:

  • Save current page: Save unsaved group changes first if needed, then save the current file configuration.
  • Save all: Save the entire pagesConfig, useful for batch edits or global configuration changes.

Conflict control:

  • Current-page saves use entityHashes.files[path] to check whether the target file changed remotely.
  • Group saves use entityHashes.groups to check whether page groups or assignments changed remotely.
  • Full saves use the global revision guard.

When another user saves the same page or group, WebSocket notifies the client and auto-merges when the local state is clean.

Every successful save advances the pages-config revision used by collaboration conflict guards.

8. Generate Prompts

Click "Generate prompt" and choose a target platform:

  • Flutter
  • React Native
  • UniApp

You can filter by development status or generate only for the current page. For design-image pages, generated HTML IR is passed through as the visual source of truth when available. If HTML IR has not been generated yet, the platform prompt asks you to generate UI IR(HTML) according to UI-IR-AGENT.md first, then implement code from the IR.

Project Structure

app-page-studio/
├── package.json           # pnpm workspace scripts
├── pnpm-workspace.yaml
├── packages/
│   ├── server/
│   │   ├── server.js      # Express entry, session, static assets, WebSocket
│   │   ├── db.js          # SQLite schema and data-access modules
│   │   ├── paths.js       # workspace paths, data paths, frontend build paths
│   │   └── api/
│   │       ├── auth.js
│   │       ├── projects.js
│   │       ├── pages.js
│   │       ├── html.js
│   │       ├── image.js
│   │       ├── psd.js
│   │       ├── prompt.js
│   │       ├── prompt/
│   │       └── utils.js
│   └── client/
│       ├── index.html     # Vite entry
│       ├── vite.config.js # Vite proxy for /api, /html, /ws
│       └── src/
│           ├── main.jsx
│           ├── App.jsx
│           ├── pages/
│           ├── components/
│           ├── hooks/
│           ├── lib/
│           └── styles/
├── html_caches/
│   └── {projectId}/
│       ├── __html__/      # HTML design exports
│       ├── __design__/    # PNG/JPG/WebP design images and generated HTML IR bundles
│       ├── __assets__/    # User-uploaded slice assets
│       └── __psd__/       # PSD files and generated PNG previews
└── studio.db              # SQLite database

API Overview

Business APIs require login. Login state is stored through express-session.

  • POST /api/auth/login, POST /api/auth/logout, GET /api/auth/me
  • GET/POST/PUT/DELETE /api/auth/users...: admin user management
  • GET /api/projects, POST /api/projects, PUT /api/projects/:id, DELETE /api/projects/:id
  • GET/POST/PUT/DELETE /api/projects/:id/members...: project member management
  • GET /api/pages: read pages config, revision, and entity hashes
  • POST /api/pages: save the full config
  • PATCH /api/pages/file: save one page config
  • PATCH /api/pages/groups: save page groups and file assignments
  • POST /api/upload-html, GET /api/scan-html, GET /api/html-content
  • POST /api/upload-image, GET /api/list-images, POST /api/upload-asset
  • POST /api/upload-psd, GET /api/list-psd, GET /api/psd-preview
  • POST /api/ai-html-agent/generate, POST /api/ai-html-agent/refine: generate and refine HTML IR
  • POST /api/figma/token, GET/PATCH/POST/DELETE /api/figma/tokens...: create and manage Figma/Pixso upload tokens
  • POST /api/figma/verify, POST /api/figma/import: Figma/Pixso plugin verification and import
  • POST /api/download-design-zip
  • POST /api/generate-prompt

Collaboration and Save Model

Page configuration is still stored as one full JSON blob in project_pages.pages_json, but save entry points are split by conflict dimension:

  • Single-page information: one htmlFiles[] entry identified by path, guarded by the file hash.
  • Group information: pageGroups[] plus groupId and isPrimaryState assignments in htmlFiles[], guarded by the group hash.
  • Global information: the full config, guarded by revision.

WebSocket provides collaboration awareness and synchronization:

  • Presence shows collaborators on the current project, page, or group.
  • Uploading or deleting HTML, design images, or PSD files broadcasts files:changed.
  • Saving the current page broadcasts pages:file-saved.
  • Saving groups broadcasts pages:groups-saved.
  • Saving the full config broadcasts pages:full-saved.
  • Filesystem changes in HTML/PSD files broadcast html:changed.

Tech Stack

  • Backend: Node.js, Express, express-session, WebSocket
  • Database: SQLite, better-sqlite3, better-sqlite3-session-store
  • File processing: Multer, ADM-Zip, archiver, Chokidar
  • PSD processing: psd for backend previews, ag-psd for frontend parsing
  • AI integration: OpenAI Node SDK with Chat Completions-compatible APIs
  • Frontend: Vite, React, React Router, Zustand, HeroUI, Tailwind CSS

Prompt Usage Suggestions

After generating prompts, place the corresponding design resources in the target project and put UI-IR-AGENT.md at the Flutter / React Native / UniApp project root.

Suggested batch workflow:

  1. Mark pages to implement as "in progress".
  2. Generate prompts only for the current page or current development status.
  3. Confirm slice asset paths and source paths are configured.
  4. After AI generates code, manually review styles, routing, state management, and API logic.

FAQ

Q: What should I do if preview does not show? A: Confirm you are logged in, have project access, and have uploaded HTML, design images, or PSD files. Click "Refresh" to rescan.

Q: Why can other users not see the design image I uploaded? A: A successful upload broadcasts file changes through WebSocket. If a client was disconnected, click "Refresh" to rescan the file list.

Q: Why does saving the current page report a conflict? A: Another user has already saved the same page. Load the latest version, then merge your changes.

Q: When should I use save all? A: Use it for batch edits, global design-system changes, or broad configuration changes. In daily collaboration, prefer "Save current page".

Q: Can a viewer edit? A: No. Viewers are read-only. Owners and editors can save, and owners plus admins can manage project members.

License

MIT

About

一个用于将 设计稿 HTML / 设计图(PNG/JPG/WebP) 转换为 AI 开发提示词的工具,帮助快速还原 Flutter、React Native 和 UniApp 页面。

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors