[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-6487ac55-6608-45d9-95b9-b381d04ab74a":3,"$flRSWNRQEoFBc__YJJBIG0NfadwlbcuQJQdkQaScdR0M":43},{"id":4,"title":5,"description":6,"categoryId":7,"moduleId":8,"tags":9,"prompt":10,"icon":11,"source":12,"sourceUrl":13,"authorId":14,"authorName":15,"isPublic":16,"stars":17,"runs":18,"createdAt":19,"updatedAt":19,"module":20,"category":27,"packages":34},"6487ac55-6608-45d9-95b9-b381d04ab74a","screenshots","使用Playwright生成您的应用营销截图。当用户需要为Product Hunt、社交媒体、着陆页或文档创建截图时使用。","cat_coding_review","mod_coding","sickn33,coding","---\nname: screenshots\ndescription: \"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.\"\nrisk: safe\nsource: \"https:\u002F\u002Fgithub.com\u002FShpigford\u002Fskills\u002Ftree\u002Fmain\u002Fscreenshots\"\ndate_added: \"2026-02-27\"\n---\n\n# Screenshots\n\nGenerate marketing-quality screenshots of your app using Playwright directly. Screenshots are captured at true HiDPI (2x retina) resolution using `deviceScaleFactor: 2`.\n\n## When to Use This Skill\n\nUse this skill when:\n- User wants to create screenshots for Product Hunt\n- Creating screenshots for social media\n- Generating images for landing pages\n- Creating documentation screenshots\n- User requests marketing-quality app screenshots\n\n## Prerequisites\n\nPlaywright must be available. Check for it:\n```bash\nnpx playwright --version 2>\u002Fdev\u002Fnull || npm ls playwright 2>\u002Fdev\u002Fnull | grep playwright\n```\n\nIf not found, inform the user:\n> Playwright is required. Install it with: `npm install -D playwright` or `npm install -D @playwright\u002Ftest`\n\n## Step 1: Determine App URL\n\nIf `$1` is provided, use it as the app URL.\n\nIf no URL is provided:\n1. Check if a dev server is likely running by looking for `package.json` scripts\n2. Use `AskUserQuestion` to ask the user for the URL or offer to help start the dev server\n\nCommon default URLs to suggest:\n- `http:\u002F\u002Flocalhost:3000` (Next.js, Create React App, Rails)\n- `http:\u002F\u002Flocalhost:5173` (Vite)\n- `http:\u002F\u002Flocalhost:4000` (Phoenix)\n- `http:\u002F\u002Flocalhost:8080` (Vue CLI, generic)\n\n## Step 2: Gather Requirements\n\nUse `AskUserQuestion` with the following questions:\n\n**Question 1: Screenshot count**\n- Header: \"Count\"\n- Question: \"How many screenshots do you need?\"\n- Options:\n  - \"3-5\" - Quick set of key features\n  - \"5-10\" - Comprehensive feature coverage\n  - \"10+\" - Full marketing suite\n\n**Question 2: Purpose**\n- Header: \"Purpose\"\n- Question: \"What will these screenshots be used for?\"\n- Options:\n  - \"Product Hunt\" - Hero shots and feature highlights\n  - \"Social media\" - Eye-catching feature demos\n  - \"Landing page\" - Marketing sections and benefits\n  - \"Documentation\" - UI reference and tutorials\n\n**Question 3: Authentication**\n- Header: \"Auth\"\n- Question: \"Does the app require login to access the features you want to screenshot?\"\n- Options:\n  - \"No login needed\" - Public pages only\n  - \"Yes, I'll provide credentials\" - Need to log in first\n\nIf user selects \"Yes, I'll provide credentials\", ask follow-up questions:\n- \"What is the login page URL?\" (e.g., `\u002Flogin`, `\u002Fsign-in`)\n- \"What is the email\u002Fusername?\"\n- \"What is the password?\"\n\nThe script will automatically detect login form fields using Playwright's smart locators.\n\n## Step 3: Analyze Codebase for Features\n\nThoroughly explore the codebase to understand the app and identify screenshot opportunities.\n\n### 3.1: Read Documentation First\n\n**Always start by reading these files** to understand what the app does:\n\n1. **README.md** (and any README files in subdirectories) - Read the full README to understand:\n   - What the app is and what problem it solves\n   - Key features and capabilities\n   - Screenshots or feature descriptions already documented\n\n2. **CHANGELOG.md** or **HISTORY.md** - Recent features worth highlighting\n\n3. **docs\u002F** directory - Any additional documentation about features\n\n### 3.2: Analyze Routes to Find Pages\n\nRead the routing configuration to discover all available pages:\n\n| Framework | File to Read | What to Look For |\n|-----------|--------------|------------------|\n| **Next.js App Router** | `app\u002F` directory structure | Each folder with `page.tsx` is a route |\n| **Next.js Pages Router** | `pages\u002F` directory | Each file is a route |\n| **Rails** | `config\u002Froutes.rb` | Read the entire file for all routes |\n| **React Router** | Search for `createBrowserRouter` or `\u003CRoute` | Route definitions with paths |\n| **Vue Router** | `src\u002Frouter\u002Findex.js` or `router.js` | Routes array with path definitions |\n| **SvelteKit** | `src\u002Froutes\u002F` directory | Each folder with `+page.svelte` is a route |\n| **Remix** | `app\u002Froutes\u002F` directory | File-based routing |\n| **Laravel** | `routes\u002Fweb.php` | Route definitions |\n| **Django** | `urls.py` files | URL patterns |\n| **Express** | Search for `app.get`, `router.get` | Route handlers |\n\n**Important**: Actually read these files, don't just check if they exist. The route definitions tell you what pages are available for screenshots.\n\n### 3.3: Identify Key Components\n\nLook for components that represent screenshottable features:\n\n- Dashboard components\n- Feature sections with distinct UI\n- Forms and interactive inputs\n- Data visualizations (charts, graphs, tables)\n- Modals and dialogs\n- Navigation and sidebars\n- Settings panels\n- User profile sections\n\n### 3.4: Check for Marketing Assets\n\nLook for existing marketing content that hints at key features:\n- Landing page components (often in `components\u002Flanding\u002F` or `components\u002Fmarketing\u002F`)\n- Feature list components\n- Pricing tables\n- Testimonial sections\n\n### 3.5: Build Feature List\n\nCreate a comprehensive list of discovered features with:\n- Feature name (from README or component name)\n- URL path (from routes)\n- CSS selector to focus on (from component structure)\n- Required UI state (logged in, data populated, modal open, specific tab selected)\n\n## Step 4: Plan Screenshots with User\n\nPresent the discovered features to the user and ask them to confirm or modify the list.\n\nUse `AskUserQuestion`:\n- Header: \"Features\"\n- Question: \"I found these features in your codebase. Which would you like to screenshot?\"\n- Options: List 3-4 key features discovered, plus \"Let me pick specific ones\"\n\nIf user wants specific ones, ask follow-up questions to clarify exactly what to capture.\n\n## Step 5: Create Screenshots Directory\n\n```bash\nmkdir -p screenshots\n```\n\n## Step 6: Generate and Run Playwright Script\n\nCreate a Node.js script that uses Playwright with proper HiDPI settings. The script should:\n\n1. **Use `deviceScaleFactor: 2`** for true retina resolution\n2. **Set viewport to 1440x900** (produces 2880x1800 pixel images)\n3. **Handle authentication** if credentials were provided\n4. **Navigate to each page** and capture screenshots\n\n### Script Template\n\nWrite this script to a temporary file (e.g., `screenshot-script.mjs`) and execute it:\n\n```javascript\nimport { chromium } from 'playwright';\n\nconst BASE_URL = '[APP_URL]';\nconst SCREENSHOTS_DIR = '.\u002Fscreenshots';\n\n\u002F\u002F Authentication config (if needed)\nconst AUTH = {\n  needed: [true|false],\n  loginUrl: '[LOGIN_URL]',\n  email: '[EMAIL]',\n  password: '[PASSWORD]',\n};\n\n\u002F\u002F Screenshots to capture\nconst SCREENSHOTS = [\n  { name: '01-feature-name', url: '\u002Fpath', waitFor: '[optional-selector]' },\n  { name: '02-another-feature', url: '\u002Fanother-path' },\n  \u002F\u002F ... add all planned screenshots\n];\n\nasync function main() {\n  const browser = await chromium.launch();\n\n  \u002F\u002F Create context with HiDPI settings\n  const context = await browser.newContext({\n    viewport: { width: 1440, height: 900 },\n    deviceScaleFactor: 2,  \u002F\u002F This is the key for true retina screenshots\n  });\n\n  const page = await context.newPage();\n\n  \u002F\u002F Handle authentication if needed\n  if (AUTH.needed) {\n    console.log('Logging in...');\n    await page.goto(AUTH.loginUrl);\n\n    \u002F\u002F Smart login: try multiple common patterns for email\u002Fusername field\n    const emailField = page.locator([\n      'input[type=\"email\"]',\n      'input[name=\"email\"]',\n      'input[id=\"email\"]',\n      'input[placeholder*=\"email\" i]',\n      'input[name=\"username\"]',\n      'input[id=\"username\"]',\n      'input[type=\"text\"]',\n    ].join(', ')).first();\n    await emailField.fill(AUTH.email);\n\n    \u002F\u002F Smart login: try multiple common patterns for password field\n    const passwordField = page.locator([\n      'input[type=\"password\"]',\n      'input[name=\"password\"]',\n      'input[id=\"password\"]',\n    ].join(', ')).first();\n    await passwordField.fill(AUTH.password);\n\n    \u002F\u002F Smart login: try multiple common patterns for submit button\n    const submitButton = page.locator([\n      'button[type=\"submit\"]',\n      'input[type=\"submit\"]',\n      'button:has-text(\"Sign in\")',\n      'button:has-text(\"Log in\")',\n      'button:has-text(\"Login\")',\n      'button:has-text(\"Submit\")',\n    ].join(', ')).first();\n    await submitButton.click();\n\n    await page.waitForLoadState('networkidle');\n    console.log('Login complete');\n  }\n\n  \u002F\u002F Capture each screenshot\n  for (const shot of SCREENSHOTS) {\n    console.log(`Capturing: ${shot.name}`);\n    await page.goto(`${BASE_URL}${shot.url}`);\n    await page.waitForLoadState('networkidle');\n\n    \u002F\u002F Optional: wait for specific element\n    if (shot.waitFor) {\n      await page.waitForSelector(shot.waitFor);\n    }\n\n    \u002F\u002F Optional: perform actions before screenshot\n    if (shot.actions) {\n      for (const action of shot.actions) {\n        if (action.click) await page.click(action.click);\n        if (action.fill) await page.fill(action.fill.selector, action.fill.value);\n        if (action.wait) await page.waitForTimeout(action.wait);\n      }\n    }\n\n    await page.screenshot({\n      path: `${SCREENSHOTS_DIR}\u002F${shot.name}.png`,\n      fullPage: shot.fullPage || false,\n    });\n    console.log(`  Saved: ${shot.name}.png`);\n  }\n\n  await browser.close();\n  console.log('Done!');\n}\n\nmain().catch(console.error);\n```\n\n### Running the Script\n\n```bash\nnode screenshot-script.mjs\n```\n\nAfter running, clean up the temporary script:\n```bash\nrm screenshot-script.mjs\n```\n\n## Step 7: Advanced Screenshot Options\n\n### Element-Focused Screenshots\n\nTo screenshot a specific element instead of the full viewport:\n\n```javascript\nconst element = await page.locator('[CSS_SELECTOR]');\nawait element.screenshot({ path: `${SCREENSHOTS_DIR}\u002Felement.png` });\n```\n\n### Full Page Screenshots\n\nFor scrollable content, capture the entire page:\n\n```javascript\nawait page.screenshot({\n  path: `${SCREENSHOTS_DIR}\u002Ffull-page.png`,\n  fullPage: true\n});\n```\n\n### Waiting for Animations\n\nIf the page has animations, wait for them to complete:\n\n```javascript\nawait page.waitForTimeout(500); \u002F\u002F Wait 500ms for animations\n```\n\n### Clicking Elements Before Screenshot\n\nTo capture a modal, dropdown, or hover state:\n\n```javascript\nawait page.click('button.open-modal');\nawait page.waitForSelector('.modal-content');\nawait page.screenshot({ path: `${SCREENSHOTS_DIR}\u002Fmodal.png` });\n```\n\n### Dark Mode Screenshots\n\nIf the app supports dark mode:\n\n```javascript\n\u002F\u002F Set dark mode preference\nconst context = await browser.newContext({\n  viewport: { width: 1440, height: 900 },\n  deviceScaleFactor: 2,\n  colorScheme: 'dark',\n});\n```\n\n## Step 8: File Naming Convention\n\nUse descriptive, kebab-case filenames with numeric prefixes for ordering:\n\n| Feature | Filename |\n|---------|----------|\n| Dashboard overview | `01-dashboard-overview.png` |\n| Link management | `02-link-inbox.png` |\n| Edition editor | `03-edition-editor.png` |\n| Analytics | `04-analytics.png` |\n| Settings | `05-settings.png` |\n\n## Step 9: Verify and Summarize\n\nAfter capturing all screenshots, verify the results:\n\n```bash\nls -la screenshots\u002F*.png\nsips -g pixelWidth -g pixelHeight screenshots\u002F*.png 2>\u002Fdev\u002Fnull || file screenshots\u002F*.png\n```\n\nProvide a summary to the user:\n\n1. List all generated files with their paths\n2. Confirm the resolution (should be 2880x1800 for 2x retina at 1440x900 viewport)\n3. Mention total file sizes\n4. Suggest any follow-up actions\n\nExample output:\n```\nGenerated 5 marketing screenshots:\n\nscreenshots\u002F\n├── 01-dashboard-overview.png (1.2 MB, 2880x1800 @ 2x)\n├── 02-link-inbox.png (456 KB, 2880x1800 @ 2x)\n├── 03-edition-editor.png (890 KB, 2880x1800 @ 2x)\n├── 04-analytics.png (567 KB, 2880x1800 @ 2x)\n└── 05-settings.png (234 KB, 2880x1800 @ 2x)\n\nAll screenshots are true retina-quality (2x deviceScaleFactor) and ready for marketing use.\n```\n\n## Error Handling\n\n- **Playwright not found**: Suggest `npm install -D playwright`\n- **Page not loading**: Check if the dev server is running, suggest starting it\n- **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.\n- **Element not found**: Verify the CSS selector, offer to take a full page screenshot instead\n- **Screenshot failed**: Check disk space, verify write permissions to screenshots directory\n\n## Tips for Best Results\n\n1. **Clean UI state**: Use demo\u002Fseed data for realistic content\n2. **Consistent sizing**: Use the same viewport for all screenshots\n3. **Wait for content**: Use `waitForLoadState('networkidle')` to ensure all content loads\n4. **Hide dev tools**: Ensure no browser extensions or dev overlays are visible\n5. **Dark mode variants**: Consider capturing both light and dark mode if supported\n\n## Limitations\n- Use this skill only when the task clearly matches the scope described above.\n- Do not treat the output as a substitute for environment-specific validation, testing, or expert review.\n- Stop and ask for clarification if required inputs, permissions, safety boundaries, or success criteria are missing.\n","","imported","https:\u002F\u002Fgithub.com\u002Fsickn33\u002Fantigravity-awesome-skills","user_system_seed","SkillOPIC",true,202,1690,"2026-05-16 13:38:02",{"id":8,"name":21,"slug":22,"icon":23,"description":24,"sort":25,"createdAt":26},"编程开发","coding","mdi-code-braces","代码生成、调试、审查，提升开发效率",2,"2026-05-16 12:53:40",{"id":7,"name":28,"slug":29,"icon":30,"description":31,"moduleId":8,"sort":32,"skillCount":33,"createdAt":26},"代码审查","review","mdi-magnify-scan","代码质量分析、安全审查",4,145,[35],{"id":36,"skillId":4,"version":37,"fileName":38,"fileSize":39,"filePath":40,"fileHash":41,"manifest":42,"createdAt":19},"b14dfed8-8e47-4412-9331-58b8be2082b0","1.0.0","screenshots.zip",5191,"uploads\u002Fskills\u002F6487ac55-6608-45d9-95b9-b381d04ab74a\u002Fscreenshots.zip","0b4d64a853b8852a57c7e8a2fedf73c8874e7366b4af323c8c48984ad4c3f25e","[{\"path\":\"SKILL.md\",\"isDirectory\":false,\"size\":13123}]",{"code":44,"message":45,"data":46},200,"success",{"items":47,"stats":48,"page":51},[],{"averageRating":49,"totalRatings":49,"ratingCounts":50},0,[49,49,49,49,49],{"limit":52,"offset":49,"hasMore":53,"nextOffset":52,"ratedOnly":16},15,false]