Work as a senior product engineer and finish the application in this specification. This is a real application, not a mockup. Create the complete source tree, configuration, migrations or schemas, working UI, persistence, error handling, and tests. Do not leave stub handlers, simulated production data, TODO features, inert buttons, or invented successful test results.
Start by inspecting the workspace and available tools. Choose compatible maintained dependency versions and pin them in a lockfile. Write a short implementation plan and an acceptance checklist, then implement and run the work without stopping after planning. Use stages to manage complexity, but carry every required stage to completion. If context runs low, save progress and remaining acceptance checks in a local handoff document and resume from it. Ask only about decisions that cannot safely be inferred.
Keep modules small and put domain logic outside presentation components. Validate inputs at trust boundaries, handle cancellation and failures, preserve user data, and provide clear recovery actions. Include keyboard access, labelled controls, visible focus, useful empty/loading/error states, sensible contrast, and reduced-motion support. No advertising, subscriptions, analytics, hidden cloud dependencies, or remote executable loading.
Before finishing, run the compiler/type checker, linting, unit/integration tests, and a production build. Add real workflow tests for the acceptance checklist and run them against the built application where possible. Fix failures and repeat affected checks. Report exact commands, actual results, any environment-blocked checks, setup instructions, and remaining limitations. Never call an unfinished or untested feature complete. Include a README explaining architecture, development, packaging, data locations, permissions, and recovery. Use clean generated sample data only in explicit tests and previews.
Build {{app_name}}, a local raster image editor inspired by Photoslop. Use Electron, React, strict TypeScript, Vite, Zustand for UI metadata, Dexie/IndexedDB for recovery, and Canvas 2D for pixel work. Use a focused dark desktop workspace with a left tool strip, central tabbed canvas, contextual top controls, and Layers/Properties/History panels. The accent can be {{accent_colour}}. Ship a usable core editor before the optional AI bridge.
Document model: real document-space pixels; separate pixel assets from React state; pixel, editable text, editable shape, adjustment and nested group layers; opacity, visibility, blend modes and transforms. Make selections alpha masks supporting rectangle, ellipse, lasso and magic-wand operations with add/subtract/intersect. Implement feather/expand/contract/invert, clipboard copy/cut/paste, selected-pixel transforms and selection-clipped fills. Masks support paint, erase, enable, invert, apply and delete. Implement Move, Crop, Brush, Eraser, Clone Stamp, Spot Healing, Paint Bucket, Gradient, Eyedropper, Text, Shape, Pen, Hand and Zoom. Keep editable pen paths with corner or symmetric Bezier anchors; Enter commits an open path and clicking the first anchor closes it. Do not pretend to implement advanced path-node editing if it is outside this release.
Engine: pointer-centred 5%–3200% zoom, trackpad pan, high-DPI viewport, view rotation, rulers, guides, snapping and pixel grid. Render previews separately from committed document pixels. One pointer gesture is one reversible history command. Implement bounded command history with undo/redo for pixels, masks, selections, layer order, adjustments, project edits and canvas resize. Use compositing caches and worker-backed Gaussian blur, unsharp mask and noise. Cancelled/stale previews must not corrupt committed pixels. Add non-destructive brightness/contrast, levels, curves and hue/saturation; editable drop shadow and stroke effects.
Files: import PNG/JPEG/WebP, one GIF frame, safely rasterized SVG and layered projects. Export full-resolution composited PNG/JPEG/WebP independently of viewport zoom. Define a versioned .photoslop ZIP containing a validated JSON manifest, PNG pixel/mask assets and a preview. Bound archive size/count/dimensions, reject unsafe entries and preserve unknown-version errors. Autosave/recover recent projects through IndexedDB. Prompt before abandoning dirty work, handle quota/storage failures, and keep original files intact until a replacement is successfully written.
Security: sandbox Electron, enable context isolation, disable renderer Node, validate typed IPC operations and file dialogs, and restrict navigation/CSP. Opening an image must not execute SVG scripts or remote resources. Pixel/project files remain local.
Optional AI Fill/Expand: discover an authenticated local MCP capability rather than bundling credentials or calling a provider directly. If unavailable, clearly disable only AI editing; the editor still works. Submit the actual selection mask, offer up to three previews and require acceptance. Clip accepted fill locally; expansion preserves original pixels and commits resize plus extension as one undoable action. Never claim an AI provider succeeded without its response.
Acceptance: create a document, draw and undo/redo; build/reorder a nested layer group; edit text and a pen path; crop and recover; mask and transform a selection; preview/cancel/apply a filter; save/reopen the layered ZIP; export and compare document-size pixels; crash/restart and recover autosave. Test corrupt projects, exhausted storage, huge images, cancelled workers and a missing MCP provider. Include unit tests for blend/selection/transform/history math and Electron workflow tests. Explain sRGB/browser canvas limits; PSD, RAW and CMYK are outside this release. Finish every feature specified above before presenting the app.
Paste this into your preferred AI assistant. Review its output before running it.