screenshot
Back to list

danny/screenshot

Screenshot

GitHub

Capture a screenshot of any rendered web page in headless Chrome — full page, viewport, section, or element — for review and motion pipelines.

ToolingFrontendVisual0 demos

Real-world examples not captured yet

This skill shows a gallery of live HTML demos (CDN libraries welcome — GSAP, Three.js, etc.) rendered inline via srcdoc.

Skill markdown
# Screenshot

Loads a URL in headless Chrome and captures exactly what the user asked for — the whole page, one section, a single element, the viewport, or a specific device rendering. Saves a PNG and Reads it back so the result is visible inline.

The engine is `scripts/screenshot.mjs`, which drives the user's installed Google Chrome through `playwright-core` (no bundled-browser download). It prints the saved PNG path on its **last stdout line** — read that path, then Read the PNG to view it.

## When to use this skill

- "Screenshot localhost:3000" / "grab a screenshot of headshotpro.com"
- "Screenshot the pricing section" / "capture the hero" / "the footer"
- "Screenshot the CTA button" / "just the nav bar" / "the `.testimonials` block"
- "Screenshot the whole page" / "the full scrollable page"
- "Screenshot the mobile view" / "how does this look on tablet"
- "Show me how the FAQ renders"

## When NOT to use this skill

- The user wants to **interact** with the page (click, fill, assert, audit a11y/console/network) → that's `expect` / browser-testing tools.
- The user wants a **generated design/mockup**, not a capture of a real page → `frontend-design` / `static-visual` / `visual`.
- Screenshot of the desktop or a non-web app → out of scope.

## CRITICAL

- **Interpret intent first** — the user describes *what* in plain language; you pick the right flag (see the map below). Don't ask which flag; infer it.
- **Last stdout line is the PNG path** (everything else is stderr). Capture it and Read the image to show the user.
- **Always report the FULL absolute path verbatim** in your reply — never abbreviate, truncate, or collapse the temp dir with `…/`. Put it on its own line so it stays copyable/clickable. Also surface the `file://…` line the script prints, since it's cmd/ctrl-clickable in most terminals.
- First run only: if it fails with `Cannot find package 'playwright-core'`, do the one-time install in Step 1.
- Uses the **installed Google Chrome** (`--channel chrome`) — no browser download. If Chrome is absent, see Troubleshooting.

## Intent → flags (the core of this skill)

| What the user said | Flags |
|--------------------|-------|
| "the page", "the whole page", "full page" | `--full-page` |
| "this page" / no target / "what's on screen" | *(omit target → viewport)* |
| "the pricing section", "the FAQ", "the hero" (named area) | `--section "pricing"` (heading match → enclosing `<section>`) |
| "the CTA button", "the nav", "`.hero`", "#footer" (one element) | `--selector ".hero"` |
| "the third section", "section 2" | `--section 3` |
| "the X inside the Y" (element within a container) | `--section "X" --container ".Y"` |
| "mobile view" / "on a phone" | `--device mobile` |
| "tablet" / "desktop" | `--device tablet` / `--device desktop` |
| "at 2x" / "retina" | `--scale 2` (already the default) |
| custom size | `--width 1440 --height 900` |
| "it loads slowly" / "wait for X" | `--wait 1500` or `--wait "<selector>"` |
| logged-in page / "I need to be signed in" | `--cdp <wsUrl>` (see Example 4) |

When in doubt between a *named area* and an *exact element*: try `--section "<text>"` first (it falls back through heading → text → block). Use `--selector` when the user names a CSS selector or a single small control.

## Workflow

```
- [ ] Step 1: Ensure deps installed (first run only)
- [ ] Step 2: Determine URL + map the user's words to a target flag
- [ ] Step 3: Run scripts/screenshot.mjs
- [ ] Step 4: Read the printed PNG path to view it; report where it saved
```

### Step 1: Ensure deps (first run only)

```bash
cd ~/.claude/skills/screenshot/scripts && npm install
```

Installs `playwright-core` only (small, no browser download). Skip if already installed.

### Step 2: Determine URL + target

- **URL**: a bare path like `/pricing` defaults to the local dev server (`http://localhost:3000` for this Nuxt app) unless the user gives a host. Make sure the dev server is running for localhost URLs.
- **Target**: map the user's phrasing using the **Intent → flags** table above.

### Step 3: Run the script

```bash
node ~/.claude/skills/screenshot/scripts/screenshot.mjs --url "<url>" [target flags] [render flags]
```

Full option list is in the header of `scripts/screenshot.mjs`. Quick reference:

| Flag | Purpose | Default |
|------|---------|---------|
| `--url <url>` | Page to load (required) | — |
| `--full-page` | Whole scrollable page | off |
| `--selector <css>` | One exact element | — |
| `--section <value>` | Heading text, CSS, or Nth `<section>` | — |
| `--container <css>` | Ancestor to capture when matching by heading | nearest `<section>` |
| `--device <name>` | `mobile` \| `tablet` \| `desktop` preset | — |
| `--width / --height` | Viewport size | 1280 × 800 |
| `--scale <n>` | Device scale (retina) | 2 |
| `--wait <ms\|selector>` | Extra wait before capture | none |
| `--pad <px>` | Padding around a section/element clip | 0 |
| `--out <path>` | Output PNG path | timestamped temp file |
| `--

…

More from danny