prompt-app-builder
Build or update commercial-studio embedded prompt mini apps from a user-provided preset prompt. Use when the user gives a reusable image prompt/template, asks to package it as an app/小应用/内置提示词/模板化生图入口
SKILL.md.codex/skills/prompt-app-builder/SKILL.md
GitHubPrompt App Builder
Purpose
Turn a user-provided preset prompt into a project-native mini app under apps/public-web/src/features/prompt-apps/. Keep the full prompt hidden, expose only the variable fields users need, and submit through the existing public image job API. Treat prompt-apps.ts as the catalog surface, not as the long-prompt storage layer.
First Decisions
Extract these from the user's prompt before editing code:
- App name: short Chinese title, e.g.
科普百科图. - Slug: lowercase kebab-case route segment, e.g.
encyclopedia-card. - Primary variable: usually the placeholder inside
{...}, e.g.{狸花猫}means required fieldtopic. - Optional fields: usually
note/备注 unless the prompt clearly needs more fields. - Mode:
- Use
generateby default. - Use
editwith uploadedsource_asset_idonly when the user explicitly wants generation based on a supplied image.
- Use
- Count: default
requested_count: 1unless the user explicitly asks for multiple outputs.
If the prompt contains unsafe sexualization, minors, non-consensual, violent, or deceptive content, do not encode it directly. Offer a safe non-sexual template variant and continue only with acceptable wording.
Project Files
Use the existing prompt app structure:
- Catalog and light prompt exports:
apps/public-web/src/features/prompt-apps/prompt-apps.ts - Long prompt builders:
apps/public-web/src/features/prompt-apps/<slug>-prompt.ts - Shared generate-only scaffold when multiple apps share the same shape:
apps/public-web/src/features/prompt-apps/prompt-image-generate-app.tsx - Shared result panel when the same output UI is reused across apps:
apps/public-web/src/features/prompt-apps/prompt-app-result-panel.tsx - App center:
apps/public-web/src/features/prompt-apps/prompt-apps-home.tsx - Shared CSS:
apps/public-web/src/features/prompt-apps/prompt-apps.module.css - App cover assets:
apps/public-web/public/app-covers/<slug>.* - Existing result panel:
apps/public-web/src/features/prompt-apps/character-poster-result-panel.tsx - Existing example page:
apps/public-web/src/features/prompt-apps/character-poster-app.tsx - Existing route pattern:
apps/public-web/src/app/apps/<slug>/page.tsx - Public API:
apps/public-web/src/lib/public-api.ts - Image upload pattern when needed:
apps/public-web/src/features/home/generation-prompt-image-upload.tsx
Do not change backend APIs unless the requested app cannot be represented by the existing /image/jobs and /image/uploads flow. Do not fake uploads, generated results, or fallback success.
Implementation Workflow
Explore context
- Read
AGENTS.mdandapps/public-web/AGENTS.md. - Read the existing prompt app files listed above.
- Check
git status --shortand preserve unrelated changes.
- Read
Write a short design and plan
- Save a design doc to
docs/plans/YYYY-MM-DD-prompt-apps-<slug>-design.md. - Save an implementation plan to
docs/plans/YYYY-MM-DD-prompt-apps-<slug>.md. - Keep docs concise: goals, non-goals, route, fields, data flow, tests.
- Save a design doc to
Use TDD
- Add or update tests first.
- Run the narrow test and confirm it fails for the expected missing behavior.
- Implement the smallest code change.
- Re-run the narrow test and confirm it passes.
Catalog and prompt builder
- Add an item to
PROMPT_APPS:id: "<slug>"title- concise
description href: "/apps/<slug>"statusLabel: "内置提示词"access: "public-image-job-api"
- Add a typed prompt input, e.g.
<Name>PromptInput. - Add
build<Name>Prompt(input). - Export the builder from
prompt-apps.tsso tests and callers keep one public surface. - Keep long fixed prose out of React pages and out of the catalog file; place it in the dedicated prompt builder file.
- Convert
{placeholder}to a required form field line:【主题】= {${topic}}(${note})- Omit the parenthesized note when empty.
- When adding a second app with the same
topic / note / modelCodeshape, reuse or extract a shared scaffold instead of copying model loading, submit, polling, and error handling again. - If the preset prompt is long or likely to grow past a single screen, keep it in
apps/public-web/src/features/prompt-apps/<slug>-prompt.tsand import it from the catalog file. - Add a matching cover asset under
apps/public-web/public/app-covers/; default to a 3:4 portrait cover unless the app is explicitly landscape.
- Add an item to
State helper
- Create
apps/public-web/src/features/prompt-apps/<slug>-app-state.ts. - Export:
canSubmit<Name>()build<Name>ImageRequest()<Name>Stateget<Name>ErrorMessage()
- Use explicit request shape:
promptmodel_coderequested_countmode: "generate"ormode: "edit"source_asset_idonly for image-reference apps.
- Create
React page
- Create
apps/public-web/src/features/prompt-apps/<slug>-app.tsx. - Create
apps/public-web/src/app/apps/<slug>/page.tsx. - Reuse the existing quiet workspace design:
<AppShell activeHref="/apps" headerTitle="<title>" leadingAction={<PromptAppBackLink />} workspaceMode>styles.posterWorkspacestyles.posterPanelPosterResultPanelor a shared prompt-app result panel when the output UI is identical- same model loading, empty, and error labels.
- Required fields should disable submit until valid.
- Keep page components thin: they should wire config, state, and copy, not host the full prompt text.
- For upload/reference-image apps, reuse
publicApi.uploadImageAsset(file)and store{ assetId, assetUrl, mimeType }; do not continue silently after upload failure.
- Create
Styling
- Reuse
prompt-apps.module.css. - Add only shared, necessary classes.
- Keep cards/panels at 8px border radius where this feature uses framed controls.
- Keep text compact and readable on mobile; do not introduce a new visual language.
- Reuse
Tests
- Update
apps/public-web/tests/prompt-apps.test.mjsfor metadata and prompt builder. - Add
apps/public-web/tests/<slug>-app-state.test.mjs. - Add
apps/public-web/tests/<slug>-page.test.mjs. - For hidden prompts, assert the React page source does not contain long fixed prompt phrases.
- Assert the long prose lives in the builder module, not the page module.
- Assert catalog cover metadata and cover asset existence; for PNG check dimensions, for SVG check the file exists and declares a stable viewport.
- For image-reference apps, assert request mode/source asset behavior.
- Update
Verification
- Run the narrow tests during TDD.
- Run:
pnpm --filter public-web testpnpm --filter public-web typecheckpnpm --filter public-web lint
- Check fixed public port:
lsof -nP -iTCP:7700 -sTCP:LISTEN
- If 7700 is already running, smoke check:
curl -sS -o /tmp/<slug>.html -w "%{http_code}\n" http://127.0.0.1:7700/apps/<slug>curl -sS -o /tmp/apps.html -w "%{http_code}\n" http://127.0.0.1:7700/apps- Inspect the saved HTML with targeted
rgorgrep -q; do not dump the whole page to the terminal.
- If 7700 is not running, start only with
pnpm dev:public; do not switch ports silently. - Run
wc -lon touched feature and test files before finalizing; split files that approach the project line limit instead of adding one more copy-pasted page.
Quality Rules
- Keep user-facing replies in Chinese unless asked otherwise.
- Do not expose the full prompt template in the UI.
- Do not add mock success paths, silent fallbacks, caps, or fake generated data.
- Surface backend and upload failures as explicit errors.
- Keep functions under 50 lines and files under 300 lines; split helpers when needed.
- Prefer generic names for shared prompt-app components once they are reused by more than one app.
- Treat
apps/public-web/src/features/prompt-apps/prompt-apps.tsas a registry and type surface, not a dumping ground for long narrative prompts. - Avoid broad refactors. Touch only prompt-app feature files, tests, route files, and the plan docs needed for the app.