From snap-mock-skill
Generate 6 Google Play Store mockup screenshots (1080x1920 PNG) PLUS a Feature Graphic (1024x500 PNG) by analyzing a LOCAL project directory. Triggers on phrases like "snap mock <path>", "generate mockups for this project", "play store screenshots from my code", "create app store mockups". Reads the entire target codebase (every text file, with sane skip patterns), so Claude has full repo understanding before synthesizing. Runs entirely in-session — no API key required, no GitHub access needed. Output lands in ./mockups/.
How this skill is triggered — by the user, by Claude, or both
Slash command
/snap-mock-skill:mockup-exportThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
Generate 6 Google Play Store mockup screenshots by analyzing a **local project directory**.
references/PROMPT.mdscripts/analyze-local.shscripts/cleanup.shscripts/export-screenshots.mjsscripts/scaffold.shscripts/start-dev.shscripts/wait-for-server.shtemplates/BriefsBootstrapper.tsxtemplates/MockupCanvas.tsxtemplates/api-export-all-route.tstemplates/api-render-screen-image-route.tstemplates/api-render-screen-route.tstemplates/briefs.example.jsontemplates/loadBriefs.tstemplates/meshGradient.tstemplates/mockupStore.tstemplates/page-patch-instructions.mdtemplates/renderScreenshot.tstemplates/renderer/eslint.config.mjstemplates/renderer/next.config.tsGenerate 6 Google Play Store mockup screenshots by analyzing a local project directory.
node_modules, ios/Pods, build outputs, binaries, lockfiles, etc.) and writes a manifest + a captured-source bundle.references/PROMPT.md and synthesizes 6 mockup briefs (headlines, layouts, themes, screen UI) using full-repo context.public/briefs.json in the user's existing Next.js + Konva app../mockups/slot-01.png … slot-06.png AND ./mockups/feature-graphic.png (1024×500 banner)./Users/me/projects/my-app). Can be the user's cwd by default if no path is given.node (≥20), npm, and python3 on PATH. No gh, no GitHub token, no internet required.~/.cache/ms-playwright).The renderer is bundled. The skill ships its own Konva renderer template at ${CLAUDE_PLUGIN_ROOT}/skills/mockup-export/templates/renderer/. On first run, scaffold.sh materializes it at ~/.snap-mock-renderer/ (override with SNAP_MOCK_RENDERER_HOME) and runs npm install once. Subsequent runs are fast — the renderer is reused. If the user is already inside an existing Next.js + React + Konva project, the script auto-detects that and uses in-place mode instead (legacy v0.1 behavior; copies library files into the existing project, prints toolbar/page patch instructions).
When the user invokes you with a GitHub URL (e.g. "snap mock https://github.com/owner/repo"), do the following in order. Do not skip any step.
Run bash ${CLAUDE_PLUGIN_ROOT}/skills/mockup-export/scripts/scaffold.sh.
This script auto-selects between two modes:
STANDALONE mode (default — used when no Next.js + Konva project is in cwd or cwd/frontend):
templates/renderer/ into ~/.snap-mock-renderer/ (override with SNAP_MOCK_RENDERER_HOME)..snap-mock-version hash).npm install and npx playwright install chromium on first run only.${CLAUDE_PLUGIN_DATA}/scaffold.env with APP_ROOT=$HOME/.snap-mock-renderer.IN-PLACE mode (auto-detected when cwd or cwd/frontend has next + react + konva):
loadBriefs.ts, BriefsBootstrapper.tsx, and scripts/export-screenshots.mjs.meshGradient.ts and renderScreenshot.ts (backups go to .claude/skill-mockups-backup/).jszip, playwright, adm-zip if missing..claude/skill-mockups.json.EditorToolbar.tsx doesn't have the Export ZIP button or page.tsx doesn't mount <BriefsBootstrapper /> — apply the patches in templates/toolbar-patch-instructions.md and templates/page-patch-instructions.md using the Edit tool.Force standalone with SNAP_MOCK_MODE=standalone bash …/scaffold.sh. Force in-place with SNAP_MOCK_MODE=inplace ….
After scaffold, read ${CLAUDE_PLUGIN_DATA}/scaffold.env to learn APP_ROOT for subsequent steps.
Run bash ${CLAUDE_PLUGIN_ROOT}/skills/mockup-export/scripts/analyze-local.sh <target-directory>.
If the user gave a <github-url> instead of a path, the URL form is no longer supported — ask them for the local path of the project they want mockups for.
This script writes:
./scratch/skill-output/manifest.json — list of every text file in the project (with size), so Claude can request specific files later if needed./scratch/skill-files/<encoded-path> — captured contents for the first 200 files (truncated at 8KB each)./scratch/skill-output/analysis.json — prompt-ready bundle: app_name, framework, description, topics, brand_colors, screens, readme_full, source_context, key_files, app_icon_localOverride OUT_DIR / FILES_DIR env vars to relocate scratch output (recommended: write under the user's cwd, e.g. OUT_DIR=./mockup-test/skill-output).
Skip patterns enforced: node_modules, .git, .next, dist, build, out, target, vendor, venv, __pycache__, ios/Pods, ios/build, android/build, android/.gradle, android/app/build, coverage, DerivedData, .expo, .xcworkspace, .xcodeproj, plus binary file extensions (.png, .ttf, .zip, etc.) and lockfiles.
You — Claude — perform this step yourself. Do NOT call a Python helper, generator script, or any other code to produce briefs.json. Do not reuse a previously generated briefs.json from another project. This is reasoning work that must be redone for every target so the output is dynamically derived from THIS project's source.
Read ${CLAUDE_PLUGIN_ROOT}/skills/mockup-export/references/PROMPT.md — it contains the six-pass prompt (Narrative Arc → Style Profile Extraction → Content Brief → Layout Design → Validation → Feature Graphic).Read ./scratch/skill-output/analysis.json (or wherever OUT_DIR placed it).Read ./scratch/skill-output/manifest.json to identify files you still need.Read the navigator file directly — search the manifest for _layout.tsx, Navigator, or App.tsx and read it to extract the REAL tab labels and screen graph. Do not guess.Read 2–3 screen source files directly — typically src/screens/<Hero>Screen.tsx plus any theme.ts / colors.ts / tailwind.config.js / paperTheme.ts. The source_context truncation in analysis.json is INSUFFICIENT for style extraction — StyleSheet.create({...}) blocks often live below the 8KB cutoff. Read full files. The style profile (typography ramp, colors, gradients, spacing scale, shape, density, elevation, mood modifiers) MUST be extracted and ship as a top-level style_profile block in briefs.json.Read 1–3 additional relevant screen source files when source_context doesn't give you enough text to write authentic screen_ui content (this is in addition to the style-extraction reads in step 5; one file can serve both purposes).style_profile, the 6 screenshots, AND the featureGraphic block.Inputs:
analysis.json you just wrote.manifest.json for file lookups.Read from the target directory.date -u +"%Y-%m-%dT%H:%M:%SZ") — you'll embed this as generatedAt.Output: a single JSON object matching the briefs.json schema in PROMPT.md. Output ONLY the JSON. No preamble, no code fences, no commentary.
Hardcoding ban (production-grade requirement): every string AND every style value in the output must trace back to either (a) analysis.json from THIS run, or (b) a file you read from the target directory in this session. If you find yourself about to write a brand color, screen name, list-item label, headline, fontSize, padding, or corner_radius that came from a previous conversation or example, stop and re-derive it from the current source. The style ban is enforced: every font_size in your output must equal a style_profile.type_ramp.<role>.size value; every corner_radius must equal a style_profile.shape.<key> value; every fill color must equal style_profile.colors.<key> or appear in a style_profile.gradients[].colors. The renderer will silently snap mismatched values, so writing them wrong wastes effort.
Asset ban (visuals come from the project only): the only imagery allowed in the output is (a) analysis.app_icon_url, (b) the in-device screen render produced by /api/render-screen-image, and (c) entries from analysis.project_assets. Do NOT fetch external photos, generate AI images, or ship stock art. If the project has no usable illustrations/splash/hero assets, every slot uses solid color + texture only — that is the correct outcome, not a fallback.
Headline copy rule (short by design): headlines are 1 or 2 lines max, 2–5 words total, ≤20 characters per line, ALL CAPS. Single-line headlines are preferred. Examples: "TRADE GRADE", "STOP\nGUESSING", "BUILD ANYTHING". Subtitles ≤35 characters, single line.
Required top-level fields (in addition to version, generatedAt, theme, screenshots, featureGraphic):
appName — copy from analysis.app_nameappIconUrl — copy verbatim from analysis.app_icon_url (a data:image/...;base64,... URL — already embedded by analyze-local.sh)projectAssets — copy analysis.project_assets verbatim ONLY if any image_placeholder element references one of its entries via asset_url. The runtime needs the array to resolve path → data_url at render time. Omit when no element uses it.style_profile — REQUIRED. Extracted by you in PASS 0.5 from the target's source files. See PROMPT.md PASS 0.5 for the full schema (type_ramp, colors, gradients, spacing, shape, density, elevation, mood_modifiers). The renderer reads this for every fontSize, padding, color, and radius — without it, the output reverts to generic defaults and the mockup won't look like the target app. Fill ALL required keys; partial profiles are rejected by PASS 3 validation.Theme colors:
analysis.brand_colors[0] as primary_gradient_startanalysis.brand_colors[1] (or a darker shade of [0]) as primary_gradient_endanalysis.brand_colors[2] (or the warmest of the palette) as accent_colormesh_colors should be 3 colors picked from brand_colors, ordered for visual flowValidate before writing:
screenshots.background layer first, at least 1 text layer, and at least 1 device layer.screen_ui is detailed (≥6 elements: status_bar, nav_bar, content elements, bottom_nav).text layer where x + width > 380.analysis.project_assets or be analysis.app_icon_url.featureGraphic block): exactly ONE entry. Has background first, ≥1 text, ≥1 device. Every device layer has a non-empty source_slot matching one of the 6 screenshots[].name values verbatim. Headline ≤2 lines, ≤4 words total, ≤18 chars per line. No text layer where x + width > 502. See PASS 4 in PROMPT.md for archetype y-values and complete validation rules.APP_ROOT is whatever Step 1 wrote to ${CLAUDE_PLUGIN_DATA}/scaffold.env (~/.snap-mock-renderer in standalone mode, the user's existing project root in in-place mode).
Write to ${APP_ROOT}/public/briefs.json.tmp first, then mv to ${APP_ROOT}/public/briefs.json. POSIX rename is atomic on the same filesystem and prevents a mid-write race with fetch('/briefs.json').
If ${APP_ROOT}/public/briefs.json already exists with a different schema (no version field, or a generatedAt that's not ISO 8601), write to ${APP_ROOT}/public/briefs.claude.json instead and tell the user. The standalone renderer ships a placeholder briefs.json (with appName: "Placeholder") — overwrite that freely.
Remember the generatedAt value — Step 6 needs it.
Run bash ${CLAUDE_PLUGIN_ROOT}/skills/mockup-export/scripts/start-dev.sh. The script reads APP_ROOT from scaffold.env automatically (no need to cd into it first).
Then bash ${CLAUDE_PLUGIN_ROOT}/skills/mockup-export/scripts/wait-for-server.sh to block until the server returns 200 (timeout 30s).
If wait fails, tail -50 ${CLAUDE_PLUGIN_DATA}/dev.log and tell the user what went wrong.
The export script lives at ${APP_ROOT}/scripts/export-screenshots.mjs (so it can resolve playwright from the app's own node_modules/). Run it from APP_ROOT:
APP_ROOT="$(grep '^APP_ROOT=' "$CLAUDE_PLUGIN_DATA/scaffold.env" | cut -d= -f2-)"
USER_CWD="$(pwd)"
cd "$APP_ROOT"
BRIEFS_GENERATED_AT="<the ISO timestamp from Step 4>" \
OUT_DIR="$USER_CWD/mockups" \
node scripts/export-screenshots.mjs
(OUT_DIR lands the PNGs at the user's original cwd, not inside the renderer.)
The script:
${CLAUDE_PLUGIN_DATA}/dev.pid line 2.briefs.json generatedAt matches BRIEFS_GENERATED_AT before clicking.[data-action="export-all-zip"], captures the zip via page.waitForEvent('download').slot-01.png … slot-06.png AND feature-graphic.png (1024×500).Print the absolute path to ./mockups/ and a list of the 7 files: slot-01.png … slot-06.png (1080×1920 each) plus feature-graphic.png (1024×500). Don't tear down the dev server — the SessionEnd hook handles that automatically.
start-dev.sh falls through to 3137 automatically. If both are busy, kill the offender: lsof -ti:3000 | xargs kill.scaffold.sh runs npx playwright install chromium automatically. Retry if it failed (network).briefs.claude.json instead and tells the user.templates/toolbar-patch-instructions.md.analyze-local.sh only matches files with .dart, .ts, .tsx, .js, .jsx, .kt, .java, .swift extensions and a screen|page|view|activity|fragment substring. Build artifacts (.cmake, .json from CodeGen, .storyboard) are filtered.briefs.json has a complete style_profile block with all 8 sub-objects (type_ramp, colors, gradients, spacing, shape, density, elevation, mood_modifiers). If missing or thin, re-synthesize after explicitly reading 2–3 screen source files PLUS any theme file. The source_context truncation in analysis.json is too short for full StyleSheet.create blocks — read the actual files via the manifest.font_size / corner_radius / fill values in screenshots[].layers[] actually match style_profile tokens. Common bug: synthesizer extracted the profile correctly but reverted to defaults when writing layers. Re-run PASS 3 validation rules 12–14.Anthropic shipped Claude Design (https://claude.ai/design) on 2026-04-17. It generates polished HTML/CSS designs from briefs but has no public API and exports to PDF/PPTX/HTML, not PNG. So it can't replace the Konva pipeline directly.
One-time use case (recommended for high-value clients): spend ~20 prompts on Claude Design to generate a reference layout for one slot of the app, export the HTML, then mine it for exact gradient stops, type ramp, nav icon SVGs, and shadow values. Bake those constants into the templates as design-system overrides via a future --design-system <claude-design-export.html> flag (not yet implemented).
Provides UI/UX resources: 50+ styles, color palettes, font pairings, guidelines, charts for web/mobile across React, Next.js, Vue, Svelte, Tailwind, React Native, Flutter. Aids planning, building, reviewing interfaces.
Fetches up-to-date documentation from Context7 for libraries and frameworks like React, Next.js, Prisma. Use for setup questions, API references, and code examples.
npx claudepluginhub arslan8122/snap-mock-skill --plugin snap-mock-skill