Dynamic Image Resizing and Gallery Server
by Kuligaposten 2026-01-18
In this guide, we’ll walk through a Node.js Express server that handles image resizing, caching, and album management. This script provides a backend for photo galleries with optimized image delivery, caching, and album pagination.
1. Overview
This server provides:
- A dynamic image resizing API that fetches images from remote HTTPS URLs, resizes them with
sharp, caches the results, and serves them in WebP format. - An album management system that reads local directories under
public/albumsand serves album metadata and images via a RESTful API. - Pagination support for album images.
- Built-in CORS support and static file serving for front-end integration.
2. Key Dependencies
The script uses the following libraries:
- express – Web server framework.
- cors – Enable Cross-Origin Resource Sharing.
- fs & fs/promises – File system operations.
- path – Path utilities.
- sharp – High-performance image processing.
- crypto – For caching keys.
- flickrRoutes – A custom module (not included here) for Flickr integration.
3. Configuration
const IMAGE_CACHE_DIR = path.join(process.cwd(), "cache", "images");
const MAX_WIDTH = 2560;
const DEFAULT_QUALITY = 80;
const FETCH_TIMEOUT = 15000;
IMAGE_CACHE_DIR: Directory where resized images are cached.MAX_WIDTH: Maximum width to resize images.DEFAULT_QUALITY: Default WebP compression quality.FETCH_TIMEOUT: Timeout for fetching remote images.
The cache directory is created if it doesn’t exist:
if (!fs.existsSync(IMAGE_CACHE_DIR)) {
fs.mkdirSync(IMAGE_CACHE_DIR, { recursive: true });
}
4. Utility Functions
Two key utility functions:
function isValidHttpsUrl(url) {
try {
return new URL(url).protocol === "https:";
} catch {
return false;
}
}
function imageCacheKey(url, width, quality, dpr) {
return crypto
.createHash("sha1")
.update(`${url}|${width}|${quality}|${dpr}`)
.digest("hex");
}
isValidHttpsUrl: Ensures only HTTPS images are allowed.imageCacheKey: Generates a unique hash for caching resized images based on URL, width, quality, and device pixel ratio (DPR).
5. Dynamic Image Resizing Endpoint
Endpoint: GET /resize
Query parameters:
url– HTTPS image URL.width– Desired width.quality– WebP compression quality.dpr– Device Pixel Ratio multiplier.
Workflow:
- Validate URL and parameters.
- Check if the image exists in cache.
- If not cached, fetch the image with timeout support.
- Validate response content type.
- Resize using
sharpand convert to WebP. - Save to cache and return the image.
res.set({
"Content-Type": "image/webp",
"Cache-Control": "public, max-age=31536000, immutable",
"Access-Control-Allow-Origin": "*",
});
This ensures long-term caching and CORS-friendly delivery.
6. Albums API
The server dynamically reads albums stored in public/albums.
6.1 List All Albums
Endpoint: GET /api/albums
- Returns metadata for all albums, including cover image, count, and URL.
- Supports absolute URLs with the
absolute=1query parameter. - Covers are automatically picked from thumbnails (
thumb) if available.
6.2 Album Images with Pagination
Endpoint: GET /api/albums/:album
- Supports
pageandlimitquery parameters for pagination. - Includes image metadata (width, height, thumbnail URL, last modified date).
- Sorts images by modification date.
- Automatically matches thumbnails to full-size images.
Example response:
{
"images": [
{
"src": "/albums/vacation/photo1.jpg",
"thumb": "/albums/vacation/photo1-thumb.jpg",
"alt": "Gallery: vacation",
"date": "March 9, 2026",
"bigWidth": 2048,
"bigHeight": 1365,
"thumbWidth": 500,
"thumbHeight": 400
}
],
"pagination": {
"page": 1,
"limit": 20,
"total": 100,
"totalPages": 5,
"hasNextPage": true,
"hasPrevPage": false
}
}
7. Error Handling & 404
- Returns meaningful HTTP status codes for invalid URLs, missing albums, or server errors.
- A catch-all 404 endpoint:
app.use((req, res) => {
res.status(404).json({ error: "Not found" });
});
8. Starting the Server
app.listen(port, () => {
console.log(`Server running at http://localhost:${port}`);
});
The server listens on port 3023 by default and logs a confirmation message.
9. Benefits of This Approach
- Optimized delivery: WebP conversion and resizing reduce bandwidth.
- Caching: Avoids repeated processing for the same image.
- Flexible albums: Easily extendable for local galleries or integrations like Flickr.
- Pagination-ready: Efficient for large galleries.
10. Next Steps
- Add authentication for private galleries.
- Integrate CDN support for caching remote images.
- Enhance error reporting for better monitoring.
- Add image transformations like cropping, filters, or watermarking.
This script forms a solid foundation for a high-performance image gallery backend that can serve both web and mobile clients efficiently.