A high-performance image optimization service built with Bun and TypeScript. This service handles image optimization through WebP conversion, width resizing, and quality control. Perfect for reducing image sizes while maintaining quality in web applications.
- 🖼️ WebP conversion for optimal compression
- 📏 Dynamic image resizing
- 🎯 Adjustable quality settings
- ⚡ High-performance Bun runtime
- 🔄 Auto-reload in development mode
- ☁️ Cloudflare R2 storage integration
- 🔄 Redis caching (optional)
- Bun runtime (for local development)
- Node.js environment (for local development)
- Cloudflare R2 account and bucket (for cloud storage)
- Redis service (for production caching)
cp .env.example .envRequired environment variables:
# Redis Configuration (for production - set up in Coolify)
REDIS_URL=redis://localhost:6379
# Cloudflare R2 Configuration
R2_ACCOUNT_ID=your_account_id
R2_ACCESS_KEY_ID=your_access_key_id
R2_SECRET_ACCESS_KEY=your_secret_access_key
R2_BUCKET_NAME=your_bucket_name
R2_REGION=auto- Install Bun if not already installed:
curl -fsSL https://bun.sh/install | bash- Install dependencies:
bun installFor development in watch mode:
bun devFor production (requires build first):
bun build
bun start# Build and run with docker-compose
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose downBuild the project:
bun buildType checking and linting:
bun lintFormat code:
bun formatThe service will be available at:
http://localhost:3000
- Go to your Coolify dashboard
- Create a new "Database" service
- Choose Redis
- Note the service name (e.g.,
redis-service)
- Create a new application in Coolify
- Connect your Git repository
- Set build command:
bun build - Set start command:
bun run dist/server.js - Set port:
3000
Set these environment variables in your Coolify app:
# Redis Configuration
REDIS_URL=redis://your-redis-service-name:6379
# Cloudflare R2 Configuration
R2_ACCOUNT_ID=your_account_id
R2_ACCESS_KEY_ID=your_access_key_id
R2_SECRET_ACCESS_KEY=your_secret_access_key
R2_BUCKET_NAME=your_bucket_name
R2_REGION=auto
In your app settings, link the Redis service as a dependency for better service discovery.
The service exposes a single endpoint for image optimization:
Path Parameters:
src(required): Source URL of the image to optimize or the R2 bucket key of the image
Query Parameters:
w(optional): Desired width in pixelsq(optional): WebP quality (0-100, default: 75)
Example Request:
http://localhost:3000/url-encoded-image-link?w=800&q=80
http://localhost:3000/images/photo.jpg?w=800&q=80
The service will:
- If the parameter
srcis a URL, fetch the image from the provided URL, if not, retrieve the image from the configured R2 bucket using the key - Check if the image is already in the Redis cache, if it is, return the cached image
- If the image is not in the cache, optimize it by resizing it to the specified width (if provided) and converting it to WebP format
- Cache the optimized image in Redis
- Return the optimized image
The service leverages:
- TypeScript for type safety
- Bun's native features:
- Fast JavaScript/TypeScript runtime
- Built-in fetch API
- Built-in S3 client for R2 integration
- Built-in Redis client
- File watching
- Package management
- Redis for caching optimization results
- Cloudflare R2 for scalable cloud storage
- Create a Cloudflare R2 bucket
- Generate API tokens with appropriate permissions
- Configure the following environment variables:
R2_ACCOUNT_ID: Your Cloudflare account IDR2_ACCESS_KEY_ID: R2 API token access keyR2_SECRET_ACCESS_KEY: R2 API token secret keyR2_BUCKET_NAME: Your R2 bucket nameR2_REGION: Region (typically "auto" for R2)
Images are stored in your R2 bucket using the key provided in the request. For example:
- Request:
/images/photo.jpg→ R2 key:images/photo.jpg - Request:
/products/thumbnail.png→ R2 key:products/thumbnail.png
WebP format provides:
- Superior compression compared to JPEG/PNG
- Smaller file sizes with quality retention
- Support for lossy and lossless compression
- Broad browser compatibility
R2 storage provides:
- Global edge caching
- High availability and durability
- Cost-effective storage
- S3-compatible API
Contributions are welcome! Feel free to open issues and pull requests.
This project is open source and available under the MIT License.
Paul George - contact@paulgeorge.dev
Project Link: https://github.com/paulgeorge35/image-optimizer