Skip to content

Latest commit

Β 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

     β–„β–„β–„Β· β–„ .β–„       β–„β–„β–„β–„β–„ β–„β–„β–„Β· β–„β–„β–Œ  β–„β–„β–„Β· β–„β–„β–„β–„β–„
    β–β–ˆ β–€β–ˆ β–ˆβ–ˆβ–ͺβ–β–ˆ β–„β–ˆβ–€β–„ β€’β–ˆβ–ˆ  β–β–ˆ β–„β–ˆ β–ˆβ–ˆβ€’  β–β–ˆ β–„β–ˆ β€’β–ˆβ–ˆ
    β–„β–ˆβ–€β–€β–ˆ β–ˆβ–ˆβ–€β–β–ˆβ–β–ˆβ–Œ.β–β–Œ β–β–ˆ.β–ͺ β–ˆβ–ˆβ–€Β· β–ˆβ–ˆβ–ͺ  β–ˆβ–ˆβ–€Β·  β–β–ˆ.β–ͺ
    β–β–ˆ β–ͺβ–β–Œβ–ˆβ–ˆβ–Œβ–β–€β–β–ˆβ–Œ.β–β–Œ β–β–ˆβ–ŒΒ·β–β–ˆβ–ͺΒ·β€’ β–β–ˆβ–Œβ–β–Œβ–β–ˆβ–ͺΒ·β€’  β–β–ˆβ–ŒΒ·
     β–€  β–€ β–€β–€β–€ Β· β–€β–ˆβ–„β–€β–ͺ β–€β–€β–€ .β–€    .β–€β–€β–€ .β–€     β–€β–€β–€

Personal Tool Go License: AGPLv3

HTML in, image out. One Go binary that drives a real headless Chromium, so modern CSS renders exactly the way Chrome shows it.

Web "HTML to image" tools mean uploading your markup to someone's server, then cropping the result by hand. shotpls does it locally: point it at an HTML file (or a whole folder), get pixel-exact PNGs back at whatever size and pixel density you want. It was built to turn standalone Instagram-carousel slide files into ready-to-post 2160x2700 images with zero cropping, but it renders any HTML.

Highlights

  • Chrome-accurate rendering β€” drives your installed Chrome/Chromium over the DevTools protocol. Flexbox, grid, @font-face, SVG, blend modes, custom properties: whatever Chrome does, you get.
  • Exact geometry, no cropping β€” a fixed viewport plus a device scale factor. 1080x1350 @2x gives you a 2160x2700 PNG, edge to edge, every time.
  • Waits for fonts and images β€” blocks on document.fonts.ready and image decode before the shot, so you never capture a half-loaded page. --delay adds settle time for JS-heavy pages.
  • One file or a whole folder β€” pass a directory and it renders every .html inside, preserving the NN- ordering in the output names.
  • PNG or JPEG β€” --format jpeg --quality 88 when you want smaller files.
  • Single static binary, zero Go runtime dependencies. The only runtime requirement is a Chrome/Chromium on your machine.

Requirements

A recent Chrome or Chromium on your PATH (google-chrome, chromium, or chromium-browser). Point at a specific binary with --chrome /path/to/chrome if it lives somewhere unusual.

Installation

Quickest (curl)

curl -fsSL https://raw.githubusercontent.com/CarterPerez-dev/shotpls/main/install.sh | bash

The installer detects your OS / architecture, downloads the matching pre-built binary from the latest GitHub release (when available), falls back to go install if no binary exists for your platform, and adds ~/.shotpls/bin to your PATH for bash, zsh, or fish.

Override with environment variables:

SHOTPLS_INSTALL_DIR=$HOME/.local/bin \
SHOTPLS_VERSION=v0.1.0 \
  bash <(curl -fsSL https://raw.githubusercontent.com/CarterPerez-dev/shotpls/main/install.sh)

go install

go install github.com/CarterPerez-dev/shotpls@latest

Build from source

git clone https://github.com/CarterPerez-dev/shotpls.git
cd shotpls
go build -o shotpls .

Quick start

# One file -> slide.png (2160x2700) next to it
shotpls slide.html

# A whole folder -> PNGs in the current directory, NN- order preserved
shotpls htmls/ -o .

# JPEG instead of PNG
shotpls hero.html --format jpeg --quality 88

# A square 3x render
shotpls card.html --width 1080 --height 1080 --scale 3

# A JS-heavy page that needs a moment to settle
shotpls dashboard.html --delay 500

Flags

Flag Description
-o, --out DIR Output directory (default: same dir as each input)
--width N Viewport width in CSS px (default: 1080)
--height N Viewport height in CSS px (default: 1350)
--scale N Device scale factor (default: 2, so 1080x1350 becomes 2160x2700)
--format FMT png or jpeg (default: png)
--quality N JPEG quality 1-100 (default: 92)
--delay MS Extra settle time after load, in milliseconds (default: 0)
--timeout SEC Per-file render timeout in seconds (default: 30)
--chrome PATH Path to a specific Chrome/Chromium binary
-h, --help Show help
-v, --version Show version

Flags work in any position β€” shotpls htmls/ --scale 2 is the same as shotpls --scale 2 htmls/.

How it works

Output pixel dimensions are simply width x scale by height x scale:

--width 1080  --height 1350  --scale 2   ->  2160 x 2700   (Instagram portrait 4:5 @2x)
--width 1080  --height 1080  --scale 2   ->  2160 x 2160   (square @2x)
--width 1200  --height 630   --scale 2   ->  2400 x 1260   (OG image @2x)

Under the hood shotpls sets a device-metrics override (viewport + device scale factor) on a headless Chromium tab, navigates to the file:// URL, waits for document.fonts.ready and every image to finish decoding, then captures a screenshot clipped to exactly 0,0 -> width,height. No page chrome, no scrollbars, no cropping.

For batch runs the browser is launched once and reused across every file in the folder.

Project structure

main.go                       Entry point
internal/
  app/app.go                  Flag parsing + orchestration
  app/app_test.go             Table-driven tests
  render/render.go            Headless-Chromium rendering (chromedp)
install.sh                    Curl-installable bootstrapper

Single external dependency: github.com/chromedp/chromedp for driving Chrome.

Development

Requires Go 1.24+ (the build auto-fetches the Go 1.26 toolchain declared in go.mod) and a local Chrome/Chromium.

go test ./...                 # Run unit tests
go vet ./...                  # Static analysis
go build -o shotpls .         # Build local binary
just shot slide.html          # Render through local source

License

AGPL 3.0

About

internal tooling: html to image 🩡

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages