StoreCanvas is a free, open-source, local-first studio for turning real mobile-app captures into App Store and Google Play campaign assets. Compose a sequence where one visual idea can continue into the next frame, then export deterministic, store-sized images without giving your project to a hosted design platform.
Open the live Vercel demo · Read the architecture · Contribute
The public demo starts from a self-contained Ledgerly finance campaign. Your local projects, screenshots, generated backgrounds, and browser edits are not uploaded automatically.
Most screenshot tools treat each frame as a separate poster. StoreCanvas treats the campaign as a visual sequence:
| StoreCanvas approach | |
|---|---|
| Story | Connected captions and artwork can span up to ten adjacent screens while keeping each slot editable. |
| Real product UI | Use your actual captures inside hardware-aware iPhone, iPad, and Android frames. |
| Precision | Device slots are independent by default; shared transforms and copy continuity are explicit opt-ins. |
| Ownership | Projects live in browser storage or an explicitly configured local JSON file. Vercel stays read-only and needs no remote database. |
| No lock-in | Export PNGs or a JSON backup. Optional AI uses a key you provide for the current session; StoreCanvas has no accounts, plans, checkout, or usage meter. |
Requirements: Node.js >=22.13.0 and pnpm 11.9.0.
pnpm install
pnpm devOpen http://localhost:3000. If the ignored app-store-screenshots.json exists in the local checkout, the editor discovers it and loads it automatically on first use. Otherwise, it loads example-project.json as a safe seed. Changes are autosaved to the browser-local project library.
For a clean checkout, the first UI-test run also needs Chromium:
pnpm exec playwright install chromiumUse the visible Project selector to create campaigns, switch between local projects, import a JSON backup, or download a backup. In local development, the ignored app-store-screenshots.json is auto-discovered without an import step. To also write edits back to a specific local file, create .env.local:
STORECANVAS_PROJECT_FILE=app-store-screenshots.jsonThe private filename, uploaded screenshots, generated backgrounds, and exports are ignored by Git. The checked-in example is never overwritten by default. A Vercel page cannot read a developer's localhost filesystem, so moving a project between origins requires a one-time JSON import; after that, browser storage restores it on that origin.
- Choose or create a project from Project.
- Add real captures by dropping files into the inspector, choosing a checked-in fixture, or importing public App Store metadata.
- Select a template and palette. Manual placement, custom tokens, and connected artwork remain untouched unless the corresponding reset/reflow option is enabled.
- Arrange copy, device slots, hardware model, camera angle, crop, visibility, and locking on the canvas. Select any layer and press Delete (or Backspace) to remove it; built-in layout layers are hidden reversibly and custom layers can be restored with Undo.
- Use the sizes control beside the device selector to choose export targets. New iPhone and iPad projects start with Apple's global target only; additional sizes are opt-in and saved per device.
- Export the selected locale/device deck or use the CLI for repeatable render jobs. When a supported phone, iPad, or tablet deck is empty, it receives an independent copy of the iPhone story, including adapted device paths and connected artwork bounds. iPad keeps all ten slots; Android phone/tablet decks mirror the first eight because Google Play's export limit is eight screenshots.
The starter campaign is deliberately self-contained so the visual system is visible before importing any app. It uses Ledgerly, a fictional personal-finance app, so the example demonstrates product storytelling instead of placeholder copy:
- Screens 1–2 connect a generated signal artwork and one headline across a light/dark seam while showing the dashboard and cash-flow features in one device per slot.
- Screens 3–7 walk through accounts, an AI money coach, goals, automation, and insights; the device frame rotates independently on selected slides.
- Screens 8–9 connect privacy and recurring-bills features with a second shared caption, making per-slot text contrast visible without stacking devices.
- The same story hydrates into iPad and Android phone/tablet decks, with the platform's valid screenshot limit preserved.
Select Connected in the toolbar, then click those thumbnails to inspect each composition and its opt-in controls. The Ledgerly captures and signal artwork live in public/screenshots/demo and public/backgrounds; no personal campaign assets are needed.
- Connected or isolated canvas composition with exact export-time crops, a responsive dock that can hide or swap the Screens and Settings panels, and keyboard-first layer deletion.
- Captions and artwork that span up to ten screens with per-slot contrast controls and light/dark surface guidance.
- Independent device slots, plus explicit opt-in transform linking when repeated captures should move together.
- iPhone 17 Pro Max, iPhone 14 Pro Max, and iPhone 13 Pro Max frames with Dynamic Island/cutout and physical controls.
- Flat, optical-tilt, low-angle, high-angle, and custom camera controls.
- Twelve campaign templates and twelve palette presets, with custom brand tokens and accessible contrast guidance.
- A typography system with self-hosted open fonts, template-level pairings, slide-level caption overrides, and per-layer family, size, color, weight, italic, decoration, and auto-contrast controls.
- Per-slide text layers, responsive constraints, hiding/locking, undo/redo, multiple locales, and JSON backups.
- App Store URL import that creates a project-owned template, palette, and copy direction from listing metadata and screenshot color signals. Published composites stay reference-only unless the user opts into using them as captures.
- Optional bring-your-own-key copy polish through OpenAI or OpenRouter, plus connected-artwork generation through OpenAI. Choose 1–10 covered screens; the API prompt receives the requested span and light/dark tone pattern. Keys remain in memory for the current dialog session.
- Deterministic Playwright rendering for exact storefront sizes and an agent CLI that can inspect, compose, generate and render every configured locale/device deck.
StoreCanvas does not operate a hosted project database, account system, telemetry pipeline, billing flow, or usage meter. Local browser storage is the canonical library; local file sync is explicit; Vercel writes are disabled. AI requests go only to the provider selected by the user and may have that provider's own cost or terms.
The repository contains a fictional Ledgerly fixture: its product screens, icon, and connected signal artwork are generated visual assets included for demonstration and testing. App Store metadata, screenshots, app icons, logos, and downloaded/generated assets from a user's own project may belong to someone else. Only redistribute assets for which you have permission, and keep private campaign material in ignored paths.
Accent color is adaptive by default. StoreCanvas keeps the requested hue, then adjusts lightness when the active light/dark surface would make a small label hard to read. This is deterministic and applied by the same render path used by the editor, thumbnails, and exports; the minimum target for accent labels is 3:1 and normal text targets 4.5:1. The Type tab in Campaign lets you switch back to a fixed accent or tune the behavior.
Typography is layered so a campaign can stay coherent without taking control away from the creator: the Type tab sets the campaign pairing, selecting Headline on a canvas exposes label/headline overrides for the current slide, and selecting a custom Text layer exposes its own family, size, color, weight, italic, decoration, and contrast controls. Font choices are bundled with next/font at build time and are limited to open-licensed families or operating-system fallbacks. See the Google Fonts source catalog, Space Grotesk, and the attribution notes in THIRD_PARTY.md.
Start the dev server, then run:
pnpm storecanvas render --device iphone --locale en-US --output exports/renderedUse --all to render every configured locale and device deck with screens. The CLI follows each project's saved export-size selection and falls back to Apple's global target for legacy projects. Set STORECANVAS_URL when the server is not at http://127.0.0.1:3100. The renderer reads the same STORECANVAS_PROJECT_FILE setting as the editor.
StoreCanvas exposes a local, JSON-first automation bridge at /api/agent and a zero-config CLI at pnpm storecanvas. This is the recommended integration for Codex, Claude, Cursor, or any agent that can run terminal commands: it has no MCP SDK dependency, uses the same project contract as the editor, and can be wrapped by an MCP adapter without duplicating template logic.
Start the editor once, then discover the available IDs before making a composition change:
pnpm dev -p 3100
pnpm storecanvas catalog --json
pnpm storecanvas inspect --jsonApply a template and optionally its recommended palette. Manual placement and artwork reflow remain explicit flags:
pnpm storecanvas apply-template \
--template afterglow-rhythm \
--device iphone \
--recommended-palette \
--jsonGenerate a continuous background across any adjacent range of 1–10 screens. The command applies the selected template first, infers the deck's light/dark rhythm, stores the generated image under an ignored local asset path, and updates the project atomically:
OPENAI_API_KEY="$OPENAI_API_KEY" pnpm storecanvas generate-background \
--template afterglow-rhythm \
--device iphone \
--start-slot 1 \
--slots 10 \
--prompt "A warm dusk horizon with subtle violet and amber motion, quiet negative space for phones and headlines" \
--artwork-id campaign-panorama \
--jsonUseful automation commands:
| Command | Purpose |
|---|---|
catalog --json |
List supported devices, templates, palettes and capabilities. |
inspect --json |
Summarize the selected project and every connected artwork span; with the app running, also expands empty iPad/Android decks using the editor defaults. |
validate --json |
Run schema and export-readiness checks; exits non-zero on errors. |
screens --json |
List every screen's layout, headline/label, resolved screenshot, artwork and hidden layers (works offline). |
edit-screen --screen <n> |
Change a screen's --headline, --label, --layout, --image or --secondary-image (alias set-copy). |
set-project |
Switch --device, --orientation, --locale, --app-name, --palette or `--connected on |
help [command] [--json] |
Command list and typical flow; --json emits a machine-readable manifest. |
apply-template --template <id> |
Recompose one device deck with optional palette/reset flags. |
remove-element --element <id> |
Remove a text/artwork/extra slot, or hide a built-in layer; use --screen to target a screen. |
generate-background --slots <1-10> |
Generate and attach one connected artwork to adjacent slots. |
render --all |
Export all configured device/locale decks through Playwright. |
All mutating commands create an ignored backup in exports/backups/, support --dry-run, and try to refresh the running local editor. Use --project path/to/project.json to target a file explicitly; otherwise the CLI follows the same local-project priority as the editor. Keep OPENAI_API_KEY in the environment (or use --api-key-env)—keys never enter project JSON, logs, or generated prompts. Full agent instructions live in skills/storecanvas-agent/SKILL.md, and the HTTP contract is implemented in src/app/api/agent/route.ts.
pnpm typecheck
pnpm test # Vitest unit tests
pnpm test:ui # Playwright UI tests
pnpm test:all
pnpm build
pnpm audit --audit-level highCI runs dependency audit, typecheck, unit tests, Playwright browser tests, and a production build on pushes and pull requests to main. See CONTRIBUTING.md for the contribution workflow and docs/OPEN_SOURCE_AUDIT.md for the current audit snapshot.
| Path | Purpose |
|---|---|
example-project.json |
Safe, checked-in demo campaign |
src/lib/defaults.ts |
Blank fallback/reset state |
src/lib/project-file.ts |
Configurable and auto-discovered local project resolution |
src/components/editor/ |
Editor UI, canvas, frames, project selector, and inspectors |
src/lib/campaign-presets.ts |
Templates and palette presets |
src/lib/agent-workflow.ts |
Shared agent operations for templates, spans, summaries, layer removal and generated artwork |
src/app/render/ |
Server-rendered deterministic export surface |
src/app/api/agent/route.ts |
Local JSON bridge for terminal/MCP-style agent integrations |
scripts/storecanvas.mjs |
Agent and Playwright export CLI |
skills/storecanvas-agent/SKILL.md |
Instructions for an AI agent using the CLI safely |
tests/ |
Unit and UI regression suites |
- Contributing · Code of Conduct · Support
- Security policy · Architecture · Roadmap
- Changelog · Open-source audit · Citation
- Third-party open-source attribution
StoreCanvas is not affiliated with Apple, Google, Vercel, OpenAI, or any app whose assets a user imports.
POST /api/ai/image accepts spanSlots from 1 to 10, plus optional tone (light, dark, or mixed) and tonePattern (an ordered array of light/dark surfaces). The server adds those constraints to the image prompt, sends the request directly to OpenAI, and saves the returned image only in the local upload path. The API key is request-scoped and never written to project JSON or browser storage. Agents should use /api/agent or pnpm storecanvas generate-background so the generated path is attached to the project automatically.
Copyright (c) 2026 Luis Lucatero. Source code and the included demo assets are available under the MIT License.