
Before And After
- 1.3k installs
- 203 repo stars
- Updated February 8, 2026
- vercel-labs/before-and-after
before-and-after is an agent skill for captures before/after screenshots of web pages or elements for visual comparison. use when user says "take before and after", "screenshot comparison", "visual diff", "pr.
About
The before-and-after skill is designed for captures before/after screenshots of web pages or elements for visual comparison. Use when user says "take before and after", "screenshot comparison", "visual diff", "PR. Before-After Screenshot Skill > Package: @vercel/before-and-after > Never use before-and-after (wrong package). Assume current state is After If user provides only one URL or says "PR screenshots" without URLs, ASK: "What URL should I use for the 'before' state? Invoke when the user user says "take before and after", "screenshot comparison", "visual diff", "PR screenshots", "compare old and new", or needs to document UI changes.
- Switch git branches, stash changes, start dev servers, or assume what "before" is.
- Use --full unless user explicitly asks for full page / full scroll capture.
- Use --markdown when user wants PR integration or markdown output.
- Use --mobile / --tablet if user mentions phone, mobile, tablet, responsive, etc.
- Assume current state is After.
Before And After by the numbers
- 1,331 all-time installs (skills.sh)
- +31 installs in the week ending Jul 28, 2026 (Skillselion tracking)
- Ranked #304 of 2,277 Frontend Development skills by installs in the Skillselion catalog
- Security screen: HIGH risk (skills.sh audit)
- Data as of Jul 28, 2026 (Skillselion catalog sync)
before-and-after capabilities & compatibility
- Capabilities
- switch git branches, stash changes, start dev se · use full unless user explicitly asks for full · use markdown when user wants pr integration or · use mobile / tablet if user mentions phone,
What before-and-after says it does
Captures before/after screenshots of web pages or elements for visual comparison. Use when user says "take before and after", "screenshot comparison", "visual diff", "PR screenshot
Captures before/after screenshots of web pages or elements for visual comparison. Use when user says "take before and after", "screenshot comparison", "visual d
npx skills add https://github.com/vercel-labs/before-and-after --skill before-and-afterAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.3k |
|---|---|
| repo stars | ★ 203 |
| Security audit | 0 / 3 scanners passed |
| Last updated | February 8, 2026 |
| Repository | vercel-labs/before-and-after ↗ |
How do I captures before/after screenshots of web pages or elements for visual comparison. use when user says "take before and after", "screenshot comparison", "visual diff", "pr?
Captures before/after screenshots of web pages or elements for visual comparison. Use when user says "take before and after", "screenshot comparison", "visual diff", "PR.
Who is it for?
Developers using before and after workflows documented in SKILL.md.
Skip if: Skip when the task falls outside before-and-after scope or needs a different stack.
When should I use this skill?
User user says "take before and after", "screenshot comparison", "visual diff", "PR screenshots", "compare old and new", or needs to document UI changes.
What you get
Completed before-and-after workflow with documented commands, files, and expected deliverables.
- shareable https file url
By the numbers
- Maximum upload size 512 MiB on 0x0.st
- Files expire after 365 days by default via 0x0.st hosting
Files
Before-After Screenshot Skill
Package: @vercel/before-and-afterNever use before-and-after (wrong package).Agent Behavior Rules
DO NOT:
- Switch git branches, stash changes, start dev servers, or assume what "before" is
- Use
--fullunless user explicitly asks for full page / full scroll capture
DO:
- Use
--markdownwhen user wants PR integration or markdown output - Use
--mobile/--tabletif user mentions phone, mobile, tablet, responsive, etc. - Assume current state is After
- If user provides only one URL or says "PR screenshots" without URLs, ASK: "What URL should I use for the 'before' state? (production URL, preview deployment, or another local port)"
Execution Order (MUST follow)
1. Pre-flight — which before-and-after || npm install -g @vercel/before-and-after 2. Protection check — if .vercel.app URL: curl -s -o /dev/null -w "%{http_code}" "<url>" (401/403 = protected) 3. Capture — before-and-after "<before-url>" "<after-url>" 4. Upload — ./scripts/upload-and-copy.sh <before.png> <after.png> --markdown 5. PR integration — optionally gh pr edit to append markdown
Never skip steps 1-2.
Quick Reference
# Basic usage
before-and-after <before-url> <after-url>
# With selector
before-and-after url1 url2 ".hero-section"
# Different selectors for each
before-and-after url1 url2 ".old-card" ".new-card"
# Viewports
before-and-after url1 url2 --mobile # 375x812
before-and-after url1 url2 --tablet # 768x1024
before-and-after url1 url2 --full # full scroll
# From existing images
before-and-after before.png after.png --markdown
# Via npx (use full package name!)
npx @vercel/before-and-after url1 url2| Flag | Description |
|---|---|
-m, --mobile | Mobile viewport (375x812) |
-t, --tablet | Tablet viewport (768x1024) |
--size <WxH> | Custom viewport |
-f, --full | Full scrollable page |
-s, --selector | CSS selector to capture |
-o, --output | Output directory (default: ~/Downloads) |
--markdown | Upload images & output markdown table |
--upload-url <url> | Custom upload endpoint (default: 0x0.st) |
Image Upload
# Default (0x0.st - no signup needed)
./scripts/upload-and-copy.sh before.png after.png --markdown
# GitHub Gist
IMAGE_ADAPTER=gist ./scripts/upload-and-copy.sh before.png after.png --markdownVercel Deployment Protection
If .vercel.app URL returns 401/403:
1. Check Vercel CLI: which vercel && vercel whoami 2. If available: vercel inspect <url> to get bypass token 3. If not: Tell user to provide bypass token, take manual screenshots, or disable protection
PR Integration
# Check for gh CLI
which gh
# Get current PR
gh pr view --json number,body
# Append screenshots to PR body
gh pr edit <number> --body "<existing-body>
## Before and After
<generated-markdown>"If no gh CLI: output markdown and tell user to paste manually.
Error Reference
| Error | Fix |
|---|---|
command not found | npm install -g @vercel/before-and-after |
could not determine executable | Use npx @vercel/before-and-after (full name) |
| 401/403 on .vercel.app | See Vercel protection section |
| Element not found | Verify selector exists on page |
#!/bin/bash
# 0x0.st adapter - Free, no-signup file hosting
# https://0x0.st
#
# Usage: ./0x0st.sh <file>
# Output: URL to uploaded file (stdout)
#
# Notes:
# - Files expire after 365 days (or sooner for larger files)
# - Max file size: 512 MiB
# - No authentication required
set -e
FILE="$1"
if [[ -z "$FILE" ]]; then
echo "Usage: $0 <file>" >&2
exit 1
fi
if [[ ! -f "$FILE" ]]; then
echo "Error: File not found: $FILE" >&2
exit 1
fi
# Upload to 0x0.st - returns the URL directly
URL=$(curl -s -A "before-after-cli/1.0" -F "file=@$FILE" https://0x0.st)
# Validate we got a URL back
if [[ ! "$URL" =~ ^https?:// ]]; then
echo "Error: Upload failed. Response: $URL" >&2
exit 1
fi
echo "$URL"
#!/bin/bash
# Custom blob storage adapter - For self-hosted or custom endpoints
#
# Usage: ./blob.sh <file>
# Output: URL to uploaded file (stdout)
#
# Environment:
# BLOB_UPLOAD_URL Required. URL endpoint for uploading images
#
# Notes:
# - Expects endpoint to accept multipart form upload with "file" field
# - Expects response to be either:
# - Plain text URL
# - JSON with "url" field
set -e
FILE="$1"
if [[ -z "$FILE" ]]; then
echo "Usage: $0 <file>" >&2
exit 1
fi
if [[ ! -f "$FILE" ]]; then
echo "Error: File not found: $FILE" >&2
exit 1
fi
if [[ -z "$BLOB_UPLOAD_URL" ]]; then
echo "Error: BLOB_UPLOAD_URL environment variable not set" >&2
echo "" >&2
echo "Set it with:" >&2
echo " export BLOB_UPLOAD_URL='https://your-blob-service.com/upload'" >&2
exit 1
fi
# Upload file
RESPONSE=$(curl -s -X POST -F "file=@$FILE" "$BLOB_UPLOAD_URL")
# Try to extract URL from JSON response
URL=$(echo "$RESPONSE" | grep -o '"url"[[:space:]]*:[[:space:]]*"[^"]*"' | sed 's/"url"[[:space:]]*:[[:space:]]*"//' | sed 's/"$//' || true)
# Fallback: maybe the response is just the URL
if [[ -z "$URL" ]]; then
URL="$RESPONSE"
fi
# Validate we got a URL back
if [[ ! "$URL" =~ ^https?:// ]]; then
echo "Error: Upload failed. Response: $RESPONSE" >&2
exit 1
fi
echo "$URL"
#!/bin/bash
# GitHub Gist adapter - Upload images via gh CLI
#
# Usage: ./gist.sh <file>
# Output: Raw URL to uploaded file (stdout)
#
# Requirements:
# - gh CLI installed and authenticated
#
# Notes:
# - Creates a public gist for each upload
# - Files persist indefinitely
# - Requires GitHub authentication
set -e
FILE="$1"
if [[ -z "$FILE" ]]; then
echo "Usage: $0 <file>" >&2
exit 1
fi
if [[ ! -f "$FILE" ]]; then
echo "Error: File not found: $FILE" >&2
exit 1
fi
# Check gh is available
if ! command -v gh &> /dev/null; then
echo "Error: gh CLI not found. Install from https://cli.github.com" >&2
exit 1
fi
# Create gist and capture output
GIST_OUTPUT=$(gh gist create "$FILE" --public 2>&1)
# Extract the gist URL from output
GIST_URL=$(echo "$GIST_OUTPUT" | grep -o 'https://gist.github.com/[^ ]*' | head -1)
if [[ -z "$GIST_URL" ]]; then
echo "Error: Failed to create gist. Output: $GIST_OUTPUT" >&2
exit 1
fi
# Convert to raw URL
# Format: https://gist.github.com/user/id -> https://gist.githubusercontent.com/user/id/raw/filename
GIST_ID=$(echo "$GIST_URL" | sed 's|.*/||')
FILENAME=$(basename "$FILE")
# Get the raw URL via gh api
RAW_URL=$(gh api "gists/$GIST_ID" --jq ".files[\"$FILENAME\"].raw_url")
if [[ -z "$RAW_URL" ]]; then
echo "Error: Could not get raw URL for gist" >&2
exit 1
fi
echo "$RAW_URL"
#!/bin/bash
# capture.sh - Core screenshot capture using agent-browser
# Usage: ./capture.sh <url> <output.png> [--full] [--element <selector>]
#
# Options:
# --full Full page screenshot (viewport 1500x1000)
# --element <sel> Element screenshot (auto-sized to element bounds)
#
# Examples:
# ./capture.sh "http://localhost:3000" ~/Downloads/screenshot.png --full
# ./capture.sh "http://localhost:3000" ~/Downloads/button.png --element ".btn-primary"
set -e
URL="$1"
OUTPUT="$2"
shift 2
# Default to full page
MODE="full"
SELECTOR=""
# Parse options
while [[ $# -gt 0 ]]; do
case $1 in
--full)
MODE="full"
shift
;;
--element)
MODE="element"
SELECTOR="$2"
shift 2
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
if [[ -z "$URL" || -z "$OUTPUT" ]]; then
echo "Usage: $0 <url> <output.png> [--full] [--element <selector>]"
exit 1
fi
# Ensure output directory exists
mkdir -p "$(dirname "$OUTPUT")"
echo "Opening: $URL"
agent-browser:open "$URL"
echo "Waiting for page load..."
agent-browser:wait --load networkidle
if [[ "$MODE" == "element" && -n "$SELECTOR" ]]; then
echo "Capturing element: $SELECTOR"
agent-browser:screenshot --selector "$SELECTOR" --output "$OUTPUT"
else
echo "Capturing full page (1500x1000)"
agent-browser:screenshot --viewport 1500x1000 --output "$OUTPUT"
fi
echo "Screenshot saved: $OUTPUT"
#!/bin/bash
# upload-and-copy.sh - Upload images via pluggable storage adapters
# Usage: ./upload-and-copy.sh <before.png> <after.png> [--markdown]
#
# Options:
# --markdown Generate PR markdown table and copy to clipboard
#
# Environment:
# IMAGE_ADAPTER Storage adapter to use (default: 0x0st)
# Available: 0x0st, gist, blob
#
# Adapter-specific environment variables:
# blob: BLOB_UPLOAD_URL - Custom upload endpoint
#
# Examples:
# ./upload-and-copy.sh before.png after.png
# ./upload-and-copy.sh before.png after.png --markdown
# IMAGE_ADAPTER=gist ./upload-and-copy.sh before.png after.png --markdown
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ADAPTERS_DIR="$SCRIPT_DIR/adapters"
# Default adapter
IMAGE_ADAPTER="${IMAGE_ADAPTER:-0x0st}"
BEFORE_FILE="$1"
AFTER_FILE="$2"
shift 2 2>/dev/null || true
MARKDOWN_MODE=false
# Parse options
while [[ $# -gt 0 ]]; do
case $1 in
--markdown)
MARKDOWN_MODE=true
shift
;;
*)
echo "Unknown option: $1"
exit 1
;;
esac
done
# Validate inputs
if [[ -z "$BEFORE_FILE" || -z "$AFTER_FILE" ]]; then
echo "Usage: $0 <before.png> <after.png> [--markdown]"
echo ""
echo "Environment:"
echo " IMAGE_ADAPTER Storage adapter (default: 0x0st)"
echo " Available: 0x0st, gist, blob"
exit 1
fi
if [[ ! -f "$BEFORE_FILE" ]]; then
echo "Error: Before file not found: $BEFORE_FILE"
exit 1
fi
if [[ ! -f "$AFTER_FILE" ]]; then
echo "Error: After file not found: $AFTER_FILE"
exit 1
fi
# Validate adapter exists
ADAPTER_SCRIPT="$ADAPTERS_DIR/$IMAGE_ADAPTER.sh"
if [[ ! -f "$ADAPTER_SCRIPT" ]]; then
echo "Error: Unknown adapter: $IMAGE_ADAPTER"
echo ""
echo "Available adapters:"
for adapter in "$ADAPTERS_DIR"/*.sh; do
name=$(basename "$adapter" .sh)
echo " - $name"
done
exit 1
fi
# Upload function using adapter
upload_file() {
local file="$1"
local filename=$(basename "$file")
echo "Uploading: $filename (via $IMAGE_ADAPTER)" >&2
# Call the adapter script
"$ADAPTER_SCRIPT" "$file"
}
# Upload both files
echo "=== Uploading Screenshots ==="
BEFORE_URL=$(upload_file "$BEFORE_FILE")
AFTER_URL=$(upload_file "$AFTER_FILE")
echo ""
echo "Before URL: $BEFORE_URL"
echo "After URL: $AFTER_URL"
echo ""
if [[ "$MARKDOWN_MODE" == "true" ]]; then
# Generate PR markdown table (centered alignment for GitHub)
MARKDOWN="| Before | After |
|:------:|:-----:|
|  |  |"
echo "=== PR Markdown Table ==="
echo "$MARKDOWN"
echo ""
# Copy to clipboard (macOS)
if command -v pbcopy &> /dev/null; then
echo "$MARKDOWN" | pbcopy
echo "Markdown table copied to clipboard!"
elif command -v xclip &> /dev/null; then
echo "$MARKDOWN" | xclip -selection clipboard
echo "Markdown table copied to clipboard!"
else
echo "(clipboard copy not available - install pbcopy or xclip)"
fi
else
# Copy URLs to clipboard
URLS="Before: $BEFORE_URL
After: $AFTER_URL"
if command -v pbcopy &> /dev/null; then
echo "$URLS" | pbcopy
echo "URLs copied to clipboard!"
elif command -v xclip &> /dev/null; then
echo "$URLS" | xclip -selection clipboard
echo "URLs copied to clipboard!"
else
echo "(clipboard copy not available - install pbcopy or xclip)"
fi
fi
Related skills
Forks & variants (1)
Before And After has 1 known copy in the catalog totaling 3 installs. They canonicalize to this original listing.
- vijaykpatel - 3 installs
FAQ
What does before-and-after do?
Captures before/after screenshots of web pages or elements for visual comparison. Use when user says "take before and after", "screenshot comparison", "visual diff", "PR.
When should I use before-and-after?
User user says "take before and after", "screenshot comparison", "visual diff", "PR screenshots", "compare old and new", or needs to document UI changes.
Is before-and-after safe to install?
Review the Security Audits panel on this page before installing in production.