- Switch from Node.js ONNX to production Python ML libraries: rembg, Real-ESRGAN, LaMa, PaddleOCR, MediaPipe - AI models baked into Docker image for instant reliability - Multi-architecture support (linux/amd64 + linux/arm64) - No Docker size limits - reliability over size (expect 3-5GB) - Object Eraser upgraded from experimental to production (LaMa) - All AI tools now use state-of-the-art models
47 KiB
Stirling-Image: Product Requirements Document
Version: 1.0 Status: Finalized Date: 2026-03-22
1. Executive Summary
Stirling-Image is an open-source, self-hostable image manipulation suite. Inspired by the philosophy and UX of Stirling-PDF, it provides a comprehensive "Swiss Army Knife" for image processing that is 100% private, simple for non-coders, and powerful for power users.
It eliminates the need for ad-heavy, privacy-invasive online image converters (TinyPNG, Remove.bg, Canva) by providing a professional-grade, self-hostable alternative deployable with a single Docker command.
The one-liner (works on Intel, AMD, and Apple Silicon):
docker run -d -p 1349:1349 -v ./data:/data stirlingtools/stirling-image:latest
2. Vision & Philosophy
- Privacy First: 100% data sovereignty. All processing happens on the host server. No telemetry, no external API calls. The FBI has warned about malicious online converters - we are the safe alternative.
- "It Just Works": Single Docker container. No Redis, no PostgreSQL, no Python runtime required. One command to deploy.
- Zero Learning Curve: A non-technical user should complete any task in under 3 clicks. The UI follows the proven Stirling-PDF pattern.
- "Stirling-PDF but for Images": This is an unspoken gap in the self-hosted community. Multiple tools have tried (imgcompress, ConvertX, OmniTools) but none has achieved Stirling-PDF's level of polish. We fill that gap.
- Full Product, Not MVP: Every feature is built to production quality from day one.
3. Target Audience
| Audience | Need |
|---|---|
| Privacy-Conscious Individuals | Don't want to upload personal photos to "free" online converters |
| Content Creators / Social Media Managers | Batch-resize, watermark, compress 20+ images for multiple platforms |
| Self-Hosters / Homelabbers | Want a "Stirling-PDF equivalent" for their media library |
| Developers | Need a quick API or UI for web optimization (WebP/AVIF conversion, favicon generation) |
| Photographers | Batch processing, EXIF stripping, format conversion, duplicate detection |
| Small Businesses | Watermarking, branding, social media asset preparation |
4. Technology Stack
4.1 Finalized Stack
| Layer | Technology | Rationale |
|---|---|---|
| Frontend | Vite + React 19 + TypeScript | No SSR needed; faster builds; no Docker memory leaks (Next.js issue #88603) |
| UI Components | shadcn/ui + Tailwind CSS 4 | AI models generate excellent code; composable; accessible (Radix primitives) |
| Backend | Fastify | 30-40% faster than Express; built-in JSON validation; 30-50MB memory baseline |
| Image Engine | Sharp (libvips) + ImageMagick | Sharp: 4-8x faster than ImageMagick, handles 95% of operations. IM: fallback for edge cases |
| AI/ML | Python (embedded in same container) | State-of-the-art Python ML ecosystem for maximum reliability. rembg (U2Net/ISNet) for BG removal, Real-ESRGAN for upscaling, LaMa for inpainting, PaddleOCR for text extraction, MediaPipe/RetinaFace for face detection. Node.js calls Python scripts via child_process. Single container — no sidecar needed |
| Database | SQLite + Drizzle ORM | Zero config for self-hosters; Drizzle: 7.4KB runtime, faster than Prisma with SQLite |
| Job Queue | Worker threads + p-queue | In-process concurrency. No Redis container needed. Configurable concurrency limit |
| Authentication | Better-Auth | TypeScript-native; built-in 2FA, rate limiting, password policies; works with SQLite + Drizzle |
| Monorepo | Turborepo + pnpm | Efficient builds, shared packages, cache |
| Deployment | Docker (single container, multi-arch) | Multi-stage Debian build. Multi-architecture: linux/amd64 + linux/arm64 (Intel, AMD, Apple Silicon, ARM servers). No size limits — reliability over size. Includes Node.js, Python, Sharp, ImageMagick, Tesseract, libraw, all AI models |
| Storage | Adapter pattern | STORAGE_MODE=local (default) or STORAGE_MODE=s3 (future SaaS) |
4.2 Monorepo Structure
stirling-image/
├── apps/
│ ├── web/ # Vite + React SPA
│ │ ├── src/
│ │ │ ├── components/
│ │ │ │ ├── ui/ # shadcn/ui base components
│ │ │ │ ├── layout/ # Sidebar, Navbar, Dropzone, Footer
│ │ │ │ ├── tools/ # Tool-specific UI (CropSettings, CompressSettings, etc.)
│ │ │ │ └── common/ # BeforeAfterSlider, ImagePreview, FileUpload
│ │ │ ├── pages/ # Route pages (Login, Home, Tool pages, Settings)
│ │ │ ├── hooks/ # Custom React hooks
│ │ │ ├── stores/ # Zustand stores (files, settings, theme)
│ │ │ ├── lib/ # API client, utils, i18n setup
│ │ │ └── styles/ # Tailwind config, global styles
│ │ ├── public/ # Static assets, icons
│ │ └── index.html
│ │
│ └── api/ # Fastify backend
│ ├── src/
│ │ ├── routes/ # API route handlers (one per tool)
│ │ ├── services/ # Business logic (compress, resize, crop, etc.)
│ │ ├── workers/ # Worker thread scripts for heavy processing
│ │ ├── plugins/ # Fastify plugins (auth, cors, upload, swagger)
│ │ ├── middleware/ # Rate limiting, file validation
│ │ ├── db/ # Drizzle schema, migrations
│ │ └── lib/ # Storage adapter, cleanup cron, utils
│ └── models/ # AI model cache directory (gitignored)
│
├── packages/
│ ├── shared/ # Shared TypeScript types, constants, i18n keys
│ ├── image-engine/ # Sharp + ImageMagick wrapper library
│ │ ├── src/
│ │ │ ├── operations/ # resize.ts, crop.ts, compress.ts, convert.ts, etc.
│ │ │ ├── formats/ # Format-specific handlers (heic, svg, gif, etc.)
│ │ │ └── utils/ # Metadata, hashing, color extraction
│ │ └── index.ts
│ └── ai/ # Python ML bridge — TS wrappers calling Python scripts
│ ├── src/
│ │ ├── bridge.ts # Generic Python child_process executor
│ │ ├── background-removal.ts # Calls rembg (U2Net/ISNet)
│ │ ├── upscaling.ts # Calls Real-ESRGAN
│ │ ├── inpainting.ts # Calls LaMa via lama-cleaner
│ │ ├── ocr.ts # Calls PaddleOCR + Tesseract
│ │ ├── face-detection.ts # Calls MediaPipe / RetinaFace
│ │ └── smart-crop.ts # Calls MediaPipe saliency
│ ├── python/ # Python scripts (run in venv inside Docker)
│ │ ├── remove_bg.py
│ │ ├── upscale.py
│ │ ├── inpaint.py
│ │ ├── ocr.py
│ │ ├── detect_faces.py
│ │ └── requirements.txt # All Python ML dependencies
│ └── index.ts
│
├── docker/
│ ├── Dockerfile # Multi-stage production build
│ └── docker-compose.yml # For development
│
├── turbo.json # Turborepo config
├── pnpm-workspace.yaml
├── package.json
├── LICENSE # MIT (open-core model)
├── README.md
├── CHANGELOG.md
└── PRD.md # This document
4.3 Docker Architecture
Single container deployment (like Stirling-PDF):
# docker-compose.yml (for users who prefer compose)
services:
stirling-image:
image: stirlingtools/stirling-image:latest
container_name: stirling-image
ports:
- "1349:1349"
environment:
- AUTH_ENABLED=true
- DEFAULT_USERNAME=admin
- DEFAULT_PASSWORD=admin
- STORAGE_MODE=local
- FILE_MAX_AGE_HOURS=24
- CLEANUP_INTERVAL_MINUTES=30
- MAX_UPLOAD_SIZE_MB=100
- MAX_BATCH_SIZE=200
- CONCURRENT_JOBS=3
# S3 Config (ignored if STORAGE_MODE=local)
- S3_BUCKET=
- S3_REGION=
- S3_ACCESS_KEY=
- S3_SECRET_KEY=
volumes:
- ./data:/data # SQLite DB + settings
- ./workspace:/tmp/workspace # Temporary file processing
restart: unless-stopped
Dockerfile strategy:
- Multi-stage build (builder → production)
- Base:
node:22-bookworm(full Debian, NOT slim/Alpine — maximum compatibility and native lib support) - Multi-architecture:
docker buildxwith--platform linux/amd64,linux/arm64(works on Intel Mac, Apple Silicon, AMD, ARM servers, Raspberry Pi 4+) - Install ALL dependencies for maximum reliability:
- Node.js 22 + pnpm
- Python 3.12 + pip + venv (for AI/ML)
- Sharp (compile libvips from source with libheif/libde265/x265 for full HEIC support)
- ImageMagick 7 (for edge case format handling)
- Tesseract 5 + language packs (for OCR)
- libraw (for camera RAW format support)
- libjxl (for JPEG XL support)
- potrace + vtracer (for image vectorization)
- Python ML packages (installed in venv):
rembg[gpu,cpu]— background removal (U2Net, ISNet models)realesrgan— image upscaling (Real-ESRGAN models)lama-cleaner— object erasing / inpainting (LaMa model)paddleocr— OCR (more accurate than Tesseract alone)mediapipe— face detection, landmark detectiononnxruntime— ONNX model inference backend
- AI models baked into the image for instant availability (no first-use download delay). Reliability over size.
- Production: Fastify serves both API routes and the Vite-built SPA as static files
- No Docker size limits — expect 3-5GB image. Reliability and cross-platform support are the priority.
4.4 SQLite Configuration
Critical settings applied on every connection:
PRAGMA journal_mode = WAL; -- Concurrent reads during writes
PRAGMA busy_timeout = 5000; -- Retry on contention instead of failing
PRAGMA synchronous = NORMAL; -- Balance between safety and speed
PRAGMA foreign_keys = ON; -- Enforce referential integrity
Database file stored at /data/stirling.db (Docker volume mounted).
5. Complete Feature Set
5.1 Category: Essentials
| # | Tool | Description | Controls |
|---|---|---|---|
| E-01 | Resize | Resize by exact pixels, percentage, or social media presets | Width/height inputs, aspect ratio lock, preset dropdown (Instagram, Twitter/X, Facebook, YouTube, LinkedIn, TikTok, WhatsApp), fit mode (contain/cover/fill) |
| E-02 | Crop | Freeform crop, aspect ratio presets, shape crop | Drag handle crop area, aspect ratio presets (1:1, 4:3, 16:9, 2:3, 4:5, 9:16), circular crop, rounded corners, custom shape masks |
| E-03 | Rotate & Flip | 90-degree rotations, horizontal/vertical flip, arbitrary angle | Rotate left/right buttons, flip H/V buttons, angle slider (0-360), rotation preview |
| E-04 | Format Convert | Convert between all supported formats | Source format auto-detected, target format dropdown, format-specific quality options |
| E-05 | Compress | Reduce file size by quality % or target file size | Compression method toggle (Quality / File Size), quality slider (1-100), target size input (KB/MB), before/after preview with file size comparison |
5.2 Category: Optimization
| # | Tool | Description | Controls |
|---|---|---|---|
| O-01 | Strip Metadata | Remove EXIF, GPS, camera info, timestamps | Checkboxes: EXIF, GPS, Camera, ICC Profile, XMP, IPTC. Option to keep specific fields. Preview of metadata before/after |
| O-02 | Bulk Rename | Rename multiple files with patterns | Pattern input (e.g., vacation-{{index}}), preview of new names, date-based naming from EXIF |
| O-03 | Image to PDF | Combine multiple images into a single PDF | Drag to reorder, page size selection (A4, Letter, custom), orientation, margins, images per page |
| O-04 | Favicon Generator | Generate all favicon/icon sizes from one image | Auto-generates: favicon.ico (16/32/48), Apple Touch (180), Android Chrome (192/512), manifest.json. Download as zip |
5.3 Category: Adjustments
| # | Tool | Description | Controls |
|---|---|---|---|
| A-01 | Brightness & Contrast | Adjust brightness, contrast levels | Sliders (-100 to +100), real-time preview, reset button |
| A-02 | Saturation & Exposure | Adjust color saturation and exposure | Sliders (-100 to +100), real-time preview |
| A-03 | Color Channels | Adjust individual R, G, B channels | Per-channel sliders (0-200%), percentage display |
| A-04 | Color Effects | Grayscale, Sepia, Invert, Tint | Effect buttons with intensity sliders where applicable |
| A-05 | Replace & Invert Color | Replace specific color with another, full invert | Color picker with eyedropper, tolerance slider, source → target color selection |
5.4 Category: AI Tools
All AI tools use state-of-the-art Python ML models called from Node.js via child_process. Models are baked into the Docker image for instant reliability — no download-on-first-use delays.
| # | Tool | Description | Model / Engine | Controls |
|---|---|---|---|---|
| AI-01 | Background Removal | AI-powered subject isolation | rembg with U2Net (general) + ISNet (high detail) models. User can select model. | One-click process, output: transparent PNG. Option to replace background with solid color or image. Model selection (U2Net/ISNet). Batch support |
| AI-02 | Image Upscaling | AI super-resolution enhancement | Real-ESRGAN (x2, x4 models). RealESRGAN_x4plus for photos, RealESRGAN_x4plus_anime for illustrations. | Scale factor (2x, 4x), model type (photo/illustration), before/after slider preview |
| AI-03 | Object Eraser | Paint over unwanted elements, AI fills the gap | LaMa (Large Mask Inpainting) via lama-cleaner. Production-grade Python library. | Brush tool with adjustable size, paint-to-erase interface, inpainting preview |
| AI-04 | OCR / Text Extraction | Extract text from images | PaddleOCR (primary, 80+ languages, higher accuracy) + Tesseract 5 (fallback). | Language selection, engine choice (PaddleOCR/Tesseract), output format (plain text / structured JSON), copy-to-clipboard, download as .txt/.json |
| AI-05 | Face / PII Blur | Auto-detect and blur faces, license plates, text | MediaPipe Face Detection (Google, real-time capable) + RetinaFace (higher accuracy option). | Detection sensitivity slider, blur intensity slider, model choice (fast/accurate), manual region selection for additional blurring |
| AI-06 | Smart Crop | AI detects subject and crops optimally | MediaPipe object/subject detection for saliency mapping. | Target aspect ratio, subject detection preview, manual adjustment |
5.5 Category: Watermark & Overlay
| # | Tool | Description | Controls |
|---|---|---|---|
| W-01 | Text Watermark | Add text overlay (semi-transparent, tiled or positioned) | Text input, font selection, size, color picker with eyedropper, opacity slider, position (center/corners/tiled), rotation angle |
| W-02 | Image Watermark | Overlay a logo/image as watermark | Upload watermark image, position, opacity, scale, tiled repeat option |
| W-03 | Text Overlay | Add styled text directly to images (non-watermark) | Font selection, size, position (drag), color, shadow, outline, background box |
| W-04 | Image Composition | Layer one image on top of another | Position control (drag), opacity slider, blend mode, resize overlay |
5.6 Category: Utilities
| # | Tool | Description | Controls |
|---|---|---|---|
| U-01 | Image Info / Inspector | Show all metadata and image properties | Display: dimensions, DPI, color space, file size, format, bit depth. EXIF data (camera, GPS, date). Color histogram |
| U-02 | Image Compare | Side-by-side comparison of two images | Upload two images, side-by-side view, overlay slider (before/after style), difference highlight |
| U-03 | Find Duplicates | Detect duplicate/near-duplicate images using dHash (difference hash) perceptual hashing for speed + accuracy balance | Batch upload, similarity threshold slider (80-100%), grouped results with side-by-side preview, keep best/keep all/manual select |
| U-04 | Color Palette Extraction | Extract dominant colors from image | Number of colors (3-10), display HEX/RGB/HSL values, export as CSS variables, JSON, or Tailwind config |
| U-05 | QR Code Generator | Generate QR code images from text/URL | Text/URL input, size, error correction level, foreground/background color, download as PNG/SVG |
| U-06 | Barcode Reader | Read QR codes and barcodes from images | Upload image with barcode, auto-detect and display decoded text, copy to clipboard |
5.7 Category: Layout & Composition
| # | Tool | Description | Controls |
|---|---|---|---|
| L-01 | Collage / Grid Maker | Combine multiple images into a grid | Layout presets (2x2, 3x3, 1x3, 2x1, custom), gap/padding, background color, drag to reorder |
| L-02 | Image Splitting | Split one image into a grid of parts | Grid selector (2x2, 3x3, 1x3 for Instagram carousel), preview grid lines, download as zip |
| L-03 | Border & Frame | Add borders, rounded corners, shadows | Border width, color picker, corner radius, shadow (offset, blur, color), padding |
5.8 Category: Format & Conversion
| # | Tool | Description | Controls |
|---|---|---|---|
| F-01 | SVG to Raster | Convert SVG to PNG/JPG at custom resolution | Output resolution (width/height or scale factor), background color (transparent for PNG), output format |
| F-02 | Image to SVG | Vectorize raster images using algorithmic tracing (potrace/vtracer, NOT AI/ONNX) | Color mode (B&W / Color), detail level slider, smoothing, preview, download SVG |
| F-03 | GIF Tools | Resize/crop/convert animated GIFs preserving animation | All standard operations with animation preservation, frame count display, optimize GIF file size |
5.9 Category: Automation
| # | Tool | Description | Controls |
|---|---|---|---|
| P-01 | Pipeline Builder | Chain multiple tools into a workflow. Validated before execution: tools that output non-image data (OCR→text) cannot be followed by image-processing tools. Validation error shown inline. | Linear stack: Add Step dropdown → configure each step → reorder → process. Save as template |
| P-02 | Saved Automations | Save and reuse pipelines | Name, description, list of saved pipelines, suggested templates |
| P-03 | Batch Processing | Apply any tool to multiple images at once | Multi-file upload, progress bar per file, download all as zip, parallel processing |
Suggested Pipeline Templates
| Template | Steps |
|---|---|
| Social Media Ready | Resize to 1080x1080 → Compress to 200KB → Strip Metadata → Convert to WebP |
| Privacy Clean | Strip Metadata → Face Blur → Remove GPS → Compress |
| Web Optimization | Resize longest edge to 1920px → Convert to WebP → Compress 80% quality |
| Profile Picture | Circular Crop → Resize to 400x400 → Compress |
| Watermark Batch | Add Logo Watermark → Strip Metadata → Compress → Convert to JPG |
6. Supported Formats
6.1 Input Formats
| Format | Extension(s) | Notes |
|---|---|---|
| JPEG | .jpg, .jpeg | Universal |
| PNG | .png | With alpha channel |
| WebP | .webp | Including animated WebP |
| AVIF | .avif | Next-gen format |
| TIFF | .tif, .tiff | Multi-page support |
| BMP | .bmp | Legacy |
| GIF | .gif | Animated GIF support (all frames processed) |
| SVG | .svg | Rasterized on input via Sharp |
| HEIC/HEIF | .heic, .heif | iPhone photos (requires libheif in Docker) |
| JPEG XL | .jxl | Emerging format. Requires custom libvips build with libjxl - may be deferred if build complexity is too high |
| ICO | .ico | Favicon input |
| RAW | .cr2, .nef, .arw, .dng, .orf, .rw2 | Camera RAW. Requires libraw as explicit Docker dependency. Pre-processing step converts RAW → TIFF before Sharp processing |
6.2 Output Formats
| Format | Extension | Default Quality | Notes |
|---|---|---|---|
| JPEG | .jpg | 80% | Default output format |
| PNG | .png | Lossless | With optional compression level |
| WebP | .webp | 80% | Recommended for web |
| AVIF | .avif | 50 | Best compression ratio |
| TIFF | .tif | Lossless | Professional use |
| GIF | .gif | N/A | Animated output supported |
| JPEG XL | .jxl | 75 | Next-gen. Requires custom libvips build |
| SVG | .svg | N/A | Only via vectorization tool |
| ICO | .ico | N/A | Only via favicon generator |
| N/A | Only via Image-to-PDF tool |
7. UI/UX Architecture
7.1 Design Philosophy
Replicate the Stirling-PDF UX pattern exactly:
- Atomic tools: Each tool does one job. One click = one task done.
- 3-click rule: No more than 3 clicks from homepage to downloaded result.
- Consistent layout: Every tool page looks the same (upload → configure → process → download).
- Visual feedback: Before/after slider for relevant tools. Progress bars for batch operations.
7.2 Layout Components
Reverse-engineered from Stirling-PDF V2:
┌──────────────────────────────────────────────────────────────┐
│ [Icon] Search tools... [Theme] [Lang] [↓]│
│ Tool │
│ Name ┌─────────────────┬──────────────────────────────────┐│
│ │ │ ││
│ [Grid] │ Files ▼ │ ││
│ Tools │ ⬆ Upload │ ┌──────────────────────┐ ││
│ │ │ │ │ ││
│ [📖] │ Settings ▼ │ │ Stirling Image │ ││
│ Reader │ │ │ │ ││
│ │ [Tool-specific │ │ ⬆ Upload from │ ││
│ [🔄] │ controls: │ │ computer │ ││
│ Auto- │ sliders, │ │ │ ││
│ mate │ toggles, │ │ Drop files here │ ││
│ │ dropdowns] │ │ or click upload │ ││
│ [📁] │ │ │ or paste from │ ││
│ Files │ │ │ clipboard │ ││
│ │─────────────────│ │ or paste URL │ ││
│ │ │ └──────────────────────┘ ││
│ │ [Process] │ ││
│ ────── │ │ ││
│ [❓] │ │ ││
│ Help │ │ Survey · Privacy · Terms ││
│ [⚙️] └─────────────────┴──────────────────────────────────┘│
│Settings │
└──────────────────────────────────────────────────────────────┘
7.3 Page Types
A. Login Page
- Split layout: Login form (left) + marketing carousel (right)
- Username/password fields
- Default: admin / admin → forced password change on first login
- Clean, minimal design matching Stirling-PDF
B. Home Page (Tool Grid)
- Two view modes: Sidebar (default, recommended) and Fullscreen grid
- Sidebar mode: Categorized tool list (left panel) + dropzone (right)
- Fullscreen mode: Card grid with category headers and tool counts
- Global search bar ("Search tools...")
- Favourites per tool (star icon)
- "Show Details" toggle in fullscreen mode
C. Tool Page (consistent pattern for ALL tools)
- Tool icon + name at top of sidebar
- Files section (collapsible): Upload button + file list
- Settings section (collapsible): Tool-specific controls
- Process button at bottom (disabled until file uploaded)
- Main area: Dropzone → Preview → Result with download
D. Automate Page
- Saved automations list
- "Create New Automation" button
- Suggested templates
- Linear pipeline builder
E. Settings Page (Modal Dialog)
- See Section 9 for full specification
7.4 Input Methods
Every tool supports all of these:
- Drag and Drop - onto the dropzone area
- File picker - "Upload from computer" button
- Clipboard paste - Ctrl/Cmd+V a screenshot or copied image
- URL input - paste an image URL to fetch (with SSRF protections: HTTPS only, blocked private/localhost IPs, 100MB max fetch size, 30s timeout)
- Multi-file upload - for batch-capable tools
Exceptions to standard tool page layout:
- QR Code Generator (U-05) does not accept image upload - it generates images from text input. Uses a text input field instead of a dropzone.
7.5 Before/After Preview
For tools where visual comparison matters (compress, color adjustments, filters, upscaling):
- Split-screen slider that user can drag left/right
- Original on left, processed on right
- File size comparison displayed (e.g., "4.2MB → 890KB (79% reduction)")
- Real-time preview where performance allows
7.6 Responsive Design
- Desktop (1024px+): Full sidebar + tool panel + workspace (as designed)
- Tablet (768-1023px): Collapsible sidebar, tool panel stacks above workspace
- Mobile (< 768px): Bottom navigation bar, full-screen tool panel, swipe between upload/settings/result
7.7 Theme System
- Light mode (default): Clean whites, soft blues (matching Stirling-PDF light theme)
- Dark mode: Dark grays/navy, high contrast controls
- Theme toggle in bottom-right corner
- CSS variables for easy custom theming via admin settings
- Respects system preference on first visit
8. Social Media Resize Presets
| Platform | Preset Name | Dimensions |
|---|---|---|
| Post (Square) | 1080 x 1080 | |
| Story / Reel | 1080 x 1920 | |
| Profile Picture | 320 x 320 | |
| Landscape Post | 1080 x 566 | |
| Portrait Post | 1080 x 1350 | |
| Twitter/X | Post Image | 1200 x 675 |
| Twitter/X | Header | 1500 x 500 |
| Twitter/X | Profile Picture | 400 x 400 |
| Post Image | 1200 x 630 | |
| Cover Photo | 820 x 312 | |
| Profile Picture | 170 x 170 | |
| Event Cover | 1920 x 1005 | |
| YouTube | Thumbnail | 1280 x 720 |
| YouTube | Channel Banner | 2560 x 1440 |
| YouTube | Profile Picture | 800 x 800 |
| Post Image | 1200 x 627 | |
| Banner | 1584 x 396 | |
| Profile Picture | 400 x 400 | |
| TikTok | Video Cover | 1080 x 1920 |
| TikTok | Profile Picture | 200 x 200 |
| Profile Picture | 500 x 500 | |
| Pin | 1000 x 1500 | |
| Threads | Post Image | 1080 x 1080 |
9. Settings / Admin Panel
9.1 Settings Structure
Modeled after Stirling-PDF's 17-section settings dialog:
PREFERENCES
| Section | Settings |
|---|---|
| General | User info + logout, software update check (opt-in only — disabled by default to respect "no external API calls" philosophy; checks GitHub releases when enabled), default tool picker mode (sidebar/fullscreen), auto-unzip settings, hide unavailable tools toggle |
| Keyboard Shortcuts | Per-tool customizable keyboard shortcuts. Defaults: Cmd/Ctrl+Alt+1 through Cmd/Ctrl+Alt+8 for top tools. Search bar to find tools |
WORKSPACE
| Section | Settings |
|---|---|
| People | User management (admin panel). User count display. Add/edit/delete users. Role assignment (Admin/User) |
DEVELOPER
| Section | Settings |
|---|---|
| API Keys | Public API key display, copy, refresh. Documentation links |
CONFIGURATION
| Section | Settings |
|---|---|
| System Settings | App name (text input), logo upload (custom branding), available languages, default locale, file upload limit (default 100MB), custom HTML |
| Features | Feature flags: enable/disable specific tools or tool categories |
| Endpoints | Enable/disable specific API endpoints |
| Advanced | Feature flags (alpha features), max DPI, temp file management (base directory, max age hours, cleanup interval minutes, startup cleanup toggle), process concurrency limits |
SECURITY & AUTHENTICATION
| Section | Settings |
|---|---|
| Security | Enable login toggle, login attempt limit, login reset time, CSRF protection, JWT configuration (key persistence, rotation, cleanup, retention days, secure cookie) |
LICENSING & ANALYTICS
| Section | Settings |
|---|---|
| Plan | Current plan display, upgrade options (for future SaaS) |
| Usage Analytics | Endpoint usage tracking, visit counts, data type filter (API/UI/All), chart visualization |
POLICIES & PRIVACY
| Section | Settings |
|---|---|
| Legal | Terms and Conditions URL, Privacy Policy URL, Accessibility Statement URL |
| Privacy | Enable analytics toggle, enable metrics toggle, search engine visibility toggle |
10. Authentication & Security
10.1 Authentication Flow
- First Launch: App starts with default credentials
admin/admin - Forced Password Change: On first login, user must set a new password
- Login Page: Split layout (form left, branding right) matching Stirling-PDF
- Session: JWT-based with configurable expiry
- Auth Bypass:
AUTH_ENABLED=falseenv var for users behind reverse proxies (Authelia, Cloudflare Access, etc.)
10.2 Security Features
- Login attempt rate limiting (default: 5 attempts, 15-minute lockout)
- CSRF protection (enabled by default)
- JWT key rotation
- Secure cookie option
- Password strength requirements (configurable)
- No external auth dependencies (no SSO for V1 - purely local)
10.3 User Management
- Single admin model (V1)
- Admin can create additional users with User role
- Users can use tools but cannot access settings
- Future: Teams, roles, permissions (for commercial version)
11. API Specification
11.1 API Design
- RESTful API with Swagger/OpenAPI documentation
- Every tool has a corresponding API endpoint
- API key authentication (generated in Settings)
- All endpoints under
/api/v1/ - Auto-generated Swagger UI at
/api/docs - Per-IP rate limiting applies regardless of auth state (default: 100 req/min per IP)
- Max image dimensions enforced:
MAX_MEGAPIXELS=100(configurable, prevents OOM on decompression bombs)
11.2 API Error Response Schema
All errors return a consistent JSON envelope:
{
"error": "Human-readable error message",
"code": "UNSUPPORTED_FORMAT",
"details": { "format": "psd", "supported": ["jpg", "png", "webp"] }
}
| HTTP Status | Code | Meaning |
|---|---|---|
| 400 | INVALID_INPUT |
Bad request (missing file, invalid params) |
| 400 | UNSUPPORTED_FORMAT |
File format not supported |
| 400 | FILE_TOO_LARGE |
Exceeds MAX_UPLOAD_SIZE_MB |
| 400 | IMAGE_TOO_LARGE |
Exceeds MAX_MEGAPIXELS |
| 400 | INVALID_PIPELINE |
Pipeline validation failed (incompatible tool chain) |
| 401 | UNAUTHORIZED |
Missing or invalid API key / session |
| 429 | RATE_LIMITED |
Too many requests |
| 500 | PROCESSING_ERROR |
Image processing failed |
| 503 | QUEUE_FULL |
Job queue at capacity, retry later |
11.3 API Patterns
Single file processing:
POST /api/v1/tools/compress
Content-Type: multipart/form-data
Body: file + settings (quality, targetSize, etc.)
Response: processed file download
Batch processing:
POST /api/v1/tools/compress/batch
Content-Type: multipart/form-data
Body: multiple files + settings
Response: zip file download
Pipeline execution:
POST /api/v1/pipeline/execute
Content-Type: multipart/form-data
Body: file + pipeline definition (JSON array of steps)
Response: processed file download
11.3 API Endpoints (complete list)
| Method | Endpoint | Tool |
|---|---|---|
| POST | /api/v1/tools/resize |
Resize |
| POST | /api/v1/tools/crop |
Crop |
| POST | /api/v1/tools/rotate |
Rotate & Flip |
| POST | /api/v1/tools/convert |
Format Convert |
| POST | /api/v1/tools/compress |
Compress |
| POST | /api/v1/tools/strip-metadata |
Strip Metadata |
| POST | /api/v1/tools/rename |
Bulk Rename (accepts multiple files, returns zip with renamed files using pattern) |
| POST | /api/v1/tools/image-to-pdf |
Image to PDF |
| POST | /api/v1/tools/favicon |
Favicon Generator |
| POST | /api/v1/tools/brightness-contrast |
Brightness & Contrast |
| POST | /api/v1/tools/saturation |
Saturation & Exposure |
| POST | /api/v1/tools/color-channels |
Color Channels |
| POST | /api/v1/tools/color-effects |
Color Effects |
| POST | /api/v1/tools/replace-color |
Replace & Invert Color |
| POST | /api/v1/tools/remove-background |
Background Removal |
| POST | /api/v1/tools/upscale |
Image Upscaling |
| POST | /api/v1/tools/erase-object |
Object Eraser |
| POST | /api/v1/tools/ocr |
OCR / Text Extraction |
| POST | /api/v1/tools/blur-faces |
Face / PII Blur |
| POST | /api/v1/tools/smart-crop |
Smart Crop |
| POST | /api/v1/tools/watermark-text |
Text Watermark |
| POST | /api/v1/tools/watermark-image |
Image Watermark |
| POST | /api/v1/tools/text-overlay |
Text Overlay |
| POST | /api/v1/tools/compose |
Image Composition |
| POST | /api/v1/tools/info |
Image Info |
| POST | /api/v1/tools/compare |
Image Compare (accepts 2 files, returns JSON: { similarity: number, diffImage: base64 }) |
| POST | /api/v1/tools/find-duplicates |
Find Duplicates |
| POST | /api/v1/tools/color-palette |
Color Palette |
| POST | /api/v1/tools/qr-generate |
QR Code Generator |
| POST | /api/v1/tools/barcode-read |
Barcode Reader |
| POST | /api/v1/tools/collage |
Collage / Grid |
| POST | /api/v1/tools/split |
Image Splitting |
| POST | /api/v1/tools/border |
Border & Frame |
| POST | /api/v1/tools/svg-to-raster |
SVG to Raster |
| POST | /api/v1/tools/vectorize |
Image to SVG |
| POST | /api/v1/tools/gif |
GIF Tools |
| POST | /api/v1/pipeline/execute |
Pipeline Execution |
| POST | /api/v1/pipeline/save |
Save Pipeline |
| GET | /api/v1/pipeline/list |
List Pipelines |
| GET | /api/v1/config/formats |
Supported Formats |
| GET | /api/v1/config/presets |
Social Media Presets |
| GET | /api/v1/health |
Health Check |
12. Internationalization (i18n)
12.1 Architecture
- All user-facing strings stored in JSON translation files
- Key-based system:
tools.compress.title,tools.compress.description, etc. - Language files in
packages/shared/src/i18n/locales/ - Frontend uses a lightweight i18n library (e.g., i18next)
- Language selector in bottom-right corner (matching Stirling-PDF)
- Default: English (
en) - Locale stored in user preferences (cookie/localStorage)
12.2 Initial Language
- English only for initial release
- Architecture supports adding any language by dropping a JSON file
- Community contributions welcome for translations
13. File Management & Cleanup
13.1 Temporary File Lifecycle
- User uploads image → stored in
/tmp/workspace/{sessionId}/ - Processing creates output in
/tmp/workspace/{sessionId}/output/ - User downloads result
- Background cron cleans up files older than configured max age
13.2 Cleanup Configuration
| Setting | Default | Env Var |
|---|---|---|
| Max file age | 24 hours | FILE_MAX_AGE_HOURS |
| Cleanup interval | 30 minutes | CLEANUP_INTERVAL_MINUTES |
| Startup cleanup | Enabled | CLEANUP_ON_STARTUP |
| Max upload size | 100 MB per file | MAX_UPLOAD_SIZE_MB |
| Max batch size | 200 files | MAX_BATCH_SIZE |
| Concurrent processing jobs | 3 | CONCURRENT_JOBS |
13.3 Storage Adapter
interface StorageAdapter {
upload(file: Readable, path: string): Promise<string>; // Streams, NOT Buffer (prevents OOM on large files)
download(path: string): Promise<Readable>; // Returns stream
delete(path: string): Promise<void>;
exists(path: string): Promise<boolean>;
listFiles(directory: string): Promise<string[]>;
}
// Implementations:
// - LocalStorageAdapter (default) - uses filesystem
// - S3StorageAdapter - uses AWS S3 / Cloudflare R2 (future)
Why streams: A 100MB upload with 200-file batch would require 20GB of memory with Buffer-based I/O. Streams keep memory usage constant regardless of file size.
14. Keyboard Shortcuts
14.1 Global Shortcuts
| Shortcut | Action |
|---|---|
Ctrl/Cmd + K |
Focus search bar |
Ctrl/Cmd + / |
Toggle sidebar |
Ctrl/Cmd + Shift + D |
Toggle dark/light mode |
Ctrl/Cmd + Shift + F |
Toggle fullscreen/sidebar tool view |
Escape |
Close modal / cancel current operation |
14.2 Tool Shortcuts
| Shortcut | Tool |
|---|---|
Ctrl/Cmd + Alt + 1 |
Resize |
Ctrl/Cmd + Alt + 2 |
Crop |
Ctrl/Cmd + Alt + 3 |
Compress |
Ctrl/Cmd + Alt + 4 |
Convert |
Ctrl/Cmd + Alt + 5 |
Remove Background |
Ctrl/Cmd + Alt + 6 |
Watermark |
Ctrl/Cmd + Alt + 7 |
Strip Metadata |
Ctrl/Cmd + Alt + 8 |
Image Info |
14.3 Workspace Shortcuts
| Shortcut | Action |
|---|---|
Ctrl/Cmd + V |
Paste image from clipboard |
Ctrl/Cmd + Enter |
Process / Execute current tool |
Ctrl/Cmd + S |
Download result |
Ctrl/Cmd + Z |
Undo last operation (where applicable) |
All shortcuts customizable via Settings > Keyboard Shortcuts.
15. Concurrency & Processing
15.1 Job Processing Architecture
User Upload
↓
[Fastify Route Handler]
↓
[Validate file type/size]
↓
[Add to p-queue (concurrency limited)]
↓
[Worker Thread]
↓
[Sharp / ImageMagick / ONNX Runtime]
↓
[Store result in temp directory]
↓
[Return download URL to frontend]
15.2 Concurrency Controls
CONCURRENT_JOBSenv var (default: 3) - max simultaneous image processing jobs- Additional jobs wait in queue (FIFO)
- Frontend shows queue position for waiting jobs
- Timeout: 5 minutes per job (configurable)
15.3 Progress Reporting (Server-Sent Events)
Uses SSE (not WebSocket) for simplicity - works with HTTP/1.1, no connection upgrade needed, simpler CORS.
GET /api/v1/jobs/{jobId}/progress
Accept: text/event-stream
Events:
data: { "jobId": "abc123", "status": "processing", "progress": 45, "currentFile": "photo_3.jpg", "totalFiles": 10 }
data: { "jobId": "abc123", "status": "completed", "progress": 100, "downloadUrl": "/api/v1/jobs/abc123/download" }
data: { "jobId": "abc123", "status": "failed", "error": "Unsupported format", "failedFile": "photo_7.psd" }
15.4 SQLite Write Concurrency
All database writes go through a single shared connection (not a pool) to avoid SQLite write contention:
- Worker threads communicate job status to the main thread via
parentPort.postMessage() - Main thread handles all DB writes sequentially
- Reads can use separate connections (WAL mode allows concurrent reads)
- Uses
better-sqlite3(synchronous, faster than async alternatives for SQLite)
15.5 CORS & Static File Serving
Production: Fastify serves both the API (/api/v1/*) and the Vite-built SPA (static files from apps/web/dist/). No CORS needed — same origin.
Development: Vite dev server (port 5173) proxies API calls to Fastify (port 1349). Vite config includes proxy rule:
// apps/web/vite.config.ts
server: {
proxy: { '/api': 'http://localhost:1349' }
}
15.3 Batch Processing
- Files processed in parallel up to
CONCURRENT_JOBSlimit - Per-file progress tracking
- Partial failure handling (continue on error, report failed files)
- Results collected and zipped server-side
- Download as single ZIP file
16. Deployment & Configuration
16.1 Environment Variables (complete)
| Variable | Default | Description |
|---|---|---|
PORT |
1349 |
Application port |
AUTH_ENABLED |
true |
Enable/disable authentication |
DEFAULT_USERNAME |
admin |
Initial admin username |
DEFAULT_PASSWORD |
admin |
Initial admin password |
STORAGE_MODE |
local |
Storage backend (local / s3) |
FILE_MAX_AGE_HOURS |
24 |
Max age before cleanup |
CLEANUP_INTERVAL_MINUTES |
30 |
Cleanup cron interval |
CLEANUP_ON_STARTUP |
true |
Clean temp files on boot |
MAX_UPLOAD_SIZE_MB |
100 |
Max single file upload |
MAX_BATCH_SIZE |
200 |
Max files per batch |
CONCURRENT_JOBS |
3 |
Parallel processing limit |
DB_PATH |
/data/stirling.db |
SQLite database path |
PYTHON_VENV_PATH |
/opt/venv |
Python virtual environment path |
WORKSPACE_PATH |
/tmp/workspace |
Temp processing directory |
APP_NAME |
Stirling Image |
Custom branding name |
APP_LOGO |
(default) | Custom logo path |
DEFAULT_THEME |
light |
Default theme (light/dark) |
DEFAULT_LOCALE |
en |
Default language |
S3_BUCKET |
- | S3 bucket name |
S3_REGION |
- | S3 region |
S3_ACCESS_KEY |
- | S3 access key |
S3_SECRET_KEY |
- | S3 secret key |
S3_ENDPOINT |
- | S3-compatible endpoint (for R2, MinIO) |
MAX_MEGAPIXELS |
100 |
Max image dimensions (prevents OOM) |
RATE_LIMIT_PER_MIN |
100 |
Per-IP rate limit (applies even with AUTH_ENABLED=false) |
LOGIN_LOCKOUT_MINUTES |
15 |
Lockout duration after failed login attempts |
16.2 Docker Volumes
| Volume | Container Path | Purpose |
|---|---|---|
data |
/data |
SQLite database, settings, user data |
workspace |
/tmp/workspace |
Temporary file processing (auto-cleaned) |
16.3 Health Check
GET /api/v1/health
Response:
{
"status": "healthy",
"version": "1.0.0",
"uptime": "2d 5h 30m",
"storage": { "mode": "local", "available": "45.2 GB" },
"queue": { "active": 1, "pending": 3 },
"ai": { "python": "available", "rembg": "ready", "realesrgan": "ready", "lama": "ready", "paddleocr": "ready", "mediapipe": "ready" }
}
17. Open-Source & Licensing Strategy
17.1 Licensing Model
Following Stirling-PDF's open-core approach:
- Core (MIT License): All image tools, UI, API, authentication, settings
- Commercial/Proprietary (future): Enterprise SSO, team management, usage analytics, custom metadata, priority support
17.2 Repository Standards
- Public GitHub repository
- Strict
.gitignore(no secrets, no node_modules, no AI models) - ESLint + Prettier for consistent code style
- GitHub Issue Templates (bug report, feature request)
- GitHub Actions CI/CD (lint, test, build, Docker publish)
CHANGELOG.mdwith semantic versioningCONTRIBUTING.mdfor community contributors
17.3 README Strategy
The README must prove ease-of-use in 5 seconds:
- Hero section: One-line description + badges (stars, Docker pulls, license)
- Quick Start: Single
docker runcommand - Screenshot/GIF: Tool grid in action
- Feature grid: Visual icons for each tool category
- Configuration table: Key env vars
- Comparison: "Replaces 20+ online tools" with visual table
18. Development Roadmap
Phase 1: Foundation (Weeks 1-3)
- Monorepo setup (Turborepo + pnpm)
- Fastify server with auth (Better-Auth + SQLite)
- React SPA with routing, layout, theme system
- Dropzone + file upload + file management
- Settings dialog (basic sections)
- Docker setup (multi-stage build)
- CI/CD pipeline
Phase 2: Core Tools (Weeks 4-7)
- Image engine package (Sharp wrapper)
- Resize, Crop, Rotate & Flip
- Format Convert (all formats including HEIC)
- Compress (quality + target size)
- Strip Metadata
- Color adjustments (brightness, contrast, saturation, channels)
- Before/After preview slider
- Batch processing + ZIP download
- API + Swagger documentation
Phase 3: Advanced Tools (Weeks 8-11)
- Watermark (text + image)
- Text Overlay
- Image Composition
- Border & Frame
- Collage / Grid Maker
- Image Splitting
- Bulk Rename
- Image to PDF
- SVG to Raster
- GIF Tools (animated support)
- Image Info / Inspector
- Color Palette Extraction
- QR Code Generator + Barcode Reader
- Favicon Generator
- Image-to-SVG Vectorization (algorithmic tracing, not AI)
Phase 4: AI Tools (Weeks 12-15)
- ONNX Runtime integration
- Background Removal
- Image Upscaling (2x, 4x) - Real-ESRGAN Python
- OCR / Text Extraction
- Face / PII Blur
- Smart Crop
- Object Eraser (LaMa via lama-cleaner — production Python library)
- Find Duplicates (dHash perceptual hashing)
- Image Compare (side-by-side + slider)
Phase 5: Automation & Polish (Weeks 16-18)
- Pipeline Builder
- Saved Automations + Templates
- Keyboard shortcuts (customizable)
- Full settings panel (all sections)
- Usage analytics
- i18n architecture
- Mobile responsive polish
- README + documentation
- Docker Hub / GHCR publishing
- Public launch
19. Success Metrics
| Metric | Target |
|---|---|
| Docker Run → First Tool Used | Under 60 seconds |
| Click-to-Result (any tool) | Under 3 clicks |
| Cross-Platform | Works on linux/amd64 + linux/arm64 (Intel, AMD, Apple Silicon) |
| Batch Processing (100 images resize) | Under 30 seconds |
| GitHub Stars (6 months) | 500+ |
| Zero external data transmission | 0 bytes to third parties |
Appendix A: Stirling-PDF Feature Mapping
How Stirling-PDF's tool categories map to Stirling-Image:
| Stirling-PDF | Stirling-Image Equivalent |
|---|---|
| Merge | Collage / Grid Maker |
| Compare | Image Compare |
| Compress | Compress |
| Convert | Format Convert |
| OCR | OCR / Text Extraction |
| Redact | Face / PII Blur |
| Sign | Text Overlay / Watermark |
| Add Password | N/A (images don't have passwords) |
| Add Watermark | Text/Image Watermark |
| Crop PDF | Crop |
| Rotate | Rotate & Flip |
| Split | Image Splitting |
| Extract Images | N/A (we ARE the image tool) |
| Remove Pages | N/A |
| Change Metadata | Strip Metadata / Image Info |
| Adjust Colours | Brightness/Contrast/Saturation/Color Channels |
| Automate | Pipeline Builder |
| PDF Multi Tool | Batch Processing |
Document generated 2026-03-22. This PRD serves as the definitive blueprint for building Stirling-Image.