168 lines
6.6 KiB
Markdown
168 lines
6.6 KiB
Markdown
|
|
# CLAUDE.md
|
||
|
|
|
||
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
|
|
||
|
|
## Overview
|
||
|
|
|
||
|
|
WebShot is a CLI tool built with Node.js and Puppeteer for capturing screenshots, videos, and full HTML snapshots of websites. It features an interactive "shoot mode" with pastel-themed terminal UI, custom automation scripts, and support for multiple export formats (PNG, JPG, WEBP, PDF, MP4, HTML).
|
||
|
|
|
||
|
|
## Architecture
|
||
|
|
|
||
|
|
### Core Components
|
||
|
|
|
||
|
|
**Main executable** (`webshot`):
|
||
|
|
- Single-file CLI application with shebang (`#!/usr/bin/env node`)
|
||
|
|
- Self-contained with all functionality in ~800 lines
|
||
|
|
- Uses Puppeteer for browser automation
|
||
|
|
- Built-in debug mode with Node.js inspector support (restarts process with `--inspect`)
|
||
|
|
|
||
|
|
**Key architectural patterns**:
|
||
|
|
- **Spinner class** (webshot:79-114): Animated terminal progress indicator with rotating frames and pastel colors
|
||
|
|
- **Export functions** (webshot:202-470): Modular export handlers for each format (PNG, JPG, WEBP, PDF, MP4, HTML)
|
||
|
|
- **MP4 recording** (webshot:243-400): Fast screenshot-loop method that captures JPEG frames and uses ffmpeg to create video (supports both MP4 with H.264 and WebM with VP9)
|
||
|
|
- **HTML export** (webshot:403-470): Downloads complete page with all assets (images, CSS, JS) into `assets/` subdirectory
|
||
|
|
- **Interactive shoot mode** (webshot:149-200): Race between spacebar press and countdown timer
|
||
|
|
|
||
|
|
### Custom Script System
|
||
|
|
|
||
|
|
WebShot supports custom Puppeteer automation scripts via `-s/--script` flag. Scripts are evaluated with access to the `page` object and can manipulate the page before capture.
|
||
|
|
|
||
|
|
**Example scripts** (`examples/`):
|
||
|
|
- `scroll-animation.js` - Smoothly scrolls to bottom and back to top
|
||
|
|
- `dark-mode.js` - Attempts to enable dark mode using multiple detection methods
|
||
|
|
- `interact-form.js` - Fills out forms with demo data
|
||
|
|
- `hover-effects.js` - Simulates hover states on interactive elements
|
||
|
|
- `mobile-view.js` - Switches to mobile viewport (375x667, iPhone SE)
|
||
|
|
- `animated-sections.js` - Scrolls through sections to trigger scroll-based animations
|
||
|
|
|
||
|
|
Scripts are executed via `eval()` in an async context with access to `page`, `console`, and other webshot internals (webshot:722-727).
|
||
|
|
|
||
|
|
## Commands
|
||
|
|
|
||
|
|
### Basic Usage
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Install dependencies
|
||
|
|
pnpm install
|
||
|
|
|
||
|
|
# Make executable (if needed)
|
||
|
|
chmod +x webshot
|
||
|
|
|
||
|
|
# Run from anywhere (if in PATH)
|
||
|
|
webshot -u https://github.com --help
|
||
|
|
```
|
||
|
|
|
||
|
|
### Common Workflows
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Screenshot with interactive shoot mode
|
||
|
|
webshot -u https://example.com
|
||
|
|
|
||
|
|
# Screenshot without delay
|
||
|
|
webshot -u https://example.com --no-delay
|
||
|
|
|
||
|
|
# High quality WEBP
|
||
|
|
webshot -u https://example.com -f webp --quality 95
|
||
|
|
|
||
|
|
# Record 10 second video (MP4)
|
||
|
|
webshot -u https://bruno-simon.com -f mp4 --duration 10000 --fps 30
|
||
|
|
|
||
|
|
# Record as WebM instead
|
||
|
|
webshot -u https://bruno-simon.com -f mp4 -o output.webm --duration 10000
|
||
|
|
|
||
|
|
# Export as PDF
|
||
|
|
webshot -u https://github.com/features -f pdf
|
||
|
|
|
||
|
|
# Download complete HTML with assets
|
||
|
|
webshot -u https://stripe.com -f html -o stripe/index.html
|
||
|
|
|
||
|
|
# Use custom automation script
|
||
|
|
webshot -u https://example.com -s examples/dark-mode.js
|
||
|
|
|
||
|
|
# Custom viewport
|
||
|
|
webshot -u https://example.com -w 1280 -h 720
|
||
|
|
|
||
|
|
# Custom shoot delay (5 seconds)
|
||
|
|
webshot -u https://example.com 5000
|
||
|
|
```
|
||
|
|
|
||
|
|
### Debug Mode
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# Enable debug logging and Node.js inspector
|
||
|
|
webshot -u https://example.com --debug
|
||
|
|
|
||
|
|
# Connect debugger on custom port
|
||
|
|
DEBUG_PORT=9230 webshot -u https://example.com --debug
|
||
|
|
|
||
|
|
# Debug with specific wait strategy (for slow sites)
|
||
|
|
webshot -u https://example.com --debug --wait-until load --timeout 60000
|
||
|
|
```
|
||
|
|
|
||
|
|
Debug mode:
|
||
|
|
- Prints detailed logs prefixed with `[DEBUG]` in magenta (webshot:36-40)
|
||
|
|
- Enables Puppeteer dumpio for browser console output (webshot:669)
|
||
|
|
- Listens for page console messages, errors, and failed requests (webshot:677-682)
|
||
|
|
- Restarts process with `--inspect` if not already in debug mode (webshot:7-19)
|
||
|
|
|
||
|
|
### Wait Strategies
|
||
|
|
|
||
|
|
The `--wait-until` flag controls when navigation is considered complete:
|
||
|
|
- `load` - Wait for window.load event (fastest, may miss dynamic content)
|
||
|
|
- `domcontentloaded` - Wait for DOM to be ready
|
||
|
|
- `networkidle2` (default) - Wait until 2 or fewer network connections remain for 500ms
|
||
|
|
- `networkidle0` - Wait until 0 network connections remain (slowest, most complete)
|
||
|
|
|
||
|
|
Use `--timeout <ms>` to increase navigation timeout for slow sites (default: 30000ms).
|
||
|
|
|
||
|
|
## Format-Specific Details
|
||
|
|
|
||
|
|
### MP4/WebM Video Recording
|
||
|
|
|
||
|
|
Video recording uses a fast screenshot-loop method:
|
||
|
|
1. Captures JPEG screenshots as fast as possible (quality: 60 for speed)
|
||
|
|
2. Saves frames to temporary directory (`.webshot-frames-<timestamp>/`)
|
||
|
|
3. Uses ffmpeg to convert frames to video
|
||
|
|
4. Automatically detects output format based on file extension (`.mp4` → H.264, `.webm` → VP9)
|
||
|
|
5. Duplicates frames to reach target FPS using ffmpeg `-r` flag
|
||
|
|
6. Cleans up temporary frames after conversion
|
||
|
|
|
||
|
|
Requires `ffmpeg` to be installed and available in PATH.
|
||
|
|
|
||
|
|
### HTML Export
|
||
|
|
|
||
|
|
HTML export downloads a complete snapshot:
|
||
|
|
1. Extracts all resource URLs (images, CSS, JS, favicon)
|
||
|
|
2. Downloads each resource using Puppeteer's page.goto()
|
||
|
|
3. Saves resources to `assets/` subdirectory relative to output file
|
||
|
|
4. Rewrites HTML to use local asset paths
|
||
|
|
5. Returns to original page after downloading
|
||
|
|
|
||
|
|
## Package Structure
|
||
|
|
|
||
|
|
- **Package manager**: pnpm (uses pnpm-workspace)
|
||
|
|
- **Main entry**: `webshot` (executable script, also set as bin in package.json)
|
||
|
|
- **Only dependency**: `puppeteer` (uses bundled Chromium)
|
||
|
|
- **Keywords**: pupeteer (sic), cli, record, screeencast (sic), shoot
|
||
|
|
|
||
|
|
## Color Palette
|
||
|
|
|
||
|
|
Terminal UI uses pastel ANSI colors defined in `colors` object (webshot:43-63):
|
||
|
|
- Pastels: pink (217), lavender (183), mint (158), peach (223), sky (153), coral (210), sage (151)
|
||
|
|
- Standard: green, yellow, red, cyan, gray
|
||
|
|
- Modifiers: bright, dim, reset
|
||
|
|
|
||
|
|
ASCII banner uses mint → sky → lavender gradient (webshot:66-76).
|
||
|
|
|
||
|
|
## Important Notes
|
||
|
|
|
||
|
|
- **Single file architecture**: All code lives in the `webshot` executable - no separate modules
|
||
|
|
- **No README**: Project lacks a README.md file, all documentation is in `--help` output
|
||
|
|
- **No tests**: No test directory or test files present
|
||
|
|
- **Script evaluation security**: Custom scripts are evaluated with `eval()` and have full access to Node.js APIs - only use trusted scripts
|
||
|
|
- **ffmpeg dependency**: MP4/WebM recording requires ffmpeg to be installed separately
|
||
|
|
- **Viewport defaults**: 1920x1080 at 2x device scale factor (webshot:684-688)
|
||
|
|
- **Interactive mode**: Uses raw terminal input with keypress events (webshot:152-154)
|
||
|
|
- **File overwrite**: Always prompts before overwriting existing files (webshot:129-146)
|
||
|
|
- **Fonts ready**: Waits for document.fonts.ready before capturing (webshot:716)
|