cleanup
This commit is contained in:
346
README.md
346
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
|
||||
<?xml version="1.0"?>
|
||||
<Container version="2">
|
||||
<Name>pnger</Name>
|
||||
<Repository>pnger:latest</Repository>
|
||||
<Network>bridge</Network>
|
||||
<Privileged>false</Privileged>
|
||||
<WebUI>http://[IP]:[PORT:8080]</WebUI>
|
||||
<Config Name="WebUI Port" Target="3000" Default="8080" Mode="tcp" Description="Port for web interface" Type="Port" Display="always" Required="true" Mask="false">8080</Config>
|
||||
<Config Name="Max File Size" Target="MAX_FILE_SIZE" Default="10485760" Mode="" Description="Maximum upload file size in bytes" Type="Variable" Display="advanced" Required="false" Mask="false">10485760</Config>
|
||||
<Config Name="Memory Limit" Target="" Default="512m" Mode="" Description="Container memory limit" Type="Variable" Display="advanced" Required="false" Mask="false">512m</Config>
|
||||
</Container>
|
||||
```
|
||||
---
|
||||
|
||||
## 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
|
||||
**License**: MIT
|
||||
**Repository**: [https://git.alwisp.com/jason/pnger](https://git.alwisp.com/jason/pnger)
|
||||
Reference in New Issue
Block a user