snap-asset
Screenshot-to-asset pipeline: capture web pages, components & extract site assets as optimized PNG+WebP — CLI + Claude Code skill
- Stars
- 10
- Language
- JavaScript
- License
- MIT
- Updated
The Problem
Building a portfolio? Showcasing app features? You've done this dance:
- Open your app in the browser
- Manually take a screenshot
- Rename it something sensible
- Convert to WebP for performance
- Move to
public/orassets/ - Repeat 20 times
snap-asset is a Claude Code plugin that automates the entire pipeline. Tell Claude what to capture — it handles the rest. Also works standalone as a CLI.
Install as Claude Code Plugin
git clone https://github.com/Manavarya09/snap-asset.git ~/.claude/plugins/snap-asset
cd ~/.claude/plugins/snap-asset && npm install
Then just talk to Claude naturally:
"Screenshot my app at localhost:5173 and save it as hero"
"Extract all assets from https://competitor.com into public/"
"Capture the .feature-card element in dark mode"
"Take a screenshot of my Hero.tsx component in isolation"
Or use /snap-asset as a slash command.
Features
- Claude Code Skill — Just describe what you want, Claude captures it
- URL Capture — Screenshot any URL with Playwright's headless Chromium
- Element Capture — Target specific elements with CSS selectors
- Site Extraction — Scrape an entire website: sections, images, components, everything
- Component Isolation — Render React/Vue/Svelte components in isolation and capture
- Batch Mode — Define all your captures in a config file, run once
- Auto-Optimization — PNG + WebP generated simultaneously via Sharp
- Retina Ready — 2x device scale by default for crisp screenshots
- Dark Mode — Capture in light or dark color scheme
- Claude Code Skill — Use as
/snap-assetinside Claude Code
Install
# Clone into your plugins directory
git clone https://github.com/Manavarya09/snap-asset.git
cd snap-asset
npm install
# Or use directly with npx (after global install)
npm install -g .
Playwright will automatically download Chromium during
npm install.Run
npm testto execute the built-in output and optimizer test suite.Component isolation uses Vite and framework plugins. Those dependencies are included in the package so component rendering works out of the box.
Quick Start
Capture a URL
snap-asset https://myapp.com --name hero --out public/
snap-asset v0.1.0
URL https://myapp.com
Viewport 1280x800 @2x
saved public/hero.png (142 KB)
saved public/hero.webp ( 68 KB)
WebP saved 52% vs PNG
✓ Done!
Capture a Specific Element
snap-asset https://myapp.com --selector ".feature-card" --name feature
Extract Everything from a Website
snap-asset extract https://myapp.com --out public/assets
This grabs:
- Full page screenshot
- Viewport (above-the-fold) screenshot
- Sections: hero, header, footer, features, pricing, testimonials, CTA
- All images (>50px, auto-named from alt text)
- Components: cards, buttons, navbars, modals, sidebars
Capture a Component in Isolation
snap-asset component ./src/components/Hero.tsx --name hero
Spins up a temporary Vite server, renders your component, captures it with transparent background.
Batch Mode
# Generate starter config
snap-asset init
# Edit snap-asset.config.json, then:
snap-asset batch
CLI Reference
Usage: snap-asset [options] [command] [url]
Commands:
extract <url> Extract all assets from a website
component <path> Capture a component in isolation
batch Run captures from snap-asset.config.json
init Generate starter config
Options:
-n, --name <name> Output filename (auto-derived if omitted)
-o, --out <dir> Output directory (auto-detects public/)
-s, --selector <css> Capture a specific element
-w, --width <px> Viewport width (default: 1280)
-h, --height <px> Viewport height (default: 800)
--scale <n> Device scale factor (default: 2)
-f, --format <fmt> png, webp, or both (default: both)
-q, --quality <n> WebP quality 1-100 (default: 80)
--resize <WxH> Resize after capture
--wait <ms> Wait before capture (for animations)
--dark Dark color scheme
--full-page Capture full scrollable page
--overwrite Overwrite existing files
Config File
snap-asset.config.json:
{
"defaults": {
"out": "public/screenshots",
"width": 1280,
"height": 800,
"scale": 2,
"quality": 80
},
"captures": [
{
"name": "hero",
"url": "http://localhost:5173",
"selector": ".hero-section"
},
{
"name": "dashboard",
"url": "http://localhost:5173/dashboard",
"fullPage": true
},
{
"name": "feature-card",
"component": "./src/components/FeatureCard.tsx",
"width": 400,
"height": 300
}
]
}
Uploaders (S3 / GCS)
This project includes optional uploaders for S3 and GCS. They are loaded dynamically and are not required at runtime unless you explicitly select them.
Environment variables / secrets
-
For S3 (AWS):
AWS_REGION— AWS regionAWS_S3_BUCKET— target bucket nameAWS_ACCESS_KEY_IDandAWS_SECRET_ACCESS_KEY— credentials (recommended to use GitHub Secrets)
-
For GCS:
GCS_BUCKET— target bucket nameGOOGLE_APPLICATION_CREDENTIALSor pass credentials object via uploader options
GitHub Actions snippet (example)
jobs:
upload-integration:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 20.x
- name: Install deps
run: npm ci
- name: Run uploader integration tests
env:
RUN_UPLOADER_INTEGRATION: '1'
AWS_REGION: ${{ secrets.AWS_REGION }}
AWS_S3_BUCKET: ${{ secrets.AWS_S3_BUCKET }}
AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
GCS_BUCKET: ${{ secrets.GCS_BUCKET }}
GOOGLE_APPLICATION_CREDENTIALS: ${{ secrets.GOOGLE_APPLICATION_CREDENTIALS }}
run: npm test -- tests/uploader.integration.test.js
Notes
- Tests are guarded and will only run when
RUN_UPLOADER_INTEGRATION=1is set to avoid leaking secrets in regular CI runs. - If you want to run uploads locally against a real provider, export the required env vars or create a credentials file for GCS and set
RUN_UPLOADER_INTEGRATION=1.
Claude Code Integration
Use as a Claude Code skill:
/snap-asset https://myapp.com --name hero
/snap-asset extract https://competitor.com --out public/extracted
/snap-asset component ./src/Hero.tsx
Claude will capture, optimize, and save the assets — then help you integrate the image paths into your components.
How It Works
URL / Component Path
│
▼
┌─────────────┐
│ Playwright │ Headless Chromium
│ Capture │ Retina (2x), dark mode, selectors
└──────┬──────┘
│ Raw PNG buffer
▼
┌─────────────┐
│ Sharp │ Optimize PNG, convert to WebP
│ Optimize │ Auto-resize, quality control
└──────┬──────┘
│ Optimized buffers
▼
┌─────────────┐
│ Output │ Auto-detect public/ or assets/
│ Manager │ Safe naming, dedup, save
└─────────────┘
Use Cases
| Scenario | Command |
|---|---|
| Portfolio hero image | snap-asset https://myapp.com --name hero |
| Feature showcase cards | snap-asset https://myapp.com --selector ".card" --name feature |
| Competitor analysis | snap-asset extract https://competitor.com |
| Component library docs | snap-asset component ./src/Button.tsx |
| Landing page assets | snap-asset batch with config |
| Dark mode variant | snap-asset https://myapp.com --dark --name hero-dark |
| Mobile screenshot | snap-asset https://myapp.com --width 375 --height 812 --name mobile |
Tech Stack
| Tool | Purpose |
|---|---|
| Playwright | Headless browser automation |
| Sharp | High-performance image processing |
| Commander | CLI argument parsing |
| Chalk | Terminal colors |
| Ora | Terminal spinners |
Contributing
PRs welcome! Check the issues for planned features.
git clone https://github.com/Manavarya09/snap-asset.git
cd snap-asset
npm install
node bin/snap-asset.js https://example.com --name test
License
MIT - Manav Arya Singh