skills/parthjadhav/app-store-screenshots/SKILL.md
Use when building App Store screenshot pages, generating exportable marketing screenshots for iOS apps, or creating programmatic screenshot generators with Next.js. Triggers on app store, screenshots, marketing assets, html-to-image, phone mockup.
npx skillsauth add aiskillstore/marketplace app-store-screenshotsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Build a Next.js page that renders iOS App Store screenshots as advertisements (not UI showcases) and exports them via html-to-image at Apple's required resolutions. Screenshots are the single most important conversion asset on the App Store.
Screenshots are advertisements, not documentation. Every screenshot sells one idea. If you're showing UI, you're doing it wrong — you're selling a feeling, an outcome, or killing a pain point.
Before writing ANY code, ask the user all of these. Do not proceed until you have answers:
Based on the user's style direction, brand colors, and app aesthetic, decide:
IMPORTANT: If the user gives additional instructions at any point during the process, follow them. User instructions always override skill defaults.
Check what's available, use this priority: bun > pnpm > yarn > npm
# Check in order
which bun && echo "use bun" || which pnpm && echo "use pnpm" || which yarn && echo "use yarn" || echo "use npm"
# With bun:
bunx create-next-app@latest . --typescript --tailwind --app --src-dir --no-eslint --import-alias "@/*"
bun add html-to-image
# With pnpm:
pnpx create-next-app@latest . --typescript --tailwind --app --src-dir --no-eslint --import-alias "@/*"
pnpm add html-to-image
# With yarn:
yarn create next-app . --typescript --tailwind --app --src-dir --no-eslint --import-alias "@/*"
yarn add html-to-image
# With npm:
npx create-next-app@latest . --typescript --tailwind --app --src-dir --no-eslint --import-alias "@/*"
npm install html-to-image
The skill includes a pre-measured iPhone mockup at mockup.png (co-located with this SKILL.md). Copy it to the project's public/ directory. The mockup file is in the same directory as this skill file.
project/
├── public/
│ ├── mockup.png # Phone frame (included with skill)
│ ├── app-icon.png # User's app icon
│ └── screenshots/ # User's app screenshots
│ ├── home.png
│ ├── feature-1.png
│ └── ...
├── src/app/
│ ├── layout.tsx # Font setup
│ └── page.tsx # The screenshot generator (single file)
└── package.json
The entire generator is a single page.tsx file. No routing, no extra layouts, no API routes.
// src/app/layout.tsx
import { YourFont } from "next/font/google"; // Use whatever font the user specified
const font = YourFont({ subsets: ["latin"] });
export default function Layout({ children }: { children: React.ReactNode }) {
return <html><body className={font.className}>{children}</body></html>;
}
Adapt this framework to the user's requested slide count. Not all slots are required — pick what fits:
| Slot | Purpose | Notes | |------|---------|-------| | #1 | Hero / Main Benefit | App icon + tagline + home screen. This is the ONLY one most people see. | | #2 | Differentiator | What makes this app unique vs competitors | | #3 | Ecosystem | Widgets, extensions, watch — beyond the main app. Skip if N/A. | | #4+ | Core Features | One feature per slide, most important first | | 2nd to last | Trust Signal | Identity/craft — "made for people who [X]" | | Last | More Features | Pills listing extras + coming soon. Skip if few features. |
Rules:
Get all headlines approved before building layouts. Bad copy ruins good design.
<br />.| Type | What it does | Example | |------|-------------|---------| | Paint a moment | You picture yourself doing it | "Check your coffee without opening the app." | | State an outcome | What your life looks like after | "A home for every coffee you buy." | | Kill a pain | Name a problem and destroy it | "Never waste a great bag of coffee." |
page.tsx
├── Constants (W, H, SIZES, design tokens from user's brand)
├── Phone component (mockup with screen overlay)
├── Caption component (label + headline)
├── Decorative components (blobs, glows, shapes — based on style direction)
├── Screenshot1..N components (one per slide)
├── SCREENSHOTS array (registry)
├── ScreenshotPreview (ResizeObserver scaling + hover export)
└── ScreenshotsPage (grid + toolbar + export logic)
const SIZES = [
{ label: '6.9"', w: 1320, h: 2868 },
{ label: '6.5"', w: 1284, h: 2778 },
{ label: '6.3"', w: 1206, h: 2622 },
{ label: '6.1"', w: 1125, h: 2436 },
] as const;
Design at the LARGEST size (1320x2868) and scale down for export.
Each screenshot is designed at full resolution (1320x2868px). Two copies exist:
transform: scale() via ResizeObserver to fit a grid cardposition: absolute; left: -9999px at true resolutionThe included mockup.png has these pre-measured values:
const MK_W = 1022; // mockup image width
const MK_H = 2082; // mockup image height
const SC_L = (52 / MK_W) * 100; // screen left offset %
const SC_T = (46 / MK_H) * 100; // screen top offset %
const SC_W = (918 / MK_W) * 100; // screen width %
const SC_H = (1990 / MK_H) * 100; // screen height %
const SC_RX = (126 / 918) * 100; // border-radius x %
const SC_RY = (126 / 1990) * 100; // border-radius y %
function Phone({ src, alt, style, className = "" }: {
src: string; alt: string; style?: React.CSSProperties; className?: string;
}) {
return (
<div className={`relative ${className}`}
style={{ aspectRatio: `${MK_W}/${MK_H}`, ...style }}>
<img src="/mockup.png" alt=""
className="block w-full h-full" draggable={false} />
<div className="absolute z-10 overflow-hidden"
style={{
left: `${SC_L}%`, top: `${SC_T}%`,
width: `${SC_W}%`, height: `${SC_H}%`,
borderRadius: `${SC_RX}% / ${SC_RY}%`,
}}>
<img src={src} alt={alt}
className="block w-full h-full object-cover object-top"
draggable={false} />
</div>
</div>
);
}
All sizing relative to canvas width W:
| Element | Size | Weight | Line Height |
|---------|------|--------|-------------|
| Category label | W * 0.028 | 600 (semibold) | default |
| Headline | W * 0.09 to W * 0.1 | 700 (bold) | 1.0 |
| Hero headline | W * 0.1 | 700 (bold) | 0.92 |
Vary across slides — NEVER use the same layout twice in a row:
Centered phone (hero, single-feature):
bottom: 0, width: "82-86%", translateX(-50%) translateY(12-14%)
Two phones layered (comparison):
Back: left: "-8%", width: "65%", rotate(-4deg), opacity: 0.55
Front: right: "-4%", width: "82%", translateY(10%)
Phone + floating elements (only if user provided component PNGs):
Cards should NOT block the phone's main content.
Position at edges, slight rotation (2-5deg), drop shadows.
If distracting, push partially off-screen or make smaller.
Dark/contrast background with app icon, headline ("And so much more."), and feature pills. Can include a "Coming Soon" section with dimmer pills.
html2canvas breaks on CSS filters, gradients, drop-shadow, backdrop-filter, and complex clipping. html-to-image uses native browser SVG serialization — handles all CSS faithfully.
import { toPng } from "html-to-image";
// Before capture: move element on-screen
el.style.left = "0px";
el.style.opacity = "1";
el.style.zIndex = "-1";
const opts = { width: W, height: H, pixelRatio: 1, cacheBust: true };
// CRITICAL: Double-call trick — first warms up fonts/images, second produces clean output
await toPng(el, opts);
const dataUrl = await toPng(el, opts);
// After capture: move back off-screen
el.style.left = "-9999px";
el.style.opacity = "";
el.style.zIndex = "";
toPng() loads fonts/images lazily. Second produces clean output. Without this, exports are blank.left: 0 before calling toPng.position: absolute; left: -9999px (not fixed).fontFamily on the offscreen container.01-hero-1320x2868.png, 02-freshness-1320x2868.png, etc. Use String(index + 1).padStart(2, "0").| Mistake | Fix | |---------|-----| | All slides look the same | Vary phone position (center, left, right, two-phone, no-phone) | | Decorative elements invisible | Increase size and opacity — better too visible than invisible | | Copy is too complex | "One second at arm's length" test | | Floating elements block the phone | Move off-screen edges or above the phone | | Plain white/black background | Use gradients — even subtle ones add depth | | Too cluttered | Remove floating elements, simplify to phone + caption | | Too simple/empty | Add larger decorative elements, floating items at edges | | Headlines use "and" | Split into two slides or pick one idea | | No visual contrast across slides | Mix light and dark backgrounds | | Export is blank | Use double-call trick; move element on-screen before capture |
development
Apple Human Interface Guidelines for content display components. Use this skill when the user asks about charts component, collection view, image view, web view, color well, image well, activity view, lockup, data visualization, content display, displaying images, rendering web content, color pickers, or presenting collections of items in Apple apps. Also use when the user says how should I display charts, what's the best way to show images, should I use a web view, how do I build a grid of items, what component shows media, or how do I present a share sheet. Cross-references: hig-foundations for color/typography/accessibility, hig-patterns for data visualization patterns, hig-components-layout for structural containers, hig-platforms for platform-specific component behavior.
tools
Automate HelpDesk tasks via Rube MCP (Composio): list tickets, manage views, use canned responses, and configure custom fields. Always search tools first for current schemas.
testing
Expert Haskell engineer specializing in advanced type systems, pure functional design, and high-reliability software. Use PROACTIVELY for type-level programming, concurrency, and architecture guidance.
tools
GraphQL gives clients exactly the data they need - no more, no less. One endpoint, typed schema, introspection. But the flexibility that makes it powerful also makes it dangerous. Without proper controls, clients can craft queries that bring down your server. This skill covers schema design, resolvers, DataLoader for N+1 prevention, federation for microservices, and client integration with Apollo/urql. Key insight: GraphQL is a contract. The schema is the API documentation. Design it carefully.