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 🙏

© 2025 – Pkg Stats / Ryan Hefner

croppix

v2.1.0

Published

[![Docker Pulls](https://img.shields.io/docker/pulls/asterixcapri/croppix)](https://hub.docker.com/r/asterixcapri/croppix) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](https://www.tldrlegal.com/license/mit-license) [![GitHub stars]

Readme

Croppix

Docker Pulls License: MIT GitHub stars

Croppix is an open-source image processing service based on Sharp and Amazon Rekognition, allowing dynamic generation of cropped and optimized images directly from URL parameters, with intelligent caching support on AWS S3.

The smart crop feature uses Amazon Rekognition to detect the main subject in an image, ensuring the most important content is always visible in the cropped result.

Croppix is designed to be integrated into high-performance websites, serving optimized images directly from a CDN (like CloudFront), with automatic fallback to a processing server when cache is missed.

🔍 Table of Contents

🚀 Architecture and Production Deployment

Croppix typically runs as a Node.js service behind an Ingress (NGINX or ALB), with original images stored in an S3 bucket (AWS_BUCKET) and processed images stored in a separate bucket (AWS_BUCKET_CACHE).

Docker is recommended for deployment, along with CDN integration such as CloudFront.

🔄 How it Works in Production

  1. A user requests an image from CloudFront, for example:

    https://your-cloudfront-distribution.net/photos/image123.jpg/w240_h160_csmart.webp
  2. CloudFront checks the S3 cache bucket:

    • ✅ If the image exists, it serves it immediately
    • 🚫 If it doesn't exist (404 or 403), it falls back to Croppix
  3. Croppix receives the request and processes the image:

    • Fetches it from the source bucket (AWS_BUCKET)
    • Applies the requested transformations
    • Stores the result in AWS_BUCKET_CACHE
    • Returns the image to CloudFront
  4. CloudFront caches the image for future requests

🔧 Features and Quick Start with Docker

Croppix is also available as a Docker container:

👉 https://hub.docker.com/r/asterixcapri/croppix

You can run the container with:

docker run -p 3003:3003 \
  -e AWS_ACCESS_KEY_ID=xxx \
  -e AWS_SECRET_ACCESS_KEY=xxx \
  -e AWS_REGION=us-east-1 \
  -e AWS_BUCKET=your-source-bucket \
  -e AWS_BUCKET_CACHE=your-cache-bucket \
  asterixcapri/croppix:latest

Croppix is designed to work behind a CloudFront distribution with two origins:

  1. Primary origin: S3 bucket AWS_BUCKET_CACHE (with cached processed images)
  2. Secondary origin (fallback): https://your-croppix-domain.com (Croppix processor)

📊 Architecture Benefits

  • 🤖 AI-powered smart crop using Amazon Rekognition for subject detection
  • ⚡ High performance via CloudFront + S3
  • 👊 Croppix server is hit only on cache misses
  • 📆 Fully cacheable and URL-customizable images
  • 🚪 Robust system with automatic fallback
  • ✨ On-demand image generation via URL
  • 📁 Integration with AWS S3 for source and cache
  • ⚡ Output in WebP, JPEG, PNG and more
  • 🔄 Smart crop, resize, retina scaling, cache busting
  • ⚙ Docker-ready

📂 URL Parameters for Image Transformations

A Croppix image request looks like this:

https://your-croppix-domain.com/<image-path>/<transform-params>.<format>

✅ Example

https://your-croppix-domain.com/photos/image123.jpg/w400_h300_d2_csmart_u1712345678.webp

Supported Parameters

| Parameter | Description | |------------------|-------------| | w{width} | Width in pixels (e.g., w240) | | h{height} | Height in pixels (e.g., h160) | | s{shortSide} | Fit to the shortest side | | l{longSide} | Fit to the longest side | | c{crop} | Crop type (see below) | | q{quality} | Output quality (e.g., q80) | | d{density} | Retina scale factor, e.g., d2 | | u{updatedAt} | Cache busting timestamp (e.g., u1684485984) | | .webp, .jpeg, .png | Output format |

Parameters can be combined with _ and used in any order.

Validation & HTTP Status Codes

  • If the URL is syntactically invalid, the format is not supported, or a parameter is out of range, Croppix returns 404 Not Found.
    • Examples: w{width} / h{height} / s{shortSide} / l{longSide} > maxDimension, d{density} outside [1.0, maxDensity], unsupported c{crop} or q{quality}.
  • If the source image key does not exist in S3, Croppix returns 404 Not Found.
  • Any internal processing error (Sharp, Rekognition, or other runtime errors) results in 500 Internal Server Error.

Tip: To get the original image without any transformations, use /original:

  • https://your-croppix-domain.com/photos/image123.jpg/original (same format as source)

✂️ Supported Crop Types (c{crop})

Croppix supports the following crop modes via the c{crop} parameter.

Note: The smart crop uses Amazon Rekognition to detect objects in the image. If no subject is detected (e.g., abstract images or landscapes without distinct objects), it automatically falls back to Sharp's attention strategy.

| Value | Description | |---------------|----------------------------------------------------------------------------------| | smart | AI-powered smart crop using Amazon Rekognition to detect the main subject | | none | No crop: resize and fill with the average background color | | entropy | Crop area with highest entropy (Sharp) | | attention | Crop area with visual attention (Sharp) | | fit | Fit image within dimensions without cropping | | center | Center crop | | top | Crop from the top | | bottom | Crop from the bottom | | left | Crop from the left | | right | Crop from the right | | leftTop | Crop from top-left corner | | rightTop | Crop from top-right corner | | leftBottom | Crop from bottom-left corner | | rightBottom | Crop from bottom-right corner |

ℹ️ Optional JavaScript Example

To dynamically generate Croppix URLs in a frontend app:

const croppixBaseUrl = 'https://your-croppix-domain.com';

export const croppixUrl = (path, params = {}) => {
  if (!path) return '';
  return croppixBaseUrl + encodeURI(path) + formatParams(params);
};

const formatParams = (params = {}) => {
  const parts = [];
  if (params?.width) parts.push(`w${params.width}`);
  if (params?.height) parts.push(`h${params.height}`);
  if (params?.shortSide) parts.push(`s${params.shortSide}`);
  if (params?.longSide) parts.push(`l${params.longSide}`);
  if (params?.crop) parts.push(`c${params.crop}`);
  if (params?.quality) parts.push(`q${params.quality}`);
  if (params?.density) parts.push(`d${params.density}`);
  if (params?.updatedAt) parts.push(`u${params.updatedAt}`);

  if (parts.length === 0) return '/original';
  return '/' + parts.join('_') + '.' + (params?.format || 'jpeg');
};

🧑‍💻 Local Development Setup

Requirements

  • Docker installed
  • Two S3 buckets:
    • AWS_BUCKET for original images
    • AWS_BUCKET_CACHE for processed images

Everything else is handled by the provided Docker container.

Installation and Start

git clone https://github.com/asterixcapri/croppix.git
cd croppix
cp .env.dist .env
docker compose up -d
docker compose exec node bash
yarn install
yarn dev

Environment Variables

You can create a .env file in the project root with:

AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key
AWS_REGION=your-region
AWS_BUCKET=your-source-bucket
AWS_BUCKET_CACHE=your-cache-bucket

The Docker container will automatically load these variables if referenced in docker-compose.yml.

IAM Permissions

The AWS credentials must have the following permissions:

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:PutObject"
      ],
      "Resource": [
        "arn:aws:s3:::your-source-bucket/*",
        "arn:aws:s3:::your-cache-bucket/*"
      ]
    },
    {
      "Effect": "Allow",
      "Action": "rekognition:DetectLabels",
      "Resource": "*"
    }
  ]
}

The rekognition:DetectLabels permission is required for the smart crop feature.

💬 Support & Contributions

Found a bug or want to add a feature?

Open an Issue or a Pull Request.

⚖️ License

Distributed under the MIT license.


Developed by Alessandro Astarita