npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@adaptive-ds/assets-optimizer

v0.6.0

Published

Process and sync web project images and videos between local folders and R2

Downloads

1,084

Readme

@adaptive-ds/assets-optimizer

Process, hash, sync, and clean image assets for web projects that keep originals outside git and optionally sync through any rclone remote, with a separate pass for web videos.

Features

  • originals may live on an rclone remote and be synced locally
  • optimized outputs should be deterministic and aggressively cacheable
  • output filenames should change when either the source file or the transform changes
  • old optimized files should be removed locally and remotely
  • generates type-safe imageList.ts and videoList.ts should stay in sync with processed assets

Quick link

  • code - https://github.com/david1gp/assets-optimizer
  • npm - https://www.npmjs.com/package/@adaptive-ds/assets-optimizer

Diagrams

Overview

Overview

Images

Image process

Videos

Video process

What It Does

processAssets() orchestrates the full workflow:

  1. Syncs originals from remote source to local images and videos folders via rclone bisync
  2. Runs assetsOptimize() to process images and videos locally
  3. Uploads optimized assets to s3-compatible remote destination with caching headers

assetsOptimize() performs the core asset processing:

  1. Resolves the project name from package.json.name
  2. If rcloneRemote is configured, uses that project name as the base path on the remote
  3. If rcloneRemote is configured, syncs originals between the remote and images
  4. Scans transform folders like 1920x1080_jpg
  5. Processes matching image source files with sharp
  6. Writes flat optimized images into public/images
  7. Names image files as <basename>_<hash>.<ext>
  8. Skips already-generated images
  9. Deletes stale optimized images locally
  10. If rcloneRemote is configured, uploads missing optimized images to the remote with cache headers
  11. If rcloneRemote is configured, deletes stale optimized images from the remote
  12. Runs a separate optional video pass from videos to public/videos
  13. Generates a .jpg preview beside each processed video using the processed video dimensions
  14. Keeps video filenames unchanged and skips any processed video or preview that already exists
  15. If rcloneRemote is configured, uploads missing processed videos and previews to the remote without deleting manual variants
  16. Generates src/app/assets/imageList.ts and src/app/assets/videoList.ts by default
  17. Prints a clear summary of what changed

The hash is derived from:

  • source file bytes
  • normalized transform spec

That means image cache keys change when the source image changes or when you change the folder rule, even if the output filename format stays short.

Folder Convention

Original files belong in transform folders inside images.

Example:

images/
  1920x1080_jpg/
    living-room.png
  1200x1200_webp/
    kitchen.jpg

This produces flat optimized image output like:

public/images/
  kitchen_a1b2c3d4.jpg
  living-room_9f8e7d6c.jpg
  kitchen_7c6b5a4d.webp

Root-level files directly inside images are intentionally skipped and warned on every run.

Videos are handled separately and do not use transform folders:

videos/
  hero.mp4
  intro.webm

public/videos/
  hero.mp4
  hero.jpg
  intro.webm
  intro.jpg

Video behavior:

  • if both local videos and remote video-originals are missing, the video pass does nothing
  • if rcloneRemote is configured, source videos sync through video-originals
  • if rcloneRemote is configured, processed videos sync through video-processed
  • missing processed videos are created with ffmpeg
  • missing preview images are created as .jpg files beside processed videos
  • existing processed videos are skipped and preserved as manual transformations
  • existing preview images are skipped and preserved
  • video filenames and relative paths are kept as-is
  • stale processed videos are not deleted

Transform Folder Format

Folder names must use:

<width>x<height>_<format>

Supported image output formats:

  • jpg

  • png

  • webp Examples:

  • 1920x1080_jpg

  • 1600x900_webp Image processing behavior:

  • resize fit: inside / max-bounds scaling

  • withoutEnlargement: true

  • image auto-rotation is applied

  • default quality is 80

Supported video source extensions:

  • mp4
  • mov
  • m4v
  • webm
  • avi
  • mkv

Installation

bun add -D @adaptive-ds/assets-optimizer

Basic Usage

Example project entrypoint:

import { assetsProcess } from "@adaptive-ds/assets-optimizer"

await assetsProcess()

This generates optimized images, processed videos, video preview JPGs, imageList.ts, and videoList.ts in one run.

Existing image alt text and existing video preview alt text are preserved when the generated files already exist.

Local folders

This package is built for a workflow with two local directories:

  • images: original source images, never modified
  • public/images: generated optimized images, flat output only
  • videos: original source videos, optional
  • public/videos: processed videos, optional

Optimization

Images

  • Source images live in transform folders like 1920x1080_jpg inside images/
  • Each source file is resized to fit within the specified bounds without enlargement
  • Auto-rotation is applied based on EXIF data
  • Output quality defaults to 80%
  • Files are named using a hash of the source content and transform spec
  • Existing optimized files are skipped unless their source changed
  • Stale optimized files (from deleted sources or changed transforms) are removed
  • A TypeScript list file is generated with all processed image references

Videos

  • Source videos live directly in videos/ (no transform folders)
  • Each video is copied to the output directory using ffmpeg
  • A JPEG preview is generated beside each processed video
  • Existing processed videos and previews are preserved as-is
  • A TypeScript list file is generated with all processed video references

Requirements

  • bun
  • rclone
  • ffmpeg
  • an existing rclone remote
  • write access to the target bucket/path
  • Node/Bun environment capable of running sharp

This package assumes the remote bucket/path already exists or can be created by rclone mkdir.

Cleanup Behavior

The package does not use a manifest.

Instead it derives the expected output set from the current originals and current transform folders, then reconciles that against:

  • local public/images
  • remote images/optimized objects

That means:

  • files no longer produced by the current source set are deleted
  • renaming or removing a source file cleans up stale optimized files
  • changing a transform folder causes a different hash and a different output filename

Recommended Workflow

  1. Add or sync originals into images/<transform-folder>/
  2. Run your local image pipeline entrypoint
  3. Regenerate your typed image list
  4. Reference the generated hashed filenames from app code or derived metadata

Important Caveat

If your project currently stores source images directly at the root of images, this package will skip them by design.

Before adopting it fully, move originals into explicit transform folders such as:

images/1920x1080_jpg/

That contract is what makes the output deterministic and safe to clean automatically.

License

MIT