Generate marketing screenshots of your app using Playwright. Use when the user wants to create screenshots for Product Hunt, social media, landing pages, or documentation.
npx mdskills install Shpigford/screenshots@Shpigford? Sign in with GitHub to claim this listing.Comprehensive instructions for generating marketing screenshots with intelligent framework detection and retina support
1---2name: screenshots3argument-hint: [url]4description: Generate marketing screenshots of your app using Playwright. Use when the user wants to create screenshots for Product Hunt, social media, landing pages, or documentation.5allowed-tools: Bash(npx *), Bash(node *), Bash(mkdir *), Bash(ls *), Bash(rm *), Bash(sips *)6context: fork7metadata:8 author: Shpigford9 version: "1.0"10---1112Generate marketing-quality screenshots of your app using Playwright directly. Screenshots are captured at true HiDPI (2x retina) resolution using `deviceScaleFactor: 2`.1314## Prerequisites1516Playwright must be available. Check for it:17```bash18npx playwright --version 2>/dev/null || npm ls playwright 2>/dev/null | grep playwright19```2021If not found, inform the user:22> Playwright is required. Install it with: `npm install -D playwright` or `npm install -D @playwright/test`2324## Step 1: Determine App URL2526If `$1` is provided, use it as the app URL.2728If no URL is provided:291. Check if a dev server is likely running by looking for `package.json` scripts302. Use `AskUserQuestion` to ask the user for the URL or offer to help start the dev server3132Common default URLs to suggest:33- `http://localhost:3000` (Next.js, Create React App, Rails)34- `http://localhost:5173` (Vite)35- `http://localhost:4000` (Phoenix)36- `http://localhost:8080` (Vue CLI, generic)3738## Step 2: Gather Requirements3940Use `AskUserQuestion` with the following questions:4142**Question 1: Screenshot count**43- Header: "Count"44- Question: "How many screenshots do you need?"45- Options:46 - "3-5" - Quick set of key features47 - "5-10" - Comprehensive feature coverage48 - "10+" - Full marketing suite4950**Question 2: Purpose**51- Header: "Purpose"52- Question: "What will these screenshots be used for?"53- Options:54 - "Product Hunt" - Hero shots and feature highlights55 - "Social media" - Eye-catching feature demos56 - "Landing page" - Marketing sections and benefits57 - "Documentation" - UI reference and tutorials5859**Question 3: Authentication**60- Header: "Auth"61- Question: "Does the app require login to access the features you want to screenshot?"62- Options:63 - "No login needed" - Public pages only64 - "Yes, I'll provide credentials" - Need to log in first6566If user selects "Yes, I'll provide credentials", ask follow-up questions:67- "What is the login page URL?" (e.g., `/login`, `/sign-in`)68- "What is the email/username?"69- "What is the password?"7071The script will automatically detect login form fields using Playwright's smart locators.7273## Step 3: Analyze Codebase for Features7475Thoroughly explore the codebase to understand the app and identify screenshot opportunities.7677### 3.1: Read Documentation First7879**Always start by reading these files** to understand what the app does:80811. **README.md** (and any README files in subdirectories) - Read the full README to understand:82 - What the app is and what problem it solves83 - Key features and capabilities84 - Screenshots or feature descriptions already documented85862. **CHANGELOG.md** or **HISTORY.md** - Recent features worth highlighting87883. **docs/** directory - Any additional documentation about features8990### 3.2: Analyze Routes to Find Pages9192Read the routing configuration to discover all available pages:9394| Framework | File to Read | What to Look For |95|-----------|--------------|------------------|96| **Next.js App Router** | `app/` directory structure | Each folder with `page.tsx` is a route |97| **Next.js Pages Router** | `pages/` directory | Each file is a route |98| **Rails** | `config/routes.rb` | Read the entire file for all routes |99| **React Router** | Search for `createBrowserRouter` or `<Route` | Route definitions with paths |100| **Vue Router** | `src/router/index.js` or `router.js` | Routes array with path definitions |101| **SvelteKit** | `src/routes/` directory | Each folder with `+page.svelte` is a route |102| **Remix** | `app/routes/` directory | File-based routing |103| **Laravel** | `routes/web.php` | Route definitions |104| **Django** | `urls.py` files | URL patterns |105| **Express** | Search for `app.get`, `router.get` | Route handlers |106107**Important**: Actually read these files, don't just check if they exist. The route definitions tell you what pages are available for screenshots.108109### 3.3: Identify Key Components110111Look for components that represent screenshottable features:112113- Dashboard components114- Feature sections with distinct UI115- Forms and interactive inputs116- Data visualizations (charts, graphs, tables)117- Modals and dialogs118- Navigation and sidebars119- Settings panels120- User profile sections121122### 3.4: Check for Marketing Assets123124Look for existing marketing content that hints at key features:125- Landing page components (often in `components/landing/` or `components/marketing/`)126- Feature list components127- Pricing tables128- Testimonial sections129130### 3.5: Build Feature List131132Create a comprehensive list of discovered features with:133- Feature name (from README or component name)134- URL path (from routes)135- CSS selector to focus on (from component structure)136- Required UI state (logged in, data populated, modal open, specific tab selected)137138## Step 4: Plan Screenshots with User139140Present the discovered features to the user and ask them to confirm or modify the list.141142Use `AskUserQuestion`:143- Header: "Features"144- Question: "I found these features in your codebase. Which would you like to screenshot?"145- Options: List 3-4 key features discovered, plus "Let me pick specific ones"146147If user wants specific ones, ask follow-up questions to clarify exactly what to capture.148149## Step 5: Create Screenshots Directory150151```bash152mkdir -p screenshots153```154155## Step 6: Generate and Run Playwright Script156157Create a Node.js script that uses Playwright with proper HiDPI settings. The script should:1581591. **Use `deviceScaleFactor: 2`** for true retina resolution1602. **Set viewport to 1440x900** (produces 2880x1800 pixel images)1613. **Handle authentication** if credentials were provided1624. **Navigate to each page** and capture screenshots163164### Script Template165166Write this script to a temporary file (e.g., `screenshot-script.mjs`) and execute it:167168```javascript169import { chromium } from 'playwright';170171const BASE_URL = '[APP_URL]';172const SCREENSHOTS_DIR = './screenshots';173174// Authentication config (if needed)175const AUTH = {176 needed: [true|false],177 loginUrl: '[LOGIN_URL]',178 email: '[EMAIL]',179 password: '[PASSWORD]',180};181182// Screenshots to capture183const SCREENSHOTS = [184 { name: '01-feature-name', url: '/path', waitFor: '[optional-selector]' },185 { name: '02-another-feature', url: '/another-path' },186 // ... add all planned screenshots187];188189async function main() {190 const browser = await chromium.launch();191192 // Create context with HiDPI settings193 const context = await browser.newContext({194 viewport: { width: 1440, height: 900 },195 deviceScaleFactor: 2, // This is the key for true retina screenshots196 });197198 const page = await context.newPage();199200 // Handle authentication if needed201 if (AUTH.needed) {202 console.log('Logging in...');203 await page.goto(AUTH.loginUrl);204205 // Smart login: try multiple common patterns for email/username field206 const emailField = page.locator([207 'input[type="email"]',208 'input[name="email"]',209 'input[id="email"]',210 'input[placeholder*="email" i]',211 'input[name="username"]',212 'input[id="username"]',213 'input[type="text"]',214 ].join(', ')).first();215 await emailField.fill(AUTH.email);216217 // Smart login: try multiple common patterns for password field218 const passwordField = page.locator([219 'input[type="password"]',220 'input[name="password"]',221 'input[id="password"]',222 ].join(', ')).first();223 await passwordField.fill(AUTH.password);224225 // Smart login: try multiple common patterns for submit button226 const submitButton = page.locator([227 'button[type="submit"]',228 'input[type="submit"]',229 'button:has-text("Sign in")',230 'button:has-text("Log in")',231 'button:has-text("Login")',232 'button:has-text("Submit")',233 ].join(', ')).first();234 await submitButton.click();235236 await page.waitForLoadState('networkidle');237 console.log('Login complete');238 }239240 // Capture each screenshot241 for (const shot of SCREENSHOTS) {242 console.log(`Capturing: ${shot.name}`);243 await page.goto(`${BASE_URL}${shot.url}`);244 await page.waitForLoadState('networkidle');245246 // Optional: wait for specific element247 if (shot.waitFor) {248 await page.waitForSelector(shot.waitFor);249 }250251 // Optional: perform actions before screenshot252 if (shot.actions) {253 for (const action of shot.actions) {254 if (action.click) await page.click(action.click);255 if (action.fill) await page.fill(action.fill.selector, action.fill.value);256 if (action.wait) await page.waitForTimeout(action.wait);257 }258 }259260 await page.screenshot({261 path: `${SCREENSHOTS_DIR}/${shot.name}.png`,262 fullPage: shot.fullPage || false,263 });264 console.log(` Saved: ${shot.name}.png`);265 }266267 await browser.close();268 console.log('Done!');269}270271main().catch(console.error);272```273274### Running the Script275276```bash277node screenshot-script.mjs278```279280After running, clean up the temporary script:281```bash282rm screenshot-script.mjs283```284285## Step 7: Advanced Screenshot Options286287### Element-Focused Screenshots288289To screenshot a specific element instead of the full viewport:290291```javascript292const element = await page.locator('[CSS_SELECTOR]');293await element.screenshot({ path: `${SCREENSHOTS_DIR}/element.png` });294```295296### Full Page Screenshots297298For scrollable content, capture the entire page:299300```javascript301await page.screenshot({302 path: `${SCREENSHOTS_DIR}/full-page.png`,303 fullPage: true304});305```306307### Waiting for Animations308309If the page has animations, wait for them to complete:310311```javascript312await page.waitForTimeout(500); // Wait 500ms for animations313```314315### Clicking Elements Before Screenshot316317To capture a modal, dropdown, or hover state:318319```javascript320await page.click('button.open-modal');321await page.waitForSelector('.modal-content');322await page.screenshot({ path: `${SCREENSHOTS_DIR}/modal.png` });323```324325### Dark Mode Screenshots326327If the app supports dark mode:328329```javascript330// Set dark mode preference331const context = await browser.newContext({332 viewport: { width: 1440, height: 900 },333 deviceScaleFactor: 2,334 colorScheme: 'dark',335});336```337338## Step 8: File Naming Convention339340Use descriptive, kebab-case filenames with numeric prefixes for ordering:341342| Feature | Filename |343|---------|----------|344| Dashboard overview | `01-dashboard-overview.png` |345| Link management | `02-link-inbox.png` |346| Edition editor | `03-edition-editor.png` |347| Analytics | `04-analytics.png` |348| Settings | `05-settings.png` |349350## Step 9: Verify and Summarize351352After capturing all screenshots, verify the results:353354```bash355ls -la screenshots/*.png356sips -g pixelWidth -g pixelHeight screenshots/*.png 2>/dev/null || file screenshots/*.png357```358359Provide a summary to the user:3603611. List all generated files with their paths3622. Confirm the resolution (should be 2880x1800 for 2x retina at 1440x900 viewport)3633. Mention total file sizes3644. Suggest any follow-up actions365366Example output:367```368Generated 5 marketing screenshots:369370screenshots/371├── 01-dashboard-overview.png (1.2 MB, 2880x1800 @ 2x)372├── 02-link-inbox.png (456 KB, 2880x1800 @ 2x)373├── 03-edition-editor.png (890 KB, 2880x1800 @ 2x)374├── 04-analytics.png (567 KB, 2880x1800 @ 2x)375└── 05-settings.png (234 KB, 2880x1800 @ 2x)376377All screenshots are true retina-quality (2x deviceScaleFactor) and ready for marketing use.378```379380## Error Handling381382- **Playwright not found**: Suggest `npm install -D playwright`383- **Page not loading**: Check if the dev server is running, suggest starting it384- **Login failed**: The smart locators try common patterns but may fail on unusual login forms. If login fails, analyze the login page HTML to find the correct selectors and customize the script.385- **Element not found**: Verify the CSS selector, offer to take a full page screenshot instead386- **Screenshot failed**: Check disk space, verify write permissions to screenshots directory387388## Tips for Best Results3893901. **Clean UI state**: Use demo/seed data for realistic content3912. **Consistent sizing**: Use the same viewport for all screenshots3923. **Wait for content**: Use `waitForLoadState('networkidle')` to ensure all content loads3934. **Hide dev tools**: Ensure no browser extensions or dev overlays are visible3945. **Dark mode variants**: Consider capturing both light and dark mode if supported395
Full transparency — inspect the skill content before installing.