diff --git a/DOCKER_BUILD_FIX.md b/DOCKER_BUILD_FIX.md deleted file mode 100644 index 7ccb1e6..0000000 --- a/DOCKER_BUILD_FIX.md +++ /dev/null @@ -1,167 +0,0 @@ -# Docker Build Fix - Simplified Dependency Installation - -## Issue -Docker build was failing with: -``` -npm error The `npm ci` command can only install with an existing package-lock.json -``` - -## Root Cause -The original Dockerfile used `npm ci` which requires fully resolved `package-lock.json` files. These lockfiles were missing and stub lockfiles don't work because `npm ci` requires the complete dependency tree. - -## Solution Applied - -### Simplified Approach -The Dockerfile now uses **`npm install`** instead of `npm ci`. This is simpler and more reliable: - -```dockerfile -RUN npm install -``` - -**Why this works:** -- ✅ No lockfile required -- ✅ Automatically resolves and installs all dependencies -- ✅ Works consistently across all environments -- ✅ No manual lockfile maintenance needed -- ✅ Simpler Dockerfile = easier to maintain - -### Trade-offs - -| Approach | Speed | Lockfile Required | Deterministic | Maintenance | -|----------|-------|-------------------|---------------|-------------| -| `npm ci` | Fastest | ✅ Yes | ✅ Yes | High | -| **`npm install`** | Fast | ❌ No | ⚠️ By version ranges | **Low** | - -**Note:** While `npm install` resolves versions at build time (not 100% deterministic), your `package.json` uses caret ranges (e.g., `^4.19.0`) which only allow minor/patch updates, providing reasonable stability. - -### Files Modified - -1. **Dockerfile** - Simplified to use `npm install` in all three stages -2. **.dockerignore** - Optimizes build context -3. **backend/package.json** - Updated multer to v2.1.0 (v1.4.5 no longer exists) - -### Dependency Updates - -- **multer**: `^1.4.5` → `^2.1.0` (security fixes, v1.x removed from npm) -- **@types/multer**: `^1.4.7` → `^2.1.0` (matching types) - -## How It Works - -### Build Flow - -1. **Copy package.json** into build stage -2. **Run npm install** - automatically resolves and installs all dependencies -3. **Build the application** - -No lockfile generation or validation needed! - -## Usage - -### Build Docker Image -```bash -docker build -t pnger:latest . -``` - -The build will: -- Install dependencies from npm registry -- Build frontend and backend -- Create production image with only runtime dependencies -- Complete successfully every time - -### Run Container -```bash -docker run -d \ - -p 3000:3000 \ - -e MAX_FILE_SIZE=10485760 \ - --name pnger \ - pnger:latest -``` - -### Unraid Deployment -The Docker image builds cleanly in Unraid without any configuration needed. - -## Optional: Add Lockfiles for Deterministic Builds - -If you want 100% deterministic builds with locked dependency versions: - -```bash -# Generate lockfiles locally -cd frontend && npm install && cd .. -cd backend && npm install && cd .. - -# Commit them -git add frontend/package-lock.json backend/package-lock.json -git commit -m "Add lockfiles for deterministic builds" - -# Update Dockerfile to use npm ci instead of npm install -``` - -**Benefits of lockfiles:** -- Guaranteed exact dependency versions -- Slightly faster builds -- Better for production environments - -**Drawbacks:** -- Must update lockfiles when changing dependencies -- More complex maintenance - -## Build Optimization - -The `.dockerignore` file excludes: -- `node_modules/` (prevents copying local dependencies) -- Development files (`.env`, `.vscode/`, etc.) -- Build artifacts -- Documentation and test files - -This keeps build context small and fast. - -## Verification - -Test the complete build: -```bash -# Build image -docker build -t pnger:test . - -# Run container -docker run -d -p 3000:3000 --name pnger-test pnger:test - -# Check health -curl http://localhost:3000 - -# View logs -docker logs pnger-test - -# Cleanup -docker stop pnger-test && docker rm pnger-test -``` - -## Technical Details - -### Multi-Stage Build - -1. **frontend-builder**: Builds Svelte/Vite frontend with all dev dependencies -2. **backend-builder**: Compiles TypeScript backend with all dev dependencies -3. **production**: Combines compiled outputs with production dependencies only (`--omit=dev`) - -### Security Features - -- Runs as non-root user (`node`) -- Health check endpoint configured -- Minimal production dependencies -- Alpine Linux base (smaller attack surface) -- No unnecessary dev tools in production image - -### Multer v2.1.0 Upgrade - -Upgraded from v1.4.5 (no longer available) to v2.1.0: -- ✅ Security fixes (CVE-2026-2359 and others) -- ✅ Backward compatible API -- ✅ Better performance -- ✅ Active maintenance - ---- - -**Created**: 2026-03-08 -**Branch**: `fix/add-package-lockfiles` -**Status**: Ready to merge -**Issue**: Docker build failing ✅ RESOLVED \ No newline at end of file diff --git a/INSTRUCTIONS.md b/INSTRUCTIONS.md index 06ac1b7..254d229 100644 --- a/INSTRUCTIONS.md +++ b/INSTRUCTIONS.md @@ -1,86 +1,76 @@ -# PNGer Development Instructions +# PNGer Development & Technical Instructions ## Project Overview -PNGer is a single-container web application for PNG editing and resizing, designed for deployment on Unraid with Gitea version control. - -## Development Roadmap - -### Phase 1: MVP Foundation (Completed ✅) -- [x] Repository setup -- [x] Project structure initialization -- [x] Backend API scaffold -- [x] Frontend scaffold -- [x] Basic upload/download flow -- [x] Dockerfile configuration -- [x] Live preview implementation -- [x] Dark/light mode theming -- [x] Image resize and compression -- [x] Format conversion (PNG, WebP, JPEG) - -### Phase 2: Sprint 1 - Enhanced UX (Completed ✅) -- [x] Drag & drop file upload -- [x] Clipboard paste (Ctrl+V) -- [x] Smart presets (8 configurations) -- [x] Keyboard shortcuts (Enter, Ctrl+Enter, ?, Esc) -- [x] Enhanced visual feedback -- [x] Responsive UI improvements -- [x] Theme contrast fixes - -### Phase 3: Advanced Features (Upcoming) -- [ ] Batch processing -- [ ] Advanced crop tool with visual selector -- [ ] Watermarking -- [ ] Image filters and effects -- [ ] Undo/redo functionality -- [ ] History/recent files +PNGer is a single-container web application for PNG editing and resizing, designed for deployment on Unraid with Gitea version control. It features a modern Svelte frontend and a high-performance Node.js/Sharp backend. ## Technical Architecture +### Architecture Overview + +PNGer uses a multi-layered architecture designed for responsiveness and efficiency: + +```mermaid +graph TD + A[User Browser] --> B[Svelte Frontend] + B --> C[Canvas API (Live Preview)] + B --> D[Express API (Backend)] + D --> E[Sharp Image Library] + D --> F[Runtime Environment (Docker)] +``` + ### Backend (Express + Sharp) -**Endpoints:** +The backend is built with Node.js and TypeScript, using Express for the API and Sharp for high-performance image processing. + +**Key Endpoints:** - `POST /api/transform` - Transform image (resize, crop, compress, convert) - `GET /api/health` - Health check **Key Dependencies:** -- express: Web framework -- multer: File upload handling -- sharp: Image processing -- cors: Cross-origin support +- `sharp`: High-performance image processing (handles resizing, cropping, and format conversion). +- `multer`: Middleware for handling `multipart/form-data`, used for file uploads. +- `express`: Web framework for the API. ### Frontend (Svelte + Vite) -**Components:** -- `App.svelte` - Main container with all features -- `lib/api.ts` - API client -- `lib/preview.ts` - Live preview logic using Canvas API -- `lib/theme.ts` - Dark/light theme management -- `lib/presets.ts` - Smart presets configuration +The frontend is a reactive Svelte application that prioritizes real-time feedback and UX. -**Key Features:** -- Drag & drop upload -- Clipboard paste support -- Real-time preview (debounced 300ms) -- Side-by-side comparison -- File size analysis -- 8 smart presets -- Keyboard shortcuts -- Persistent theme preference +**Core Components & Modules:** +- `App.svelte`: Main application container managing state and UI. +- `lib/api.ts`: API client for backend communication. +- `lib/preview.ts`: Client-side preview logic using the Canvas API for instant feedback. +- `lib/theme.ts`: Dark/light theme management with persistent storage. +- `lib/presets.ts`: Configuration for smart image presets. -**Key Dependencies:** -- svelte: Reactive framework -- vite: Build tool -- axios: HTTP client +### Design System (Dark/Light Modes) -### Docker Strategy +The UI uses a modern design system with CSS custom properties for theming: +- **Light Mode**: Clean white background with dark gold (`#b8860b`) accents. +- **Dark Mode**: Deep black (`#0a0a0a`) background with light gold (`#daa520`) accents. +- **Transparencies**: Dark/Light toggling allows users to inspect PNG transparency against different backgrounds. -**Multi-stage Build:** -1. Stage 1: Build frontend (Vite build) -2. Stage 2: Copy frontend + setup backend -3. Final image: Alpine-based Node.js +## Implementation Details -**Image Size Target:** < 150MB +### Live Preview System + +Live preview is implemented using a client-side Canvas-based approach to provide instant feedback (< 100ms) without server round-trips. + +**How it works:** +1. User uploads an image. +2. The browser loads the image into an HTML5 Canvas. +3. On any parameter change (width, quality, etc.), a debounced (300ms) update applies transformations to the canvas. +4. The canvas content is displayed side-by-side with the original for comparison. +5. File sizes are estimated from the Canvas data URL to provide immediate feedback on optimization savings. + +### Docker Strategy & Fixes + +PNGer uses a multi-stage Docker build to minimize image size and maximize security. + +**Optimization Fixes applied:** +- **Dependency Installation**: Uses `npm install` instead of `npm ci` to handle missing lockfiles gracefully while maintaining stability via caret ranges in `package.json`. +- **Security**: Runs as a non-root `node` user in the final Alpine-based image. +- **Multer Upgrade**: Upgraded to `v2.1.0` for improved security and performance. ## Local Development Setup @@ -89,7 +79,7 @@ PNGer is a single-container web application for PNG editing and resizing, design - npm or pnpm - Docker (optional) -### Initial Setup +### Setup Steps ```bash # Clone repository @@ -101,259 +91,44 @@ cd backend npm install npm run dev -# Setup frontend (new terminal) +# Setup frontend (separate terminal) cd frontend npm install npm run dev ``` -### Development Workflow - -1. **Feature Branch**: Create from `main` -2. **Develop**: Make changes with hot-reload -3. **Test**: Manual testing + health checks -4. **Commit**: Descriptive commit messages -5. **Push**: Push to Gitea -6. **Review**: Self-review changes -7. **Merge**: Merge to `main` - ### Environment Variables **Backend (.env):** -``` -PORT=3000 -NODE_ENV=development -MAX_FILE_SIZE=10485760 -CORS_ORIGIN=http://localhost:5173 -``` +- `PORT`: 3000 (internal) +- `MAX_FILE_SIZE`: 10485760 (10MB default) +- `CORS_ORIGIN`: http://localhost:5173 **Frontend (.env):** -``` -VITE_API_URL=http://localhost:3000/api -``` +- `VITE_API_URL`: http://localhost:3000/api -## Docker Build & Test +## Development Workflow & Standards -```bash -# Build image -docker build -t pnger:test . +### Workflow +1. **Feature Branch**: Create from `main`. +2. **Develop**: Use hot-reload (`npm run dev`). +3. **Test**: Perform manual testing of image operations and presets. +4. **Commit**: Use `type: description` format (e.g., `feat: add rotation`). +5. **Merge**: Merge into `main` after review. -# Run container -docker run -p 8080:3000 --name pnger-test pnger:test - -# Test endpoints -curl http://localhost:8080/api/health - -# View logs -docker logs pnger-test - -# Stop and remove -docker stop pnger-test && docker rm pnger-test -``` - -## Unraid Deployment - -### Setup Steps - -1. **SSH into Unraid** -2. **Navigate to docker configs**: `/mnt/user/appdata/pnger` -3. **Clone repository**: - ```bash - git clone https://git.alwisp.com/jason/pnger.git - cd pnger - ``` -4. **Build and run**: - ```bash - docker-compose up -d - ``` -5. **Access**: http://[unraid-ip]:8080 - -### Update Process - -```bash -cd /mnt/user/appdata/pnger -git pull origin main -docker-compose down -docker-compose build -docker-compose up -d -``` - -## Code Standards - -### JavaScript/TypeScript -- Use ES6+ features -- Async/await for asynchronous operations -- Descriptive variable names -- Comments for complex logic only -- Type safety with TypeScript - -### File Organization -- One component per file -- Group related utilities -- Keep components under 300 lines (split if larger) -- Organize by feature when possible - -### Commit Messages -- Format: `type: description` -- Types: feat, fix, docs, style, refactor, test, chore -- Example: `feat: add drag and drop upload` -- Be specific and descriptive - -## Feature Implementation Notes - -### Drag & Drop Upload -- Uses HTML5 Drag and Drop API -- Visual feedback on dragover/dragleave -- File type validation on drop -- Falls back to file input for browser support - -### Clipboard Paste -- Listens for paste events on document -- Extracts image from clipboard items -- Supports screenshots and copied images -- Works across all major browsers - -### Smart Presets -- 8 predefined configurations: - 1. Web Optimized (1920x1080, 80%, WebP) - 2. Social Media (1080x1080, 85%, JPEG) - 3. Profile Picture (400x400, 90%, PNG) - 4. Email Friendly (800x600, 75%, JPEG) - 5. Tiny Icon (64x64, 100%, PNG) - 6. Retina 2x (2x size, 90%) - 7. Icon Small (256x256, 95%, PNG) - 8. Icon Large (512x512, 95%, PNG) -- Applies all settings with one click -- Visual icons for easy identification - -### Keyboard Shortcuts -- Global document listeners -- Context-aware Enter key (checks focus) -- Help dialog with ? key -- Esc to close dialogs -- Cross-platform support (Ctrl/Cmd) - -### Live Preview -- Client-side Canvas API rendering -- Debounced updates (300ms) -- Reactive state management -- Automatic size estimation -- Side-by-side comparison +### Code Standards +- **TypeScript**: Use strict types where possible. +- **Svelte**: Keep components modular and under 300 lines. +- **Async/Await**: Use for all asynchronous operations. +- **Semantic HTML**: Ensure accessibility and proper structure. ## Troubleshooting -### Common Issues +- **Port in use**: `lsof -ti:3000 | xargs kill -9` +- **Sharp issues**: `npm rebuild sharp` +- **Docker Cache**: `docker builder prune` if builds fail unexpectedly. +- **Preview Glitches**: Check browser console for Canvas API errors. -**Port already in use:** -```bash -lsof -ti:3000 | xargs kill -9 -``` +--- -**Sharp installation issues:** -```bash -npm rebuild sharp -``` - -**Docker build fails:** -- Check Docker daemon is running -- Verify Dockerfile syntax -- Clear Docker cache: `docker builder prune` - -**Preview not updating:** -- Check browser console for errors -- Verify Canvas API support -- Clear browser cache - -**Drag & drop not working:** -- Check file type validation -- Verify event handlers are attached -- Test with different browsers - -## Performance Targets - -- Upload handling: < 100ms (for 5MB file) -- Image processing: < 2s (for 10MP image) -- Download generation: < 500ms -- UI response time: < 100ms -- Preview generation: < 500ms (client-side) -- Docker image size: < 150MB - -## Security Considerations - -- File type validation (image/* only) -- File size limits (10MB default, configurable) -- No persistent storage of user files -- Memory cleanup after processing -- CORS configuration -- Input sanitization -- Error message sanitization (no path disclosure) - -## Testing Checklist - -### Upload Methods -- [ ] File input (click to browse) -- [ ] Drag & drop -- [ ] Clipboard paste (Ctrl+V) -- [ ] File validation errors -- [ ] Size limit handling - -### Image Operations -- [ ] Resize with width only -- [ ] Resize with height only -- [ ] Resize with both dimensions -- [ ] Crop to fit (cover mode) -- [ ] All 9 crop positions -- [ ] Format conversion (PNG, WebP, JPEG) -- [ ] Quality adjustment - -### Presets -- [ ] All 8 presets apply correctly -- [ ] Preset values match specifications -- [ ] Visual feedback on selection - -### Keyboard Shortcuts -- [ ] Ctrl+V pastes image -- [ ] Enter downloads (not in input) -- [ ] Ctrl+Enter downloads (anywhere) -- [ ] ? shows help dialog -- [ ] Esc closes dialog - -### UI/UX -- [ ] Theme toggle works -- [ ] Theme persists on reload -- [ ] Live preview updates -- [ ] File size analysis accurate -- [ ] Error messages clear -- [ ] Loading states visible -- [ ] Responsive on mobile - -### Browser Compatibility -- [ ] Chrome/Edge -- [ ] Firefox -- [ ] Safari -- [ ] Mobile browsers - -## Next Steps - -1. ✅ Create backend folder structure -2. ✅ Create frontend folder structure -3. ✅ Initialize package.json files -4. ✅ Create Dockerfile -5. ✅ Create docker-compose.yml -6. ✅ Implement MVP features -7. ✅ Add drag & drop upload -8. ✅ Add clipboard paste -9. ✅ Add smart presets -10. ✅ Add keyboard shortcuts -11. [ ] Implement batch processing -12. [ ] Add advanced crop tool -13. [ ] Add watermarking -14. [ ] Add filters/effects - -## Resources - -- [Sharp Documentation](https://sharp.pixelplumbing.com/) -- [Svelte Documentation](https://svelte.dev/docs) -- [Canvas API Reference](https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API) -- [Drag and Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API) -- [Clipboard API](https://developer.mozilla.org/en-US/docs/Web/API/Clipboard_API) \ No newline at end of file +**Last Updated**: March 12, 2026 \ No newline at end of file diff --git a/README.md b/README.md index af54e93..40ea650 100644 --- a/README.md +++ b/README.md @@ -1,341 +1,49 @@ # PNGer - Modern PNG Editor & Resizer -A sleek, modern PNG editor and resizer with **live preview**, **drag & drop**, **smart presets**, **keyboard shortcuts**, and **dark/light mode theming**. Built with TypeScript and deployed as a single Docker container on Unraid. +A sleek, modern PNG editor and resizer with **live preview**, **drag & drop**, **smart presets**, **keyboard shortcuts**, and **dark/light mode theming**. Built with TypeScript and optimized for deployment as a single Docker container. ## ✨ Features -### 🎨 Modern UI with Dark/Light Mode -- **Dark Mode**: Black background (#0a0a0a) with light gold (#daa520) accents -- **Light Mode**: White background with dark gold (#b8860b) accents -- Perfect for inspecting PNG transparency on different backgrounds -- Persistent theme preference -- Smooth color transitions +- **🎨 Modern UI**: Beautiful dark/light mode for inspecting transparency. +- **⚡ Live Preview**: Instant side-by-side comparison with file size analysis. +- **🚀 Efficiency**: Drag & Drop upload, clipboard paste (`Ctrl+V`), and smart presets. +- **🖼️ Precision**: Control width, height, quality, and crop positions (9 modes). +- **📦 Reliable Deployment**: Multi-stage Docker build optimized for Unraid and Gitea. -### ⚡ Live Preview -- **Real-time preview** of transformations before download -- **Side-by-side comparison** (original vs transformed) -- **File size analysis** showing savings or increase -- **Instant feedback** using client-side Canvas API (< 500ms) -- No server round-trip needed for preview +## 🚀 Quick Start -### 🖼️ Image Operations -- **Resize Operations**: Width, height, and aspect ratio controls -- **Crop to Fit**: Smart cropping with position control (9 positions) -- **Format Conversion**: PNG, WebP, and JPEG output -- **Quality Control**: Adjustable compression settings (10-100%) -- **Fit Modes**: Inside (resize only) or Cover (crop to fill) - -### 🚀 Performance & Usability -- **Drag & Drop**: Drag images directly into the app or use file browser -- **Clipboard Paste**: Paste images with Ctrl+V (Cmd+V on Mac) -- **Smart Presets**: Quick access to common configurations: - - 📷 Web Optimized (1920x1080, 80% quality, WebP) - - 📱 Social Media (1080x1080, 85% quality, JPEG) - - 👤 Profile Picture (400x400, 90% quality, PNG) - - 📧 Email Friendly (800x600, 75% quality, JPEG) - - ⭐ Tiny Icon (64x64, 100% quality, PNG) - - 🔍 Retina 2x (2x dimensions, 90% quality) - - 💎 Icon Small (256x256, 95% quality, PNG) - - 🔶 Icon Large (512x512, 95% quality, PNG) -- **Keyboard Shortcuts**: Fast workflow with keyboard controls (see below) -- **Direct Download**: No server-side storage, immediate download -- **Modern UI**: Sleek, responsive TypeScript/Svelte design -- **File Analysis**: Original size, transformed size, savings percentage -- **Debounced Updates**: Smooth preview generation (300ms delay) -- **Visual Feedback**: Loading states, error messages, success indicators - -### ⌨️ Keyboard Shortcuts -- **Ctrl+V** (Cmd+V): Paste image from clipboard -- **Enter**: Transform & Download (works when input not focused) -- **Ctrl+Enter** (Cmd+Enter): Transform & Download (works anywhere) -- **?**: Show/hide keyboard shortcuts help -- **Esc**: Close shortcuts dialog - -## Tech Stack - -- **Frontend**: Svelte 4 + Vite + TypeScript -- **Backend**: Node.js + Express + TypeScript -- **Image Processing**: Sharp (high-performance image library) -- **Preview**: Canvas API (client-side) -- **Container**: Docker (Alpine-based, multi-stage build) -- **Deployment**: Unraid via Docker Compose - -## Quick Start - -### Unraid Deployment (Recommended) - -1. **Clone or pull this repository to your Unraid server:** +### Docker/Unraid Deployment +1. **Clone & Build**: ```bash - cd /mnt/user/appdata git clone https://git.alwisp.com/jason/pnger.git cd pnger - ``` - -2. **Build the Docker image:** - ```bash docker build -t pnger:latest . ``` - -3. **Run via docker-compose:** +2. **Run**: ```bash docker compose up -d ``` +3. **Access**: `http://localhost:8080` (or your Unraid IP) -4. **Access the application:** - - Navigate to `http://[unraid-ip]:8080` +### Local Development +1. **Install & Run Backend**: `cd backend && npm install && npm run dev` +2. **Install & Run Frontend**: `cd frontend && npm install && npm run dev` +3. **Access**: `http://localhost:5173` -### Unraid Environment Variables (Configurable via UI) +## 📚 Documentation -When setting up in Unraid Docker UI, you can configure: +For more detailed information, please refer to: +- **[INSTRUCTIONS.md](./INSTRUCTIONS.md)**: Technical architecture, development setup, code standards, and troubleshooting. +- **[ROADMAP.md](./ROADMAP.md)**: Project history, sprint updates, and future feature plans. -| Variable | Default | Description | -|----------|---------|-------------| -| `HOST_PORT` | `8080` | External port to access the app | -| `MAX_FILE_SIZE` | `10485760` | Max upload size in bytes (10MB default) | -| `MEM_LIMIT` | `512m` | Memory limit for container | -| `CPU_LIMIT` | `1.0` | CPU limit (1.0 = 1 full core) | -| `NODE_ENV` | `production` | Node environment | +## ⌨️ Keyboard Shortcuts -### Unraid Docker Template Example +- `Ctrl+V`: Paste image from clipboard +- `Enter`: Download (when input not focused) +- `?`: Show shortcuts help +- `Esc`: Close dialogs -```xml - - - pnger - pnger:latest - bridge - false - http://[IP]:[PORT:8080] - 8080 - 10485760 - 512m - -``` +--- -## Local Development - -### Prerequisites -- Node.js 20+ -- npm or yarn - -### Setup - -1. **Install backend dependencies:** - ```bash - cd backend - npm install - ``` - -2. **Install frontend dependencies:** - ```bash - cd frontend - npm install - ``` - -3. **Run development servers:** - - Terminal 1 (Backend): - ```bash - cd backend - npm run dev - ``` - - Terminal 2 (Frontend): - ```bash - cd frontend - npm run dev - ``` - -4. **Access dev server:** - - Frontend: `http://localhost:5173` - - Backend API: `http://localhost:3000/api` - -### Building for Production - -```bash -# Backend TypeScript compilation -cd backend -npm run build - -# Frontend build -cd frontend -npm run build -``` - -## Docker Deployment (Manual) - -```bash -# Build the image (all dependencies and builds are handled internally) -docker build -t pnger:latest . - -# Run the container -docker run -d \ - --name pnger \ - -p 8080:3000 \ - -e MAX_FILE_SIZE=10485760 \ - --restart unless-stopped \ - pnger:latest -``` - -## Project Structure - -``` -pnger/ -├── frontend/ # Svelte + TypeScript application -│ ├── src/ -│ │ ├── App.svelte # Main UI component (with live preview) -│ │ ├── main.ts # Entry point -│ │ ├── app.css # Design system (dark/light modes) -│ │ └── lib/ -│ │ ├── api.ts # API client -│ │ ├── preview.ts # Live preview logic -│ │ ├── theme.ts # Theme management store -│ │ └── presets.ts # Smart presets configuration -│ ├── package.json -│ ├── tsconfig.json -│ └── vite.config.ts -├── backend/ # Express + TypeScript API server -│ ├── src/ -│ │ ├── index.ts # Express server -│ │ ├── routes/ -│ │ │ └── image.ts # Image transform endpoint -│ │ └── types/ -│ │ └── image.ts # TypeScript types -│ ├── package.json -│ └── tsconfig.json -├── Dockerfile # Multi-stage build (frontend + backend) -├── docker-compose.yml # Unraid deployment config -├── ROADMAP.md # Feature roadmap -├── SPRINT1_CHANGES.md # Sprint 1 implementation details -└── UI_UPGRADE_NOTES.md # UI upgrade documentation -``` - -## How It Works - -1. User uploads an image via drag & drop, file browser, or clipboard paste -2. **Live preview** generates instantly using Canvas API -3. User adjusts parameters (width, height, quality, format, etc.) or selects a preset -4. Preview updates in real-time (debounced 300ms) -5. User sees file size comparison and savings -6. When satisfied, user clicks "Transform & Download" or presses Enter -7. Frontend sends image + parameters to backend API -8. Backend processes using Sharp (resize, crop, compress, convert) -9. Processed image returned directly to browser -10. Browser triggers automatic download -11. No files stored on server (stateless operation) - -## API Endpoints - -### POST /api/transform - -Transform an image with resize, crop, and format conversion. - -**Request:** -- Method: `POST` -- Content-Type: `multipart/form-data` -- Body: - - `file`: Image file (PNG/JPEG/WebP) - - `width`: Target width (optional) - - `height`: Target height (optional) - - `quality`: Quality 10-100 (optional, default: 80) - - `format`: Output format `png|webp|jpeg` (optional, default: `png`) - - `fit`: Resize mode `inside|cover` (optional, default: `inside`) - - `position`: Crop position when `fit=cover` (optional, default: `center`) - -**Response:** -- Content-Type: `image/[format]` -- Body: Transformed image binary - -## Configuration - -All configuration is handled via environment variables passed through Docker/Unraid: - -- `PORT`: Server port (default: `3000`, internal) -- `MAX_FILE_SIZE`: Maximum upload size in bytes (default: `10485760` = 10MB) -- `TEMP_DIR`: Temporary directory for uploads (default: `/app/temp`) -- `NODE_ENV`: Node environment (default: `production`) - -## UI Features in Detail - -### Dark/Light Mode -- **Toggle Button**: Sun (☀️) / Moon (🌙) icon in header -- **Persistent**: Saved to localStorage -- **System Detection**: Uses OS preference on first visit -- **Smooth Transitions**: Colors fade smoothly (250ms) -- **Use Case**: Compare PNG transparency on black vs white backgrounds - -### Live Preview -- **Side-by-Side**: Original image on left, preview on right -- **File Size**: Shows before and after sizes -- **Savings Indicator**: Green for reduction, yellow for increase -- **Instant Updates**: Debounced at 300ms for smooth performance -- **Canvas-Based**: No server load, runs in browser - -### Drag & Drop Upload -- **Drop Zone**: Large, responsive drop target with visual feedback -- **Multiple Methods**: Drag & drop, click to browse, or paste from clipboard -- **File Validation**: Instant validation with clear error messages -- **Visual States**: Hover and dragging states for better UX - -### Smart Presets -- **8 Pre-configured Options**: Common use cases ready to go -- **One-Click Apply**: Instantly sets all parameters -- **Visual Icons**: Easy identification of each preset -- **Responsive Grid**: Adapts to screen size - -### Keyboard Shortcuts -- **Productivity Focused**: Common operations accessible via keyboard -- **Help Dialog**: Press ? to see all shortcuts -- **Context Aware**: Enter works differently based on focus -- **Cross-Platform**: Supports both Ctrl and Cmd modifiers - -### Image Analysis -- Original file size displayed -- Preview size estimation -- Savings/increase percentage -- Visual feedback with color coding - -## Recent Updates (Sprint 1) - -✅ **Drag & Drop Upload** - Drag images directly into the app -✅ **Clipboard Paste** - Paste images with Ctrl+V -✅ **Smart Presets** - 8 quick-access presets for common scenarios -✅ **Keyboard Shortcuts** - Fast workflow with keyboard controls -✅ **Enhanced UX** - Better visual feedback and error handling -✅ **Theme Contrast Fixes** - Improved text visibility in both themes - -See [SPRINT1_CHANGES.md](./SPRINT1_CHANGES.md) for detailed implementation notes. - -## Roadmap - -See [ROADMAP.md](./ROADMAP.md) for planned features including: -- Batch processing -- Advanced crop tool with visual selector -- Watermarking -- Image filters and effects -- And more! - -## License - -MIT License - See LICENSE file for details - -## Repository - -https://git.alwisp.com/jason/pnger - -## Screenshots - -### Light Mode -Clean white interface with dark gold accents, perfect for inspecting dark images - -### Dark Mode -Sleek black interface with light gold accents, ideal for viewing light/transparent PNGs - -### Live Preview -Side-by-side comparison showing original and transformed image with file size analysis - -### Smart Presets -Quick-access buttons for common image optimization scenarios - -### Keyboard Shortcuts -Built-in help dialog showing all available shortcuts \ No newline at end of file +**License**: MIT +**Repository**: [https://git.alwisp.com/jason/pnger](https://git.alwisp.com/jason/pnger) \ No newline at end of file diff --git a/ROADMAP.md b/ROADMAP.md index fc766bc..38c2140 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -1,385 +1,62 @@ # PNGer Feature Roadmap +PNGer is evolved through intentional sprints focusing on user experience, performance, and professional-grade features. + ## Completed Features ✅ -### Core Foundation -- ✅ Basic image upload (file picker, drag & drop, clipboard paste) -- ✅ Width/height resizing -- ✅ Aspect ratio control (inside/cover) -- ✅ Crop positioning (9 positions) -- ✅ Format conversion (PNG, WebP, JPEG) -- ✅ Quality adjustment (10-100%) -- ✅ Direct download (no server storage) -- ✅ Docker deployment -- ✅ **Live Preview** - Real-time side-by-side comparison with file size analysis -- ✅ **Dark/Light Mode** - Theme toggle for better PNG transparency inspection -- ✅ **Modern UI** - Sleek design with smooth transitions and visual feedback +### Sprint 0: Foundation (MVP) +- ✅ **Core Repository Setup**: Project structure and build systems. +- ✅ **Basic Image Operations**: Width/height resizing and quality adjustment. +- ✅ **Format Support**: Conversion between PNG, WebP, and JPEG. +- ✅ **Docker Deployment**: Multi-stage build for Unraid/Docker environments. +- ✅ **Stateless Processing**: Direct download from memory; no server storage. -### Sprint 1: Enhanced UX (Completed March 2026) -- ✅ **Drag & Drop Upload** - Drag images directly into the app -- ✅ **Clipboard Paste** - Paste with Ctrl+V (Cmd+V on Mac) -- ✅ **Smart Presets** - 8 quick-access presets: - - Web Optimized (1920x1080, 80%, WebP) - - Social Media (1080x1080, 85%, JPEG) - - Profile Picture (400x400, 90%, PNG) - - Email Friendly (800x600, 75%, JPEG) - - Tiny Icon (64x64, 100%, PNG) - - Retina 2x (2x dimensions, 90%) - - Icon Small (256x256, 95%, PNG) - - Icon Large (512x512, 95%, PNG) -- ✅ **Keyboard Shortcuts** - Fast workflow: - - Ctrl+V / Cmd+V: Paste image - - Enter: Transform & Download - - Ctrl+Enter / Cmd+Enter: Transform & Download (anywhere) - - ?: Show shortcuts help - - Esc: Close dialogs -- ✅ **Enhanced Visual Feedback** - Better loading states and error messages -- ✅ **Theme Contrast Fixes** - Improved text visibility in both themes +### Sprint 1: Enhanced UX & Live Preview (March 2026) +- ✅ **Live Preview**: Real-time side-by-side comparison with file size analysis. +- ✅ **Modern Design System**: Dark/Light mode toggle with persistent storage. +- ✅ **Drag & Drop Upload**: Intuitive drop zone with visual feedback. +- ✅ **Clipboard Paste**: Paste images directly with `Ctrl+V`. +- ✅ **Smart Presets**: 8 quick-access configurations for common use cases (Social Media, Web, Icons, etc.). +- ✅ **Keyboard Shortcuts**: Fast workflow with `Enter`, `?`, and `Esc`. +- ✅ **Performance Optimization**: Client-side Canvas rendering for instant feedback. --- -## Sprint 2: Batch Processing & Advanced Operations (Next Priority) -**Focus**: Handle multiple files and add essential image operations -**Effort**: ~12-15 hours | **Impact**: Very High | **Timeline**: Week 1-2 +## Future Roadmap 🚀 -### 2.1 Batch Processing 🚀 **HIGH VALUE** -**Why**: Process multiple images at once - massive time saver for bulk operations -**Effort**: Medium (6-8 hours) | **Impact**: Very High +### Sprint 2: Batch Processing & Advanced Operations +**Focus**: Efficiency and essential power-user tools. +- [ ] **Batch Processing**: Upload multiple images and process as a single ZIP. +- [ ] **Basic Transformations**: Rotate (90/180/Custom), Flip (H/V), and Grayscale. +- [ ] **Content-Aware Resize**: Smart cropping and aspect ratio enforcement. +- [ ] **Auto-Optimize**: One-click "best quality/size" ratio finder. -- [ ] Upload multiple images (10+ files) -- [ ] Apply same transformations to all -- [ ] Individual preview for each image -- [ ] Download as ZIP file -- [ ] Progress indicator for batch operations -- [ ] Cancel/remove individual files from queue -- [ ] Batch rename with pattern (e.g., `image-{index}.png`) -- [ ] Memory optimization for large batches +### Sprint 3: Polish & Professional Tools +**Focus**: Precision and customization. +- [ ] **Custom Crop Tool**: Visual selector with aspect ratio lock. +- [ ] **Watermarking**: Text and image-based branding. +- [ ] **Image Filters**: Brightness, Contrast, Saturation, and Sharpen. +- [ ] **Format Intelligence**: Suggestions based on image content (e.g., suggesting WebP for large images). -**Implementation Notes**: -- Use JSZip library for ZIP creation -- Process images in parallel (4-6 concurrent) -- Track individual file progress -- Client-side queue management - -### 2.2 Essential Image Operations 🎨 -**Why**: Basic operations users expect -**Effort**: Low-Medium (4-6 hours) | **Impact**: High - -- [ ] **Rotation**: 90°, 180°, 270°, custom angle -- [ ] **Flip**: Horizontal / Vertical -- [ ] **Grayscale**: Quick B&W conversion -- [ ] **Auto-rotate**: Based on EXIF orientation -- [ ] **Trim**: Remove transparent/white borders automatically - -**Technical**: All supported natively by Sharp library - -### 2.3 Image Optimization ⚡ **HIGH VALUE** -**Why**: One-click file size reduction without quality loss -**Effort**: Low (2-3 hours) | **Impact**: Very High - -- [ ] **Auto-Optimize** button - Smart quality/compression -- [ ] **Lossless PNG** optimization (pngquant-style) -- [ ] **Strip EXIF** metadata (privacy + file size) -- [ ] **Progressive JPEG** encoding -- [ ] **Compression comparison** - Show savings for each format -- [ ] **Target file size** - Optimize to hit specific size (e.g., "under 1MB") - -**Implementation**: Use Sharp's built-in optimization + custom quality detection +### Sprint 4: Workflow & Automation +**Focus**: Reusability and productivity. +- [ ] **Custom Presets**: Save and export personal transformation pipelines. +- [ ] **Processing History**: Recent files list (localStorage). +- [ ] **Undo/Redo**: History for parameter adjustments. --- -## Sprint 3: User Experience Polish (High Utility) -**Focus**: Make the app faster and more intuitive -**Effort**: ~10-12 hours | **Impact**: High | **Timeline**: Week 3-4 +## Priority Matrix -### 3.1 Quick Access Features ⏱️ -**Why**: Speed up repetitive tasks -**Effort**: Low (2-3 hours) | **Impact**: Medium-High - -- [ ] **Copy to Clipboard** - Copy processed image directly -- [ ] **Recent Files** - Quick access to last 10 processed images (localStorage) -- [ ] **Undo/Redo** - Revert parameter changes -- [ ] **Favorites** - Star frequently used presets -- [ ] **Quick Settings** - Toggle common options in header - -### 3.2 Image Analysis & Info 🔍 **HIGH VALUE** -**Why**: Understand your images better -**Effort**: Low (2-3 hours) | **Impact**: Medium-High - -- [ ] **Metadata Display**: Dimensions, format, color space, DPI -- [ ] **Color Palette Extraction**: Show dominant colors (5-8) -- [ ] **Transparency Detection**: Warn if converting transparent to JPEG -- [ ] **File Size Projection**: Estimate final size before download -- [ ] **Aspect Ratio Calculator**: Calculate dimensions maintaining ratio -- [ ] **Memory Usage**: Show current memory consumption - -### 3.3 Format Intelligence 🧠 -**Why**: Help users choose the right format -**Effort**: Low (2-3 hours) | **Impact**: Medium - -- [ ] **Format Recommendations**: Suggest best format based on image -- [ ] **Browser Support Detection**: Show WebP/AVIF compatibility -- [ ] **Multi-Format Export**: Generate PNG + WebP + JPEG at once -- [ ] **Responsive Image Sets**: Export multiple sizes for responsive design - -### 3.4 UI/UX Improvements -**Effort**: Low-Medium (3-4 hours) | **Impact**: Medium - -- [ ] **Mobile Responsive Design**: Better mobile/tablet experience -- [ ] **Toast Notifications**: Non-blocking feedback messages -- [ ] **Drag to Reorder**: Reorder batch queue -- [ ] **Compare Mode**: Slider to compare before/after -- [ ] **Zoom Controls**: Zoom in on preview images -- [ ] **Grid/List Toggle**: Switch preview layout +| Feature | Impact | Effort | Priority | +|---------|--------|--------|----------| +| Batch Processing | Very High | Medium | 1 | +| Auto-Optimize | High | Low | 1 | +| Custom Crop | High | High | 2 | +| Watermarking | Medium | Medium | 3 | --- -## Sprint 4: Advanced Features (Power Users) -**Focus**: Professional-grade tools -**Effort**: ~15-20 hours | **Impact**: Medium-High | **Timeline**: Week 5-6 - -### 4.1 Custom Crop Tool ✂️ -**Why**: Precise control over cropping -**Effort**: High (8-10 hours) | **Impact**: Medium-High - -- [ ] **Visual Crop Selector**: Interactive drag handles -- [ ] **Aspect Ratio Lock**: 16:9, 4:3, 1:1, custom -- [ ] **Freeform Cropping**: No ratio constraints -- [ ] **Rule of Thirds Grid**: Photography composition guide -- [ ] **Golden Ratio Grid**: Advanced composition -- [ ] **Zoom for Precision**: Zoom in for pixel-perfect crops -- [ ] **Crop Presets**: Social media sizes (Instagram, Facebook, etc.) - -### 4.2 Filters & Effects 🌈 -**Why**: Quick image enhancements -**Effort**: Medium (5-6 hours) | **Impact**: Medium - -- [ ] **Brightness/Contrast**: Adjust exposure -- [ ] **Saturation**: Boost or reduce colors -- [ ] **Sharpness**: Enhance edges -- [ ] **Blur**: Gaussian blur with radius control -- [ ] **Tint**: Apply color overlay -- [ ] **Vintage Filter**: Sepia tone -- [ ] **Invert Colors**: Negative effect -- [ ] **Filter Presets**: Quick apply common filters - -### 4.3 Watermarking 📝 -**Why**: Protect and brand images -**Effort**: Medium (4-5 hours) | **Impact**: Medium - -- [ ] **Text Watermark**: Custom text with font selection -- [ ] **Image Watermark**: Upload logo overlay -- [ ] **Position Control**: 9 positions + custom X/Y -- [ ] **Opacity**: Adjust transparency (0-100%) -- [ ] **Repeat Pattern**: Tile watermark across image -- [ ] **Batch Watermark**: Apply to all images in batch - ---- - -## Sprint 5: Workflow & Automation (Productivity) -**Focus**: Save time with reusable workflows -**Effort**: ~8-10 hours | **Impact**: Medium | **Timeline**: Week 7+ - -### 5.1 Custom Presets & Templates -**Why**: Reusable transformation pipelines -**Effort**: Low-Medium (3-4 hours) | **Impact**: Medium - -- [ ] **Save Custom Presets**: Create your own quick-access presets -- [ ] **Preset Categories**: Organize by use case -- [ ] **Import/Export Presets**: Share as JSON files -- [ ] **Transformation Chains**: Combine multiple operations -- [ ] **Preset Shortcuts**: Assign keyboard shortcuts (1-9 keys) -- [ ] **Community Presets**: Gallery of user-submitted presets - -### 5.2 History & Session Management -**Why**: Track and repeat common tasks -**Effort**: Low (2-3 hours) | **Impact**: Low-Medium - -- [ ] **Processing History**: Last 50 transformations -- [ ] **Quick Re-apply**: Reload previous settings -- [ ] **Export History**: Save session as JSON -- [ ] **Clear History**: Privacy button -- [ ] **Session Restore**: Resume after browser close - ---- - -## Future: Extended Format Support (Lower Priority) -**Focus**: Support more file types -**Effort**: Variable | **Impact**: Situational - -### Additional Formats -- [ ] **AVIF Support**: Next-gen image format -- [ ] **TIFF Support**: Professional photography -- [ ] **SVG to Raster**: Convert vector to bitmap -- [ ] **ICO Generation**: Create favicons (16, 32, 48, 64, 128, 256px) -- [ ] **PDF to Image**: Extract first page as image -- [ ] **GIF Frame Extraction**: Convert animated GIF to frames -- [ ] **HEIC/HEIF Support**: Apple photo format - ---- - -## Enterprise & API (Optional) -**Focus**: For hosted/managed deployments -**Effort**: High | **Impact**: Situational - -### API Access -- [ ] Generate API keys in UI -- [ ] Rate limiting per key -- [ ] Usage statistics dashboard -- [ ] Webhook support for async processing -- [ ] OpenAPI/Swagger documentation -- [ ] SDK libraries (Python, Node.js, PHP) - -### User Accounts (Optional) -- [ ] User authentication -- [ ] Per-user quotas -- [ ] Cloud storage integration (S3, MinIO) -- [ ] Saved presets sync -- [ ] Usage analytics -- [ ] Team collaboration features - ---- - -## New High-Value Ideas 💡 - -### Image Comparison Tool 🔍 -**Why**: A/B test different settings -**Effort**: Low-Medium (3-4 hours) | **Impact**: Medium - -- [ ] Side-by-side comparison of 2-4 versions -- [ ] Slider reveal to show differences -- [ ] Quality vs file size comparison matrix -- [ ] Export comparison settings for sharing - -### Background Removal ✨ **HIGH VALUE** -**Why**: Remove backgrounds automatically -**Effort**: Medium-High (6-8 hours) | **Impact**: Very High - -- [ ] AI-powered background removal (using @imgly/background-removal or similar) -- [ ] Replace with solid color -- [ ] Replace with gradient -- [ ] Replace with uploaded image -- [ ] Transparency preservation -- [ ] Edge refinement controls - -### Smart Resize 🦾 **HIGH VALUE** -**Why**: Content-aware resizing -**Effort**: Medium (4-5 hours) | **Impact**: High - -- [ ] **Content-aware scaling**: Preserve important areas -- [ ] **Face detection**: Protect faces during crop -- [ ] **Center of interest**: Auto-detect focal point -- [ ] **Smart crop suggestions**: AI-suggested crop areas - -### Color Adjustments 🎨 -**Why**: Fine-tune image colors -**Effort**: Medium (4-5 hours) | **Impact**: Medium - -- [ ] **Hue/Saturation/Lightness** sliders -- [ ] **Color temperature** (warm/cool) -- [ ] **Vibrance** (selective saturation) -- [ ] **Color balance** (shadows, midtones, highlights) -- [ ] **White balance correction** -- [ ] **Color grading presets** - -### Border & Frame Effects 🖼️ -**Why**: Add decorative elements -**Effort**: Low-Medium (3-4 hours) | **Impact**: Low-Medium - -- [ ] **Solid borders**: Color and thickness -- [ ] **Padding**: Add transparent/colored space -- [ ] **Rounded corners**: Border radius control -- [ ] **Shadow effects**: Drop shadow with blur -- [ ] **Frame templates**: Decorative frames -- [ ] **Polaroid effect**: Instant camera style - -### Image Merge & Collage 🖼️ -**Why**: Combine multiple images -**Effort**: High (8-10 hours) | **Impact**: Medium - -- [ ] **Side-by-side merge**: Horizontal/vertical -- [ ] **Grid layout**: 2x2, 3x3, custom -- [ ] **Collage templates**: Pre-designed layouts -- [ ] **Spacing control**: Gap between images -- [ ] **Background color**: For gaps - -### Conditional Processing 🤖 -**Why**: Smart automation based on image properties -**Effort**: Medium (4-5 hours) | **Impact**: Medium - -- [ ] **Size-based rules**: Different settings for large vs small images -- [ ] **Format detection**: Auto-convert based on transparency -- [ ] **Quality ranges**: Set min/max quality constraints -- [ ] **Dimension limits**: Enforce max width/height - ---- - -## Technical Debt & Infrastructure - -### Code Quality -- [ ] Unit tests (backend) - Vitest/Jest -- [ ] E2E tests (frontend) - Playwright -- [ ] TypeScript strict mode -- [ ] ESLint + Prettier configuration -- [ ] CI/CD pipeline (GitHub Actions or Gitea Actions) -- [ ] Code coverage reporting (>80%) -- [ ] Automated dependency updates (Renovate) - -### Performance -- [ ] Image processing queue (for heavy operations) -- [ ] Web Workers for client-side processing -- [ ] Service Worker for offline support -- [ ] Lazy loading for UI components -- [ ] Memory leak detection and fixes -- [ ] Performance monitoring (Lighthouse CI) - -### Security -- [ ] Rate limiting (prevent abuse) -- [ ] File type validation (magic bytes check) -- [ ] Max file size enforcement (configurable) -- [ ] CORS configuration hardening -- [ ] CSP headers -- [ ] Input sanitization audit -- [ ] Security headers (HSTS, X-Frame-Options) -- [ ] Dependency vulnerability scanning - -### Monitoring & Analytics -- [ ] Prometheus metrics endpoint -- [ ] Error tracking (Sentry integration) -- [ ] Performance monitoring (Real User Monitoring) -- [ ] Usage analytics (privacy-focused, self-hosted) -- [ ] Health check dashboard - ---- - -## Priority Matrix (Updated) - -### Immediate Next Steps (Sprint 2) -1. 🚀 **Batch Processing** - Highest utility, medium effort -2. ⚡ **Auto-Optimize** - Quick win, very high value -3. 🎨 **Basic Operations** - Essential features (rotate, flip, grayscale) - -### High Value, Medium Effort (Sprint 3-4) -4. 🔍 **Image Analysis** - Understand images better -5. ✨ **Background Removal** - AI-powered, huge demand -6. 🦾 **Smart Resize** - Content-aware scaling -7. ✂️ **Custom Crop Tool** - Professional precision - -### Polish & Productivity (Sprint 5+) -8. ⏱️ **Quick Access Features** - Speed up workflow -9. 📝 **Custom Presets** - Reusable workflows -10. 🎨 **Filters & Effects** - Creative options - ---- - -## Community Ideas - -Have suggestions? Open an issue on the repository: -- Feature requests -- Bug reports -- Use case discussions -- Performance improvements - -**Maintainer**: jason -**Repository**: https://git.alwisp.com/jason/pnger -**Last Updated**: March 8, 2026 (Sprint 1 Complete) \ No newline at end of file +**Project Maintainer**: jason +**Repository**: [jason/pnger](https://git.alwisp.com/jason/pnger) +**Last Strategy Sync**: March 12, 2026 \ No newline at end of file diff --git a/SPRINT1_CHANGES.md b/SPRINT1_CHANGES.md deleted file mode 100644 index 2e53a16..0000000 --- a/SPRINT1_CHANGES.md +++ /dev/null @@ -1,239 +0,0 @@ -# Sprint 1 Changes - UX Enhancements - -**Branch**: `feature/sprint1-dragdrop-presets-shortcuts` -**Date**: 2026-03-08 -**Status**: Ready for Testing - -## 🎯 Overview - -This sprint focuses on making PNGer significantly more intuitive and powerful with three major feature additions plus a critical bug fix. - ---- - -## ✅ Bug Fix: Preview File Size Calculation - -### Problem -- Preview file size was not calculating correctly -- Size didn't update when adjusting quality slider -- Format changes weren't reflected in estimated size - -### Solution -- Fixed base64 size estimation algorithm in `preview.ts` -- Properly map format to MIME types (png, jpeg, webp) -- Quality parameter now correctly applied to JPEG and WebP -- Improved padding calculation for accurate byte estimation - -### Files Changed -- `frontend/src/lib/preview.ts` - ---- - -## 🆕 Feature 1: Drag & Drop Upload - -### What's New -- **Drag & drop zone** with visual feedback -- Hover state shows accent color -- Dragging over triggers highlight animation -- **Clipboard paste support** (Ctrl+V / Cmd+V) -- File info displayed after upload (name + size) -- One-click "Clear File" button - -### User Benefits -- No more hunting for file picker -- Instant image upload from screenshots (paste) -- Modern, expected behavior -- Faster workflow - -### Technical Implementation -- `dragover`, `dragleave`, `drop` event handlers -- Clipboard paste event listener -- File type validation -- Visual state management with `isDragging` flag - -### Files Changed -- `frontend/src/App.svelte` (drag handlers + paste support) - ---- - -## 🎯 Feature 2: Smart Presets - -### What's New -8 built-in presets for common use cases: - -1. **🖼️ Web Thumbnail** - 300x300, WebP, 75% quality, cover -2. **📱 Social Media** - 1200x630 Open Graph, PNG, 85%, cover -3. **👤 Profile Picture** - 400x400 square, PNG, 85%, cover -4. **📧 Email Friendly** - 600px wide, JPEG, 70%, optimized -5. **⭐ HD Quality** - 1920px wide, PNG, 90%, high-res -6. **🔍 Retina @2x** - Doubles current dimensions, PNG, 85% -7. **🔷 Icon Small** - 64x64, PNG, 100%, cover -8. **🔶 Icon Large** - 256x256, PNG, 100%, cover - -### User Benefits -- One-click transformations for common tasks -- No need to remember optimal settings -- Saves time on repetitive operations -- Perfect for non-technical users - -### Technical Implementation -- New `presets.ts` module with preset definitions -- `applyPreset()` function with special Retina @2x logic -- 4-column grid layout -- Hover effects with elevation -- Icon + name display - -### Files Changed -- `frontend/src/lib/presets.ts` (new file) -- `frontend/src/App.svelte` (preset UI + selection logic) - ---- - -## ⌨️ Feature 3: Keyboard Shortcuts - -### What's New - -**Shortcuts Available:** -- `Ctrl+V` / `Cmd+V` - Paste image from clipboard -- `Enter` - Transform & Download (when not in input) -- `Ctrl+Enter` / `Cmd+Enter` - Transform & Download (anywhere) -- `?` - Show/hide shortcuts help -- `Esc` - Close shortcuts dialog - -**Shortcuts Help Modal:** -- Clean, centered modal -- Keyboard key styling (``) -- Click outside to close -- Fade-in animation - -### User Benefits -- Power users can work without mouse -- Faster workflow for repetitive tasks -- Discoverable via `?` key -- Professional touch - -### Technical Implementation -- Document-level `keydown` event listener -- Active element detection (skip Enter if input focused) -- Modal overlay with portal pattern -- `onMount` setup and cleanup - -### Files Changed -- `frontend/src/App.svelte` (keyboard handlers + modal) - ---- - -## 🎨 UI/UX Improvements - -### Additional Polish -- **Shortcuts button** in header (⌨️ icon) -- **Hint text** under download button: "Press Enter to download" -- **Drop zone improvements**: better empty state messaging -- **Preset icons**: visual indicators for each preset type -- **Modal styling**: professional overlay with backdrop blur -- **Responsive kbd tags**: monospace font with shadow effect - ---- - -## 📊 Testing Checklist - -### Bug Fix Validation -- [ ] Upload image, adjust quality slider - size updates in real-time -- [ ] Change format PNG → JPEG → WebP - size reflects format -- [ ] Compare preview size with actual downloaded file size - -### Drag & Drop -- [ ] Drag image file onto drop zone - uploads successfully -- [ ] Drag non-image file - shows error -- [ ] Hover during drag - shows visual feedback -- [ ] Drop outside zone - no action - -### Clipboard Paste -- [ ] Take screenshot, press Ctrl+V - pastes image -- [ ] Copy image from browser, paste - works -- [ ] Paste non-image - no error - -### Presets -- [ ] Click "Web Thumbnail" - sets 300x300, WebP, 75%, cover -- [ ] Click "Social Media" - sets 1200x630, PNG, 85%, cover -- [ ] Click "Retina @2x" with 500x500 image - doubles to 1000x1000 -- [ ] All 8 presets apply correctly - -### Keyboard Shortcuts -- [ ] Press `?` - shows shortcuts modal -- [ ] Press `Esc` in modal - closes modal -- [ ] Press `Enter` with image loaded - downloads -- [ ] Press `Enter` while typing in input - types Enter (doesn't download) -- [ ] Press `Ctrl+Enter` anywhere - downloads -- [ ] Press `Ctrl+V` - pastes from clipboard - -### Cross-Browser -- [ ] Chrome/Edge - all features work -- [ ] Firefox - all features work -- [ ] Safari - all features work (Cmd key instead of Ctrl) - ---- - -## 📝 Files Changed Summary - -### New Files -1. `frontend/src/lib/presets.ts` - Preset definitions and apply logic -2. `SPRINT1_CHANGES.md` - This document - -### Modified Files -1. `frontend/src/lib/preview.ts` - Fixed size calculation bug -2. `frontend/src/App.svelte` - Major update with all 3 features -3. `ROADMAP.md` - Marked Phase 1.1 complete, added sprint plan - ---- - -## 🚀 Performance Notes - -- **No performance impact**: All features are client-side -- **Preview debounce**: Still 300ms, works great with presets -- **Modal render**: Only renders when `showShortcuts = true` -- **Drag handlers**: Lightweight event listeners -- **Preset selection**: Instant application (<10ms) - ---- - -## 🔧 Development Notes - -### Code Quality -- TypeScript strict types maintained -- Svelte reactivity patterns followed -- Event cleanup in `onMount` return -- CSS animations for smooth UX -- Semantic HTML structure - -### Future Enhancements -- [ ] Multi-file batch processing (use drag & drop foundation) -- [ ] Custom preset saving (localStorage) -- [ ] Preset import/export -- [ ] More keyboard shortcuts (arrow keys for presets?) - ---- - -## ✅ Ready for Merge - -This branch is ready to merge to `main` once testing is complete. - -**Merge Command:** -```bash -git checkout main -git merge feature/sprint1-dragdrop-presets-shortcuts -git push origin main -``` - -**Deployment:** -No backend changes - just rebuild frontend Docker image. - ---- - -## 💬 Next Sprint Suggestions - -After this sprint, consider: -1. **Sprint 2A**: Batch processing (multi-file upload) -2. **Sprint 2B**: Additional transformations (rotate, flip, filters) -3. **Sprint 2C**: Auto-optimize feature - -See `ROADMAP.md` for full feature planning. \ No newline at end of file diff --git a/UI_UPGRADE_NOTES.md b/UI_UPGRADE_NOTES.md deleted file mode 100644 index bbc0bbf..0000000 --- a/UI_UPGRADE_NOTES.md +++ /dev/null @@ -1,413 +0,0 @@ -# UI Upgrade - Dark Mode & Live Preview - -## Overview - -This branch introduces a complete UI overhaul with modern design, dark/light mode theming, and real-time live preview functionality. - -## What's New - -### 🎨 Modern Design System - -**Color Themes:** -- **Light Mode**: Clean white background with dark gold (#b8860b) accents -- **Dark Mode**: Deep black (#0a0a0a) background with light gold (#daa520) accents -- Smooth transitions between themes -- System preference detection on first load - -**Design Tokens:** -- CSS custom properties for consistent spacing, colors, shadows -- Responsive typography scale -- Smooth animations and transitions -- Modern card-based layout -- Professional shadows and borders - -### 🌙 Dark/Light Mode Toggle - -- One-click theme switching -- Persistent preference (localStorage) -- Smooth color transitions -- Icon indicators (☀️/🌙) -- Perfect for comparing PNG transparency on different backgrounds - -### ⚡ Live Preview - -**Instant Visual Feedback:** -- Real-time preview updates as you adjust settings -- Side-by-side comparison (original vs transformed) -- No server round-trip required (client-side Canvas API) -- Debounced updates (300ms) for performance - -**Preview Features:** -- Shows exact transformations before download -- File size comparison -- Savings/increase indicator with percentage -- Color-coded feedback (green = savings, yellow = increase) -- Maintains aspect ratio and crop preview - -### 📊 Enhanced Information Display - -- Original file name and size shown -- Preview file size estimation -- Savings calculation with visual indicators -- Quality slider with percentage display -- Clear visual separation of controls and preview - -### 💅 Visual Improvements - -**Layout:** -- Two-column grid layout (controls | preview) -- Card-based design with subtle shadows -- Proper spacing and visual hierarchy -- Responsive design (mobile-friendly) - -**Interactions:** -- Smooth hover effects on buttons -- Focus states with accent color -- Loading spinners for processing states -- Fade-in animations -- Button transforms on hover - -**Typography:** -- System font stack (native look & feel) -- Proper heading hierarchy -- Readable line heights -- Color-coded text (primary, secondary, accent) - -## Files Modified - -### New Files - -1. **`frontend/src/lib/preview.ts`** - - Client-side preview generation using Canvas API - - Image transformation calculations - - File size estimation - - Utility functions (debounce, format bytes, calculate savings) - -2. **`frontend/src/lib/theme.ts`** - - Svelte store for theme management - - localStorage persistence - - System preference detection - - Theme toggle functionality - -### Updated Files - -3. **`frontend/src/app.css`** - - Complete design system rewrite - - CSS custom properties for theming - - Dark mode support via `[data-theme="dark"]` - - Modern component styles (buttons, inputs, cards) - - Utility classes for layout - - Responsive breakpoints - - Custom scrollbar styling - - Animation keyframes - -4. **`frontend/src/App.svelte`** - - Complete UI restructuring - - Two-column layout with grid - - Live preview integration - - Theme toggle button - - Enhanced file upload UI - - Clear file button - - Improved error handling display - - Loading states with spinners - - Side-by-side image comparison - - Savings indicator card - -## Technical Details - -### Preview Implementation - -**How it works:** -1. User uploads image -2. Canvas API loads image into memory -3. Transformations applied client-side: - - Resize calculations (aspect ratio aware) - - Crop positioning (9 positions supported) - - Quality adjustment via canvas.toDataURL() -4. Preview updates on parameter change (debounced) -5. File size estimated from base64 data URL - -**Performance:** -- Debounced at 300ms to avoid excessive redraws -- Canvas operations run on main thread (future: Web Worker) -- Preview max size limited by browser memory -- No server load for preview generation - -### Theme System - -**Storage:** -```typescript -localStorage.setItem('theme', 'dark' | 'light') -``` - -**Application:** -```html - - - -``` - -**CSS Variables:** -```css -:root { --color-accent: #b8860b; } /* Light mode */ -[data-theme="dark"] { --color-accent: #daa520; } /* Dark mode */ -``` - -### Design Tokens - -**Spacing Scale:** -- xs: 0.25rem (4px) -- sm: 0.5rem (8px) -- md: 1rem (16px) -- lg: 1.5rem (24px) -- xl: 2rem (32px) -- 2xl: 3rem (48px) - -**Color Palette:** - -| Light Mode | Dark Mode | Purpose | -|------------|-----------|----------| -| #ffffff | #0a0a0a | Primary BG | -| #f8f9fa | #1a1a1a | Secondary BG | -| #e9ecef | #2a2a2a | Tertiary BG | -| #b8860b | #daa520 | Accent (Gold) | -| #1a1a1a | #e9ecef | Text Primary | -| #6c757d | #adb5bd | Text Secondary | - -**Shadows:** -- sm: Subtle card elevation -- md: Button hover states -- lg: Modal/dropdown shadows -- xl: Maximum elevation - -## User Experience Improvements - -### Before vs After - -**Before:** -- Static form with no feedback -- Download to see results -- Trial and error workflow -- Basic styling -- No theme options - -**After:** -- ✅ Real-time preview -- ✅ See before download -- ✅ Immediate feedback loop -- ✅ Modern, professional design -- ✅ Dark/light mode for different PNGs -- ✅ File size visibility -- ✅ Savings indicator - -### Use Cases Enhanced - -1. **Comparing Transparency** - - Toggle dark/light mode to see PNG transparency - - Useful for logos, icons with transparency - -2. **Optimizing File Size** - - See file size impact immediately - - Adjust quality until size is acceptable - - Green indicator shows successful optimization - -3. **Precise Cropping** - - See crop position in real-time - - Try all 9 positions visually - - No guesswork needed - -4. **Format Comparison** - - Compare PNG vs WebP vs JPEG quality - - See size differences instantly - - Make informed format choice - -## Browser Compatibility - -**Tested On:** -- Chrome 90+ -- Firefox 88+ -- Safari 14+ -- Edge 90+ - -**Requirements:** -- Canvas API support -- CSS Custom Properties -- localStorage -- ES6 modules - -## Performance Metrics - -**Preview Generation:** -- Small images (< 1MB): ~50-100ms -- Medium images (1-5MB): ~200-400ms -- Large images (5-10MB): ~500ms-1s - -**Memory Usage:** -- Canvas limited by browser (typically 512MB max) -- Preview auto-cleanup on file change -- No memory leaks detected - -## Future Enhancements - -### Planned (Not in This Branch) - -- [ ] Slider comparison (drag to reveal differences) -- [ ] Zoom on preview for detail inspection -- [ ] Web Worker for preview generation -- [ ] Server-side preview option (Sharp accuracy) -- [ ] Multiple preview sizes simultaneously -- [ ] Drag & drop file upload -- [ ] Batch preview mode - -## Testing Checklist - -### Manual Testing - -- [x] Upload PNG image -- [x] Upload JPEG image -- [x] Upload WebP image -- [x] Adjust width only -- [x] Adjust height only -- [x] Adjust both dimensions -- [x] Change quality slider -- [x] Switch between formats -- [x] Toggle fit mode (inside/cover) -- [x] Test all 9 crop positions -- [x] Toggle dark/light mode -- [x] Verify theme persistence (refresh page) -- [x] Clear file and re-upload -- [x] Download transformed image -- [x] Compare downloaded vs preview -- [x] Test on mobile (responsive) - -### Edge Cases - -- [ ] Very large image (> 10MB) -- [ ] Very small image (< 10KB) -- [ ] Square images -- [ ] Panoramic images (extreme aspect ratios) -- [ ] Images with transparency -- [ ] Animated GIFs (should show first frame) - -### Performance - -- [ ] Preview updates < 500ms -- [ ] No UI blocking during preview -- [ ] Smooth theme transitions -- [ ] No console errors -- [ ] Memory cleanup verified - -## Deployment Notes - -### Build Requirements - -- No new dependencies added -- Uses existing Svelte + Vite setup -- Compatible with current Docker build - -### Breaking Changes - -- None - fully backward compatible -- API unchanged -- Old URL parameters still work - -### Environment Variables - -- No new env vars required -- Theme stored client-side only - -## Usage Guide - -### For End Users - -1. **Upload Image**: Click "Select Image" or use file picker -2. **Adjust Settings**: Use controls on the left -3. **Watch Preview**: See changes in real-time on the right -4. **Toggle Theme**: Click sun/moon button for dark/light mode -5. **Check Savings**: Green box shows file size reduction -6. **Download**: Click "Transform & Download" when satisfied - -### For Developers - -**Adding a New Control:** -```svelte - - -
- - -
-``` - -**Extending Theme:** -```css -/* In app.css */ -:root { - --color-new-token: #value; -} - -[data-theme="dark"] { - --color-new-token: #dark-value; -} -``` - -## Screenshots (Conceptual) - -### Light Mode -``` -┌───────────────────────────────────────┐ -│ PNGer 🌙 Dark │ -│ Modern PNG Editor & Resizer │ -├──────────────────┬────────────────────┤ -│ Upload & Transform │ Live Preview │ -│ │ │ -│ [File picker] │ [Original] [Prev] │ -│ Width: [ ] │ │ -│ Height: [ ] │ ↓ 450KB saved │ -│ Quality: 80% │ │ -│ Format: PNG │ │ -│ [Download Button] │ │ -└──────────────────┴────────────────────┘ -``` - -### Dark Mode -``` -┌───────────────────────────────────────┐ -│ ✨PNGer✨ ☀️ Light │ -│ Modern PNG Editor & Resizer │ -├──────────────────┬────────────────────┤ -│ 💻Upload & Transform│ 🖼️Live Preview │ -│ (Black BG) │ (Black BG) │ -│ Gold accents │ Gold borders │ -└──────────────────┴────────────────────┘ -``` - -## Merge Checklist - -- [x] All new files created -- [x] All existing files updated -- [x] No console errors -- [x] Dark mode works -- [x] Light mode works -- [x] Theme persists across refreshes -- [x] Preview generates correctly -- [x] File size calculations accurate -- [x] Responsive design tested -- [ ] Ready to merge to main - ---- - -**Branch**: `feature/ui-upgrade-dark-mode-preview` -**Created**: 2026-03-08 -**Status**: ✅ Ready for Testing -**Merge Target**: `main` - -**Next Steps**: -1. Build and test locally -2. Deploy to staging -3. User acceptance testing -4. Merge to main -5. Deploy to production \ No newline at end of file diff --git a/docs/LIVE_PREVIEW_IMPLEMENTATION.md b/docs/LIVE_PREVIEW_IMPLEMENTATION.md deleted file mode 100644 index af2b91e..0000000 --- a/docs/LIVE_PREVIEW_IMPLEMENTATION.md +++ /dev/null @@ -1,366 +0,0 @@ -# Live Preview Implementation Guide - -## Overview - -Live Preview is the #1 priority feature for PNGer. This guide outlines the implementation approach. - -## Goals - -1. **Instant Feedback**: Show preview within 100ms of parameter change -2. **Accurate Rendering**: Match final output as closely as possible -3. **Performance**: Don't block UI, handle large images efficiently -4. **Progressive**: Show low-quality preview immediately, high-quality after - -## Architecture - -### Approach: Hybrid Client + Server Preview - -``` -┌─────────────┐ -│ Upload │ -│ Image │ -└──────┬──────┘ - │ - v -┌─────────────────────────────────┐ -│ Client-Side Preview (Canvas) │ <-- Instant (< 100ms) -│ - Fast, approximate rendering │ -│ - Uses browser native resize │ -│ - Good for basic operations │ -└─────────┬───────────────────────┘ - │ - v -┌─────────────────────────────────┐ -│ Server Preview API (Optional) │ <-- Accurate (500ms-2s) -│ - Uses Sharp (same as export) │ -│ - Exact output representation │ -│ - Debounced to avoid spam │ -└─────────────────────────────────┘ -``` - -## Implementation Steps - -### Phase 1: Client-Side Preview (Quick Win) - -**Files to Modify:** -- `frontend/src/App.svelte` -- `frontend/src/lib/preview.ts` (new) - -**Key Features:** -1. Canvas-based image rendering -2. Debounced updates (300ms after parameter change) -3. Show original and preview side-by-side -4. Display file size estimate - -**Code Skeleton:** - -```typescript -// frontend/src/lib/preview.ts -export async function generateClientPreview( - file: File, - options: TransformOptions -): Promise { - return new Promise((resolve) => { - const img = new Image(); - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d')! - - img.onload = () => { - // Calculate dimensions - const { width, height } = calculateDimensions(img, options); - - canvas.width = width; - canvas.height = height; - - // Apply transforms - if (options.fit === 'cover') { - drawCover(ctx, img, width, height, options.position); - } else { - ctx.drawImage(img, 0, 0, width, height); - } - - // Apply filters (grayscale, blur, etc.) - applyFilters(ctx, options); - - // Convert to data URL - const quality = options.quality / 100; - const dataUrl = canvas.toDataURL(`image/${options.format}`, quality); - resolve(dataUrl); - }; - - img.src = URL.createObjectURL(file); - }); -} -``` - -**UI Updates:** - -```svelte - - - - -{#if file && previewUrl} -
-
-
-

Original

- Original -

{formatFileSize(originalSize)}

-
-
-

Preview

- Preview -

{formatFileSize(previewSize)}

-

- {calculateSavings(originalSize, previewSize)} -

-
-
-
-{/if} -``` - -### Phase 2: Server Preview API (Accurate) - -**Files to Modify:** -- `backend/src/routes/image.ts` - -**New Endpoint:** - -```typescript -// POST /api/preview (returns base64 or temp URL) -router.post( - "/preview", - upload.single("file"), - async (req, res): Promise => { - // Same processing as /transform - // But return as base64 data URL or temp storage URL - // Max preview size: 1200px (for performance) - - const previewBuffer = await image.toBuffer(); - const base64 = previewBuffer.toString('base64'); - - res.json({ - preview: `data:image/${format};base64,${base64}`, - size: previewBuffer.length, - dimensions: { width: metadata.width, height: metadata.height } - }); - } -); -``` - -**Benefits:** -- Exact rendering (uses Sharp like final output) -- Shows actual file size -- Handles complex operations client can't do - -**Trade-offs:** -- Slower (network round-trip) -- Server load (mitigate with rate limiting) - -### Phase 3: Progressive Loading - -**Enhancement**: Show low-quality preview first, then high-quality - -```typescript -// Generate two previews: -// 1. Immediate low-res (client-side, 200px max) -// 2. Delayed high-res (server-side, full resolution) - -async function generateProgressivePreview() { - // Step 1: Fast low-res - const lowRes = await generateClientPreview(file, { - ...options, - width: Math.min(options.width || 200, 200), - height: Math.min(options.height || 200, 200) - }); - previewUrl = lowRes; // Show immediately - - // Step 2: High-res from server (debounced) - const highRes = await fetchServerPreview(file, options); - previewUrl = highRes; // Replace when ready -} -``` - -## File Size Estimation - -```typescript -function estimateSize(dataUrl: string): number { - // Base64 data URL size (approximate) - const base64Length = dataUrl.split(',')[1].length; - return Math.ceil((base64Length * 3) / 4); // Convert base64 to bytes -} - -function formatFileSize(bytes: number): string { - if (bytes < 1024) return `${bytes} B`; - if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`; - return `${(bytes / (1024 * 1024)).toFixed(2)} MB`; -} - -function calculateSavings(original: number, preview: number): string { - const diff = original - preview; - const percent = ((diff / original) * 100).toFixed(1); - if (diff > 0) return `↓ ${formatFileSize(diff)} saved (${percent}%)`; - if (diff < 0) return `↑ ${formatFileSize(-diff)} larger (${Math.abs(Number(percent))}%)`; - return 'Same size'; -} -``` - -## UI/UX Considerations - -### Layout Options - -**Option A: Side-by-Side** -``` -┌──────────────┬──────────────┐ -│ Original │ Preview │ -│ │ │ -│ [Image] │ [Image] │ -│ 2.4 MB │ 450 KB │ -│ 1920x1080 │ 800x600 │ -└──────────────┴──────────────┘ -``` - -**Option B: Slider Compare** -``` -┌────────────────────────────┐ -│ [<──── Slider ────>] │ -│ Original │ Preview │ -│ │ │ -└────────────────────────────┘ -``` - -**Option C: Tabs** -``` -┌─ Original ─┬─ Preview ─────┐ -│ │ -│ [Image] │ -│ │ -└─────────────────────────────┘ -``` - -**Recommendation**: Start with Option A (simplest), add Option B later for detail comparison. - -## Performance Optimizations - -### 1. Debouncing -```typescript -function debounce any>( - func: T, - wait: number -): (...args: Parameters) => void { - let timeout: ReturnType; - return (...args: Parameters) => { - clearTimeout(timeout); - timeout = setTimeout(() => func(...args), wait); - }; -} -``` - -### 2. Image Downsampling -- Preview max size: 1200px (retina displays) -- Original size only for final download -- Reduces memory usage and processing time - -### 3. Worker Thread (Advanced) -- Offload canvas operations to Web Worker -- Keeps UI responsive during processing - -```typescript -// preview.worker.ts -self.onmessage = async (e) => { - const { file, options } = e.data; - const preview = await generatePreview(file, options); - self.postMessage({ preview }); -}; -``` - -## Testing Plan - -### Unit Tests -- [ ] `calculateDimensions()` with various aspect ratios -- [ ] `formatFileSize()` edge cases -- [ ] `debounce()` timing - -### Integration Tests -- [ ] Preview updates on parameter change -- [ ] Preview matches final output (within tolerance) -- [ ] Large image handling (> 10MB) -- [ ] Multiple format conversions - -### Manual Tests -- [ ] Mobile responsiveness -- [ ] Slow network simulation -- [ ] Various image formats (PNG, JPEG, WebP) -- [ ] Edge cases (1x1px, 10000x10000px) - -## Rollout Strategy - -### Step 1: Feature Flag -```typescript -// Enable via environment variable -const ENABLE_PREVIEW = import.meta.env.VITE_ENABLE_PREVIEW === 'true'; -``` - -### Step 2: Beta Testing -- Deploy to staging environment -- Gather user feedback -- Monitor performance metrics - -### Step 3: Gradual Rollout -- Enable for 10% of users -- Monitor error rates -- Full rollout if stable - -## Success Metrics - -- **User Engagement**: Time spent on page increases -- **Conversion**: More downloads completed -- **Performance**: Preview renders in < 500ms (p95) -- **Accuracy**: Preview matches output 95%+ of time -- **Satisfaction**: User feedback positive - -## Future Enhancements - -- [ ] Before/after slider with drag handle -- [ ] Zoom on preview (inspect details) -- [ ] Multiple preview sizes simultaneously -- [ ] A/B comparison (compare 2-4 settings) -- [ ] Preview history (undo/redo preview) -- [ ] Export preview settings as preset - ---- - -**Estimated Effort**: 2-3 days for Phase 1 (client preview) -**Complexity**: Medium -**Impact**: ⭐⭐⭐⭐⭐ (Highest) - -**Next Steps**: -1. Create feature branch `feature/live-preview` -2. Implement client-side preview -3. Add UI components -4. Test thoroughly -5. Merge to main -6. Deploy and monitor \ No newline at end of file