# Deferred: enhancements and nice-to-haves Smaller, mostly independent improvements. None are blocking; ordered roughly by value. ## Undo / redo - Add a history stack around the reducer (past, present, future) with Cmd/Ctrl+Z and Shift+Cmd/Ctrl+Z. - The catch: continuous actions (setCrop, setZoom, setRotation from the slider) fire many times. Coalesce them - snapshot history only on discrete commits (template, aspect, rotateBy, flip, effect preset, format, quality) and treat a drag as a single entry (push on interaction start, replace until it settles). - Medium effort; the coalescing is the only subtle part. ## Persist preferences - Save format, quality, maxEdge, and last template to localStorage; restore on load. Do not persist the image. - Guard for SSR/StrictMode (read in an effect, not during render). - Small effort. ## Batch / favicon set export - The brief mentions a "favicon set". Export several sizes at once (16, 32, 48, 180, 192, 512) as a zip. - Add a tiny zip writer (for example fflate) in the worker; or trigger multiple downloads (some browsers throttle multiple downloads, so zip is nicer). - Small-to-medium effort. ## Richer adjustments (need real pixel math) - Exposure, temperature/tint (white balance), sharpen, vignette, levels/curves. - CSS/canvas filter cannot do these well. Two options: - Implement them with wasm-vips operations in the worker (vips has sharpen, linear, recomb, etc.), or - Write small WebGL/Canvas shaders for live preview plus a matching worker pass. - The live-preview-must-match-export rule makes this non-trivial; vips-only (export-time) is simpler but loses live preview for those controls. - Medium-to-large effort. ## Explicit output dimensions - Beyond the current "limit long edge" cap, allow typing an exact width/height for custom crops (with an aspect lock to avoid stretching). The worker already accepts an output size; this is mostly UI. - Small effort. ## User-defined / managed templates - Let users create, edit, reorder, and persist their own templates (localStorage or export/import JSON). Templates are already plain data, so the model fits. - Medium effort. ## Live size estimate - Show an estimated output file size before export. Requires a debounced encode of a downscaled proxy (full encode per keystroke is too expensive). - Medium effort; easy to get wrong on cost. ## Committed E2E test suite - The app was verified with Playwright, but no suite is committed because the browser binary path is environment-specific (launch used an explicit executablePath). To commit a suite: add @playwright/test as a dev dependency, add a config that resolves the browser normally (npx playwright install), and port the scenarios from VERIFICATION.md. Wire a "test:e2e" script. - Small-to-medium effort. ## Mobile polish - The responsive drawers work, but could add an explicit close button inside each drawer and swipe-to-dismiss. Small effort. ## Misc - i18n of UI strings. - A "compare" press-and-hold to temporarily disable adjustments/crop. - Keyboard nudge of the crop with arrow keys. - Drag-over highlight on the whole editor (not just the empty dropzone).