assetopt
Open source · MIT · v1.0.0

Optimize your static assets.Locally.

A Node.js CLI for images, CSS, JS, and SVG. Smart format routing, incremental cache, one command. No upload, no account, no SaaS.

$ npm install -g @assetopt/cli
~/my-project
$ assetopt optimize ./public

Loading config from .assetoptrc … preset: web-perf
Found 47 assets (images, css, js, svg)

   hero.jpg          4.2 MB  →  1.7 MB  -59.5%
   portrait.png      3.8 MB  →  540 KB  -86.1%  (smart-routed → webp)
   logo.png          1.4 MB  →  260 KB  -81.9%  (smart-routed → avif)
   styles.css        3.3 KB  →  1.5 KB  -54.0%
   app.js            2.8 KB  →  810 B   -71.7%

Total: 12.4 MB → 2.9 MB (-77%)  — in 3.8s

Why assetopt

Built for real folders, not benchmark demos.

Four things assetopt does that one-off compression tools don't.

Smart format routing

The web-perf preset converts JPEG to WebP and routes each PNG to WebP (opaque) or AVIF (transparent). One config line, the right decision per file.

Incremental cache

A sha256 manifest tracks every source and its config. Re-running optimize skips unchanged files. First run is slow, every run after is near-instant.

Multi-asset, one command

Images, CSS, JS, and SVG in the same pass — sharp, lightningcss, esbuild, svgo wired together so you don't glue four tools yourself.

Local. Free. MIT.

No upload, no account, no SaaS, no telemetry. Your assets stay on your machine. The CLI is MIT and feature-complete on its own.

Quickstart

Three commands. No config dance.

From zero to optimized assets in under a minute. Already have a build pipeline? Drop the optimize step into your CI and skip step 1.

  1. 1

    Initialize

    Generate a default .assetoptrc at the root of your project.

    $ assetopt init
  2. 2

    Analyze

    Dry-run: see potential savings without writing anything to disk.

    $ assetopt analyze ./public
  3. 3

    Optimize

    Write optimized assets to ./optimized/. Originals are untouched.

    $ assetopt optimize ./public
Cached on re-runFull reference in thedocs.

What you get

Real files. Real numbers.

Every figure below comes from running assetopt on the downloadable sample pack with the web-perf preset. Drag each slider — same pixels, far fewer bytes. The smart routing layer splits PNGs by transparency.

Landscape photograph exported as a large PNGOriginal · 5.2 MB
assetopt · WEBP · 539 KB
PNG · opaquesmart-routed

PNG export (opaque)

−89.8%
Original5.2 MB
assetopt → WEBP539 KB

An opaque PNG — smart-routed to WebP, which beats AVIF on this content.

Photo via Lorem Picsum / Unsplash

assetopt logo: a compress glyph on an indigo rounded squareOriginal · 56 KB
assetopt · AVIF · 9 KB
PNG · transparentsmart-routed

PNG logo (transparent)

−83.3%
Original56 KB
assetopt → AVIF9 KB

A logo PNG with alpha — smart-routed to AVIF, which keeps transparency at a far smaller size.

Designed for this pack · CC0

River canyon landscape photographOriginal · 1.7 MB
assetopt · WEBP · 1.4 MB
JPEG

JPEG photo

−17.4%
Original1.7 MB
assetopt → WEBP1.4 MB

A heavy photo export. The web-perf preset converts it to WebP at matched quality.

Photo via Lorem Picsum / Unsplash

CSSmain.css
2 KB → 1 KB
−31.4%
JSapp.js
2 KB → 984 B
−59.7%
SVGdiagram.svg
2 KB → 1 KB
−53.6%
Whole pack : 7.9 MB → 2.7 MB. Your gains depend on how compressed your sources already are.
−65.3% total

Try it yourself

Don't trust the numbers. Reproduce them.

Download the exact pack these figures come from. It ships with the .assetoptrc used above — run two commands and you'll land on the same −65.3%. Nothing is uploaded; everything runs on your machine.

Sample asset pack

Photos, PNGs, an SVG, CSS and JS — plus the config. 7.8 MB zip.

Download .zip
  1. 1

    Unzip and step in

    $ unzip sample-assets.zip -d sample-assets && cd sample-assets
  2. 2

    See the savings (writes nothing)

    $ npx @assetopt/cli analyze .
  3. 3

    Optimize for real (→ ./optimized)

    $ npx @assetopt/cli optimize .

No global install needed — npx fetches the CLI on first run. Your originals are never touched; results land in ./optimized.

FAQ

Questions before you install.

Three of the most common ones below. The full FAQ covers integration edge cases.

Is it safe to enable the web-perf preset in production?
Yes, in two of the three supported workflows. If a bundler wraps your assets (Vite, Next, Astro…), it rewrites references safely — go ahead. Same for asset prep when you write the HTML yourself afterward. The one case to avoid is hand-written static sites where images are referenced by literal filename — there, set formatMatrix to "keep" per format so extensions are preserved.
How is this different from TinyPNG, imagemin, or Squoosh?
Three things. It runs locally with no upload or account — your assets stay on your machine. It handles four asset types in one command (images, CSS, JS, SVG), so you don't glue four tools yourself. And the incremental cache means re-runs only process changed files, which makes it practical to put inside CI.
Will the incremental cache actually save time in CI?
On a typical re-deploy where you touched two or three assets, the cache skips the rest — runs drop from minutes to seconds. The manifest hashes source bytes, resolved config, and the @assetopt/core version, so it self-invalidates when anything that matters changes. Persist the .assetopt-cache.json file across CI runs and it keeps paying off.