marketing-screenshots
Skill0 starsChanged 4 months agoMITView on GitHub
Generate marketing screenshots and GIF demos. Use with /marketing-screenshots.
In this repository42 other files it gives its agents.
- .claude/CLAUDE.mdCLAUDE.md
- content-rewriteSkill
- content-writeSkill
- core-auditSkill
- core-bootstrapSkill
- core-commitSkill
- core-explainSkill
- core-finalizeSkill
- core-orchestrateSkill
- core-pullSkill
- core-setupSkill
- core-updateSkill
- design-convertSkill
- design-shipSkill
- design-tokensSkill
- dev-inspectSkill
- dev-learnSkill
- dev-manualSkill
- dev-optimizeSkill
- dev-securitySkill
- dev-shipSkill
- dev-tweakSkill
- game-debugSkill
- game-optimizeSkill
- game-shipSkill
- game-tweakSkill
- marketing-contentSkill
- marketing-researchSkill
- project-addSkill
- project-appSkill
- project-memorySkill
- project-planSkill
- project-removeSkill
- project-researchSkill
- project-seedSkill
- project-syncSkill
- project-todoSkill
- project-tunnelSkill
- team-issuesSkill
- team-outsourceSkill
- team-reviewSkill
- team-verifySkill
The file
Show its rules and text
We split this skill into the rules it gives an agent
35 rules. About 0 are common, 17 are distinctive, and 18 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈17
Distinctive · estimate
This author's own choices. Worth a look.
18
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Distinctive: line 38
Check for running dev server:
- Distinctive: line 50
If HTTP 200 → use this URL.
- Distinctive: line 58
If nothing found → use AskUserQuestion:
- Very specific: line 68
Verify the URL is reachable via playwright-cli open [url].
- Distinctive: line 74
Use AskUserQuestion for each:
- Distinctive: line 106
If "Yes, I'll provide credentials" → follow-up AskUserQuestion:
- Distinctive: line 160
Read README.md (and any docs/) for feature descriptions and app purpose
- Distinctive: line 174
Check for theme support (dark mode toggle, colorScheme)
- Distinctive: line 221
If "I'll pick specific ones" → ask for numbers.
- Distinctive: line 223
After selection, assign numbered filenames:
- Very specific: line 250
Use playwright-cli run-code with deviceScaleFactor: 2 for true retina-quality screenshots (2880x1800px output from 1440x900 viewport).
- Very specific: line 374
If ogImage URL is available:
- Very specific: line 419
No Playwright equivalent — uses the built-in Claude-in-Chrome MCP tools against a live local Chrome.
- Very specific: line 422
Call tabs_context_mcp first.
- Very specific: line 424
Use gif_creator to record the interaction (e.g.
- Distinctive: line 429
If credentials provided → run 4.0 (login + state-save) once.
- Very specific: line 432
Run template from 4.1 (with storageState if auth, otherwise without)
- Distinctive: line 433
Wait for content to load (networkidle in template)
- Very specific: line 436
If dark mode requested → capture dark variant (suffix -dark)
- Very specific: line 437
If mobile requested → capture mobile variant (390×844 @3x, suffix -mobile)
- Very specific: line 438
If both dark AND mobile → capture mobile-dark variant (suffix -mobile-dark)
- Distinctive: line 440
If social cards chosen → per feature: run 4.2 (meta extraction first, fallback to render mock)
- Distinctive: line 441
If GIF demo chosen → run 4.3 once (Claude-in-Chrome, or skip cleanly if no live Chrome)
- Distinctive: line 476
If social cards generated → show social card summary:
- Very specific: line 490
If GIF demo generated → add one line: GIF: {feature-slug}-demo.gif (or GIF: skipped — no live Chrome connected)
- Distinctive: line 491
If purpose is "Product Hunt" → mention recommended image sizes (1270x760)
- Distinctive: line 492
If purpose is "Social media" → suggest cropping for platform-specific ratios
- Very specific: line 509
Solution: Start with /project-tunnel or provide a live URL.
- Very specific: line 519
Solution: Delete .project/auth-state.json and re-run PHASE 4.0.
- Very specific: line 524
Solution: Write the script to a temporary file and use playwright-cli run-code --filename=script.js.
- Very specific: line 536
Start dev servers (use /project-tunnel for that)
- Very specific: line 538
Commit .project/auth-state.json — must be gitignored
- Distinctive: line 544
Verify the app URL is reachable before starting
- Very specific: line 547
Use --filename flag for all screenshots (path to .project/screenshots/)
- Very specific: line 550
Delete .project/auth-state.json at the end of PHASE 5 if auth was used
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Screenshots
Generate marketing-quality screenshots of a web app using Playwright CLI, plus optional GIF demos via Claude-in-Chrome. Analyzes the codebase to discover routes and features, plans screenshots with the user, and captures them at HiDPI resolution.
HiDPI 2x screenshots stay on Playwright CLI (deviceScaleFactor: 2) — Claude-in-Chrome's computer screenshots are bound to physical display DPI and can't produce true retina output. GIF demos have no Playwright equivalent and use Claude-in-Chrome's gif_creator — see ../shared/CLAUDE-IN-CHROME.md.
Trigger: /marketing-screenshots or /marketing-screenshots [url]
Process
Phase tracking — first action of the skill: call TaskCreate with these 6 items (status pending), then use TaskUpdate to set each phase to in_progress at the start and completed at the end. If context compaction occurs, the task list stays visible — no risk of forgotten phases.
- PHASE 0: Determine App URL
- PHASE 1: Gather Requirements
- PHASE 2: Analyze Codebase for Features
- PHASE 3: Plan Screenshots with User
- PHASE 4: Capture Screenshots
- PHASE 5: Verify and Summarize
PHASE 0: Determine App URL
Todo: call
TaskCreatewith the 6 phase items (see above). Mark PHASE 0 →in_progressviaTaskUpdate.
If $1 provided → use as the app URL.
If no URL provided:
Check for running dev server:
grep -oE 'https://[a-z0-9-]+\.trycloudflare\.com' /tmp/cloudflared.log 2>/dev/null | head -1If found, verify:
curl -s -o /dev/null -w "%{http_code}" {tunnel_url}If HTTP 200 → use this URL.
Check localhost:
curl -s -o /dev/null -w "%{http_code}" http://localhost:3000 2>/dev/null- If nothing found → use AskUserQuestion:
- header: "App URL"
- question: "No running server found. What is the URL of the app?"
- options:
- label: "localhost:3000", description: "Next.js, Create React App, Rails"
- label: "localhost:5173", description: "Vite"
- label: "localhost:4000", description: "Phoenix"
- label: "localhost:8080", description: "Vue CLI, generic"
- multiSelect: false
- Verify the URL is reachable via
playwright-cli open [url]. If it fails → exit with message to start the dev server first (e.g./project-tunnel).
PHASE 1: Gather Requirements
Todo: mark PHASE 0 →
completed, PHASE 1 →in_progress.
Use AskUserQuestion for each:
Question 1: Count
- header: "Count"
- question: "How many screenshots do you need?"
- options:
- label: "3-5 (Recommended)", description: "Quick set of the most important features"
- label: "5-10", description: "Extensive feature coverage"
- label: "10+", description: "Full marketing suite"
- multiSelect: false
Question 2: Purpose
- header: "Purpose"
- question: "What will the screenshots be used for?"
- options:
- label: "Product Hunt", description: "Hero shots and feature highlights"
- label: "Social media", description: "Eye-catching feature demos"
- label: "Landing page", description: "Marketing sections and benefits"
- label: "Documentation", description: "UI reference and tutorials"
- multiSelect: false
Question 3: Authentication
- header: "Auth"
- question: "Does the app require login to access the features?"
- options:
- label: "No login needed (Recommended)", description: "Public pages only"
- label: "Yes, I'll provide credentials", description: "Need to log in first"
- multiSelect: false
If "Yes, I'll provide credentials" → follow-up AskUserQuestion:
- header: "Login Details"
- question: "What are the login credentials? (login URL, email, password)"
- options:
- label: "I'll type them below", description: "Provide credentials as free text"
Question 4: Dark Mode
- header: "Dark Mode"
- question: "Do you also want dark mode variants?"
- options:
- label: "No (Recommended)", description: "Light mode only"
- label: "Yes, both themes", description: "Light + dark variant per screenshot"
- multiSelect: false
Question 5: Social Cards
- header: "Social Cards"
- question: "Do you also want to generate social media preview cards?"
- options:
- label: "No (Recommended)", description: "Feature screenshots only"
- label: "OG (Facebook/LinkedIn)", description: "Open Graph preview — 1200×630"
- label: "Twitter card", description: "summary_large_image — 1200×600"
- label: "Both formats", description: "OG + Twitter card variants"
- multiSelect: false
Question 6: Mobile screenshots
- header: "Mobile screenshots"
- question: "Do you also want mobile viewport screenshots?"
- options:
- label: "No (Recommended)", description: "Desktop 1440×900 only"
- label: "Yes, iPhone portrait", description: "390×844 @3x — App Store and Product Hunt mobile"
- label: "Both", description: "Desktop + mobile per feature"
- multiSelect: false
Question 7: GIF demo
- header: "GIF demo"
- question: "Do you also want a short GIF demo of an interaction (e.g. a flow or feature in action)?"
- options:
- label: "No (Recommended)", description: "Static screenshots only"
- label: "Yes, record one", description: "Captures a short interaction via Claude-in-Chrome — requires a live local Chrome"
- multiSelect: false
PHASE 2: Analyze Codebase for Features
Todo: mark PHASE 1 →
completed, PHASE 2 →in_progress.
Research context check: Search for .project/thinking/*-marketing-research.md. If found: load the Audience and Recommendations sections. Use the recommended channels and audience as context when prioritizing features in step 3 — features that align with the research context get priority in the screenshot plan. This is a soft hint, not a blocking step.
Discover routes and screenshottable features inline using Glob, Grep, and Read.
- Read README.md (and any docs/) for feature descriptions and app purpose
- Find routing configuration:
- Next.js App Router: app/ directory (folders with page.tsx)
- Next.js Pages Router: pages/ directory
- React Router: search for createBrowserRouter or <Route
- Vue Router: src/router/index.js
- Rails: config/routes.rb
- Other: search for route definitions
- Identify key UI components:
- Dashboards, data tables, charts/graphs
- Forms, settings panels, user profiles
- Modals, dialogs, sidebars
- Landing/marketing pages
- Pricing tables, feature lists
- Check for theme support (dark mode toggle, colorScheme)
Return structured output:
FEATURES_START
| # | Feature | URL Path | Description | Required State |
| - | ------- | -------- | ----------- | -------------- |
| 1 | {name} | {path} | {what it shows} | {logged in / public / modal open / etc.} |
FEATURES_END
APP_DESCRIPTION: {1-2 sentence summary of what the app does}
THEME_SUPPORT: {yes/no}Parse the structured output from the agent.
PHASE 3: Plan Screenshots with User
Todo: mark PHASE 2 →
completed, PHASE 3 →in_progress.
Display discovered features:
FEATURES FOUND: {app description}
| # | Feature | URL | Description | Status |
| --- | ------- | --- | ----------- | ------ |
{features table from agent}
Suggested screenshots: {count based on PHASE 1 selection}
Use AskUserQuestion:
- header: "Feature Selection"
- question: "Which features do you want to screenshot? (numbers)"
- options:
- label: "All of the above (Recommended)", description: "Screenshots of all discovered features"
- label: "I'll pick specific ones", description: "I'll specify which numbers"
- multiSelect: false
If "I'll pick specific ones" → ask for numbers.
After selection, assign numbered filenames:
SCREENSHOT PLAN:
| # | File | Feature | URL |
| --- | --------------------- | --------- | ----- |
| 1 | 01-{feature-slug}.png | {feature} | {url} |
| 2 | 02-{feature-slug}.png | {feature} | {url} |
...
Create output directory:
mkdir -p .project/screenshotsPHASE 4: Capture Screenshots
Todo: mark PHASE 3 →
completed, PHASE 4 →in_progress.
Primary Method: HiDPI via playwright-cli run-code
Use playwright-cli run-code with deviceScaleFactor: 2 for true retina-quality screenshots (2880x1800px output from 1440x900 viewport).
4.0 Auth Setup (only if credentials were provided)
Login once, save state, reuse for all subsequent screenshots (including dark variants). See ../shared/PLAYWRIGHT.md → Use Cases: Auth State Persistence.
# 1. Open login page + grab refs
playwright-cli open {login_url}
playwright-cli snapshot # note refs for email/password/submit
# 2. Fill in via direct interactions
playwright-cli fill [email-ref] "{email}"
playwright-cli fill [password-ref] "{password}"
playwright-cli click [submit-ref]
playwright-cli run-code "async p => { await p.waitForLoadState('networkidle'); }"
# 3. Save storage state (cookies + localStorage)
playwright-cli state-save .project/auth-state.jsonOn login failure (smart-pattern matching fails): fall back to manual selectors via playwright-cli snapshot to identify refs, then retry step 2.
4.1 Screenshot Template
playwright-cli run-code "async page => {
const browser = page.context().browser();
const ctx = await browser.newContext({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 2,
// STORAGE_STATE (only if auth used):
// storageState: '.project/auth-state.json',
});
const p = await ctx.newPage();
await p.goto('{url}');
await p.waitForLoadState('networkidle');
// ACTIONS_BLOCK (if needed: click tabs, open modals, scroll)
// await p.click('{selector}');
// await p.waitForTimeout(500);
await p.screenshot({ path: '.project/screenshots/{filename}', fullPage: false });
await ctx.close();
return 'Captured: {filename}';
}"For dark mode variants (if requested) — add colorScheme: 'dark' to newContext. storageState stays the same, so auth is automatically reused.
playwright-cli run-code "async page => {
const browser = page.context().browser();
const ctx = await browser.newContext({
viewport: { width: 1440, height: 900 },
deviceScaleFactor: 2,
colorScheme: 'dark',
// storageState: '.project/auth-state.json', (if auth)
});
// ... same navigation + screenshot with '-dark' suffix
}"For mobile variants (if requested in PHASE 1) — iPhone 14 portrait, native 3x scale:
playwright-cli run-code "async page => {
const browser = page.context().browser();
const ctx = await browser.newContext({
viewport: { width: 390, height: 844 },
deviceScaleFactor: 3,
// storageState: '.project/auth-state.json', (if auth)
});
const p = await ctx.newPage();
await p.goto('{url}');
await p.waitForLoadState('networkidle');
await p.screenshot({ path: '.project/screenshots/{filename}-mobile.png', fullPage: false });
await ctx.close();
return 'Captured: {filename}-mobile.png';
}"For mobile + dark mode (if both chosen) — same mobile viewport with colorScheme: 'dark':
playwright-cli run-code "async page => {
const browser = page.context().browser();
const ctx = await browser.newContext({
viewport: { width: 390, height: 844 },
deviceScaleFactor: 3,
colorScheme: 'dark',
// storageState: '.project/auth-state.json', (if auth)
});
const p = await ctx.newPage();
await p.goto('{url}');
await p.waitForLoadState('networkidle');
await p.screenshot({ path: '.project/screenshots/{filename}-mobile-dark.png', fullPage: false });
await ctx.close();
return 'Captured: {filename}-mobile-dark.png';
}"4.2 Social Card Capture (only if chosen in PHASE 1)
Per selected feature/route, in order of precedence:
Strategy A — Meta extraction (preferred):
playwright-cli goto {url}
playwright-cli run-code "async p => { await p.waitForLoadState('networkidle'); }"
playwright-cli eval "() => ({
ogImage: document.querySelector('meta[property=\"og:image\"]')?.content,
ogTitle: document.querySelector('meta[property=\"og:title\"]')?.content,
twitterCard: document.querySelector('meta[name=\"twitter:card\"]')?.content,
twitterImage: document.querySelector('meta[name=\"twitter:image\"]')?.content,
})"If ogImage URL is available:
// playwright-cli run-code
async (page) => {
const res = await fetch("{ogImage}");
const buf = Buffer.from(await res.arrayBuffer());
require("fs").writeFileSync(
".project/screenshots/og-{feature-slug}.png",
buf,
);
return `Saved: og-{feature-slug}.png (${buf.length} bytes)`;
};Validation: file .project/screenshots/og-{feature}.png → dimensions 1200×630.
Strategy B — Page-render mock (fallback, if no OG image or URL not reachable):
// playwright-cli run-code
async (page) => {
const browser = page.context().browser();
const ctx = await browser.newContext({
viewport: { width: 1200, height: 630 }, // or 1200×600 for Twitter
deviceScaleFactor: 2,
});
const p = await ctx.newPage();
await p.goto("{url}");
await p.waitForLoadState("networkidle");
await p.screenshot({ path: ".project/screenshots/og-{feature-slug}.png" });
await ctx.close();
};Twitter variant: same with viewport: { width: 1200, height: 600 } and -tw- filename suffix.
Findings (reporting, non-blocking):
- OG meta tags missing on feature (no og:image, og:title)
- OG image dimensions incorrect — expected 1200×630
- Twitter card type missing (
meta[name="twitter:card"]not present)
4.3 GIF Capture (only if chosen in PHASE 1, Claude-in-Chrome)
No Playwright equivalent — uses the built-in Claude-in-Chrome MCP tools against a live local Chrome. See ../shared/CLAUDE-IN-CHROME.md for the full tool-loading ritual and command mapping.
- Load the tools in one
ToolSearchcall:select:mcp__claude-in-chrome__tabs_context_mcp,mcp__claude-in-chrome__navigate,mcp__claude-in-chrome__tabs_create_mcp,mcp__claude-in-chrome__gif_creator. - Call
tabs_context_mcpfirst. If no live browser is connected: skip GIF capture, note in the PHASE 5 summary asGIF: skipped — no live Chrome connected. navigateto the feature URL selected for the demo.- Use
gif_creatorto record the interaction (e.g. opening a modal, switching a tab, completing a short flow). - Save the resulting GIF to
.project/screenshots/{feature-slug}-demo.gif.
Execution Flow
- If credentials provided → run 4.0 (login + state-save) once.
- Per screenshot:
- Log:
Capturing {n}/{total}: {feature name}... - Run template from 4.1 (with
storageStateif auth, otherwise without) - Wait for content to load (networkidle in template)
- Execute pre-screenshot actions if needed (open modal, select tab, scroll)
- Capture screenshot
- If dark mode requested → capture dark variant (suffix
-dark) - If mobile requested → capture mobile variant (390×844 @3x, suffix
-mobile) - If both dark AND mobile → capture mobile-dark variant (suffix
-mobile-dark) - Log:
Saved: {filename}
- Log:
- If social cards chosen → per feature: run 4.2 (meta extraction first, fallback to render mock)
- If GIF demo chosen → run 4.3 once (Claude-in-Chrome, or skip cleanly if no live Chrome)
PHASE 5: Verify and Summarize
Todo: mark PHASE 4 →
completed, PHASE 5 →in_progress.
List generated files:
ls -la .project/screenshots/*.png 2>/dev/nullGet dimensions:
file .project/screenshots/*.pngDisplay summary:
SCREENSHOTS COMPLETE | # | File | Feature | Dimensions | |---|------|---------|------------| | 1 | 01-dashboard-overview.png | Dashboard | 2880x1800 | | 2 | 02-settings-panel.png | Settings | 2880x1800 | ... Total: {n} screenshots in .project/screenshots/ Desktop: HiDPI 2x retina — 2880×1800 output Mobile: {n} mobile shots — 1170×2532 output (390×844 @3x) ← only if chosen Purpose: {purpose from PHASE 1}If social cards generated → show social card summary:
SOCIAL CARDS | Feature | OG image | Twitter image | Source | |------------|-------------------------|----------------------------|-----------------| | homepage | og-homepage.png (1200×630) | tw-homepage.png (1200×600) | meta-extracted | | dashboard | og-dashboard.png | — | page-render | Findings: - [feature]: OG meta tags missing (og:image, og:title) - [feature]: OG image dimensions [actual] — expected 1200×630- If GIF demo generated → add one line:
GIF: {feature-slug}-demo.gif(orGIF: skipped — no live Chrome connected) - If purpose is "Product Hunt" → mention recommended image sizes (1270x760)
- If purpose is "Social media" → suggest cropping for platform-specific ratios
Todo: mark PHASE 5 →
completed.
Clean up auth state (only if 4.0 was run):
rm -f .project/auth-state.jsonState contains session tokens — always clean up at end of run.
Error Handling
App not reachable
Cause: Dev server not running.
Solution: Start with /project-tunnel or provide a live URL. The skill does not start servers itself.
Login failed
Cause: Smart login patterns don't match the app's login form.
Solution: playwright-cli snapshot on the login page → manually identify refs for email/password/submit → retry PHASE 4.0 with correct refs. On persistent failure: use run-code with explicit CSS selectors as fallback for the login + state-save step.
State file expired / invalid
Cause: auth-state.json contains expired cookies (session expired between runs).
Solution: Delete .project/auth-state.json and re-run PHASE 4.0. State is cleaned up in PHASE 5 anyway — always recreate when reusing between sessions.
run-code fails
Cause: Syntax error in the JavaScript argument (quote escaping).
Solution: Write the script to a temporary file and use playwright-cli run-code --filename=script.js.
Screenshot is blank or incomplete
Cause: Page not fully loaded before screenshot.
Solution: Increase wait time via page.waitForTimeout(2000) in the run-code script, or use page.waitForLoadState('networkidle') before capture.
Restrictions
This skill must NEVER:
- Install npm packages or dependencies
- Start dev servers (use
/project-tunnelfor that) - Store raw credentials (email/password) in files — only post-login storage state via
state-saveis allowed - Commit
.project/auth-state.json— must be gitignored - Overwrite existing screenshots without user confirmation
- Take screenshots without user-approved plan
This skill must ALWAYS:
- Verify the app URL is reachable before starting
- Present the screenshot plan for user approval
- Capture HiDPI (2x retina) via
playwright-cli run-codewithdeviceScaleFactor: 2 - Use
--filenameflag for all screenshots (path to.project/screenshots/) - Report actual dimensions in the summary
- Clean up browser contexts after use
- Delete
.project/auth-state.jsonat the end of PHASE 5 if auth was used
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
No reviews yet
People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.
- It worked
- Partly
- It didn't
Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

