Gallery Designer is a browser-based tool for planning a gallery wall to scale. You can model a continuous wall, size and place artwork, try automatic layouts, and export measurements for installation without creating an account or sending your design to a server.
- Build a continuous wall from one or more connected sections, including layouts that unfold around corners.
- Add art pieces with exact dimensions and optional hook positions.
- Place pieces manually or let the auto-placement solver arrange them.
- Work with wall furniture and features when planning a full wall.
- Export PNG or PDF installation plans with measurements. Export the current design as JSON, or back up all saved designs in one file.
- Keep work local with autosave in browser storage. Save multiple designs and switch between them.
- Local-first state: multiple designs autosave in browser
localStorage, and the design switcher lets you move between them. - Continuous wall canvas: connected sections behave like one unfolded wall surface.
- Manual layout tools: drag artwork, zoom and pan the wall, and refine placement visually.
- Measurement support: hook metadata and exportable hanging instructions are built in.
- Auto-placement: supports blank walls, hallway viewing paths, and full-wall layouts with furniture/features.
- Visual customization: light, dark, and themed application appearance options.
- Enter your wall sections and dimensions.
- Add each art piece with its label, width, and height.
- Add hook positions if you want installation measurements for the hanging hardware, not just the frame.
- Drag pieces onto the wall for a manual layout, or run auto-placement.
- Review the measurement table and adjust spacing, margins, or features as needed.
- Export the current design as JSON, or export an all-design backup. Export PNG/PDF installation plans with measurements.
Press ? anywhere in the app to open the full shortcuts legend. The most useful ones:
| Shortcut | Effect |
|---|---|
Enter / Space |
Select a focused wall section, piece, or feature |
Escape |
Clear the current selection |
| Arrow keys | Nudge the selection ¼ in |
Shift + arrow keys |
Nudge the selection 1 in |
Delete / Backspace |
Return the selected piece(s) or feature to the staging tray |
Cmd/Ctrl + Z |
Undo the last change |
Shift/Cmd/Ctrl + click or drag |
Multi-select pieces additively |
Space + drag |
Pan the wall canvas |
Cmd/Ctrl + wheel |
Zoom the wall canvas |
Gallery Designer treats the wall as a continuous connected surface, not as disconnected canvases. A design can use one section or multiple linked sections, which lets you model straight walls as well as layouts that wrap around corners.
There are two wall planning modes:
Available sections: auto-placement uses the connected wall geometry as open hanging area.Full wall with features: auto-placement also respects furniture and wall features such as sofas, beds, desks, fireplaces, doors, windows, TVs, bookcases, and custom blocked areas.
Connected wall sections can share artwork across section boundaries as long as the placed rectangle stays fully inside the combined wall shape.
The canonical auto-placement behavior comes from the current implementation and tests, not from the deleted research notes.
- If auto-placement is set to
autoand all remaining pieces are the same size, it prefersgridfirst. - In
auto, the solver then considersrow,stack, andsalon. - For mixed-size sets,
autoalso considerspacked. - Same-size sets tend toward
grid. - Mixed-size sets tend toward
salonorpacked. - If you explicitly request
row,stack,grid, orsalon, that request is treated as a hard preference and can fail if the layout cannot fit.
- Default gap is
2 inforgrid,row, andstack. - Default gap is
3 inforsalon. - If the art buffer setting has a positive value, that overrides the default gap.
- Default outer margin is
max(5 in, gap * 2). - If the wall-edge buffer setting has a positive value, that overrides the default outer margin.
- Layouts must stay inside the connected wall shape.
- Pieces must not overlap or touch.
- Existing valid placements are preserved exactly; the solver places only the remaining pieces when possible.
- If an existing placement is invalid, auto-placement stops and reports the problem instead of moving pieces silently.
- A piece that cannot fit inside the wall margin fails with an explicit error.
- In
full wall with featuresmode, furniture and wall features block placement. - Each feature applies a clearance zone.
- Clearance uses the feature default unless you provide a custom override.
- Features can influence preferred layout families and anchoring behavior.
Current feature defaults:
sofa,bed,console,fireplace: center-anchored layouts, usually favoringroworgriddesk: prefers usable-span anchoring and tends towardroworsalonbookcase,tv,window,door,custom: block placement but do not create a preferred anchor
- Blank wall planning uses the selected viewing posture, either seated or standing.
- Hallway planning uses a hallway viewing path heuristic.
- Full-wall planning reports the result in terms of the full wall plus furniture/features context.
Gallery Designer can export:
- JSON for exporting the current design or backing up and restoring all saved designs
- PNG and PDF for visual installation plans with measurement instructions
Measurement instructions follow the actual app logic:
- The upper-leftmost placed piece is listed first.
- Each later piece references the nearest valid wall edge or neighboring piece on the same section.
- Top references prefer the closest surface above the piece.
- Side references prefer the closest left or right wall edge or neighboring piece.
- Hook measurements are included when hook data exists.
All support requests, bug reports, and feature requests should be submitted through GitHub Issues.
Security vulnerabilities should not be reported in public issues. Use GitHub Security Advisories instead. See SECURITY.md.
Gallery Designer is a local-first Vite/React app. There is no backend, account setup, database, or external service required for local development. Multiple designs autosave to the browser's localStorage and can be switched from the design switcher. PNG/PDF installation-plan export runs entirely in the browser; JSON exports an editable backup.
- Node.js 24. The repo includes
.nvmrc, so usenvm usewhen working locally. - npm, installed with Node.
- Playwright browsers only if you plan to run the end-to-end tests.
nvm use
npm installnpm install updates node_modules for local development and may refresh compatible dependency versions in package-lock.json. CI should use npm ci so automated runs install the exact tested lockfile.
npm run devOpen the local URL printed by Vite, usually http://127.0.0.1:5173. The app stores draft designs in the browser you use for testing. If another process already owns the default port, Vite will offer the next available port.
To run on a specific port, pass it through to Vite:
npm run dev -- --port 5175Use the smallest relevant check while developing, then run the broader set before review:
npm test
npm run lint
npm run format
npm run buildnpm testruns Vitest and Testing Library tests in jsdom.npm run lintchecks TypeScript, React Hooks, and refresh rules.npm run formatchecks Prettier formatting.npm run buildruns the TypeScript project build and production Vite bundle.
For browser workflow changes, install Playwright browsers once and run the e2e suite:
npx playwright install chromium webkit
npm run test:e2eThe Playwright config starts the app on http://127.0.0.1:5173 automatically.
src/app/App.tsxowns the editor UI and reducer state.src/types.tscontains shared domain types.src/editor/contains domain-owned wall, placement, staging, design, export, measurement, interaction, state, and onboarding modules.src/shared/contains reusable UI primitives and formatting helpers.src/app/contains application bootstrap, chrome, theme configuration, and global styles.tests/e2e/gallery.spec.tscovers browser workflows such as dragging, export downloads, and responsive behavior.public/contains static assets, fonts, favicon, and GitHub Pages metadata.
The app's placement behavior is defined in src/editor/placement/autoPlace.ts and src/editor/placement/placement.ts, with corresponding tests verifying those rules.