Architect — Floor Plans to Scale
Status: OngoingArchitect is one of my own School tools. For now the demo below is the only public part of it.
What it is
Architect is the floor-plan editor I use when I want to furnish a room before I move anything. I draw the walls by typing their lengths in centimetres, click inside them to get a room with its area, and drop doors and windows into the walls. Below is the real editor on made-up plans: what you change stays in your browser.
How it is built
The plan is a document with a schema, not a pile of shapes. The walls are a graph: corner points, and walls between them with a thickness. Where walls meet, their outlines are mitred, so an L, a T or an X joins without gaps, and a very sharp corner is cut square instead of reaching far out. A room is a ring of corner points, measured on the inside faces of its walls. A door or a window is a distance along a wall, so it moves with the wall.
Every change is a command run on a draft of the plan, which records the change and its inverse as patches. Undo applies the inverse, and the history keeps whole steps up to 2 MB instead of a full copy of the plan per step. The replay in the demo is a recorded list of these commands, played through the same store as everything else.
The view moves outside React: a pan or a zoom writes the transform straight to the drawing on the next animation frame, and React only hears about it when the gesture ends. The grid is drawn on a canvas and the plan in SVG, so lines and text stay sharp at any zoom.
Checked, not assumed
- 1 000 random changes in 100 seeded sequences, each undone and redone exactly, with the plan valid throughout; 2 000 random points that snap to themselves when snapped again, and never to what is being moved.
- Every check was also run against a deliberately broken copy of the code it guards: 18 of 18 broken copies were caught.
- A PDF to scale is tested to scale: 1 000 cm at 1:100 is 100 mm on the page, and a plan that does not fit the paper is said not to fit, never shrunk.
- The colours are design tokens checked for contrast in light and dark mode, and a test fails if a raw colour slips into the editor.
- Plans from the first version, made of boxes, are converted when they are opened, and the original is kept so it can be put back.
What it cost
The editor's own JavaScript grew from 58.5 KB to 90 KB (gzip) with the wall geometry, the command history and the new panels. For now that is above the 80 KB limit I set for it. The windows, the PDF writer and the plan checker are left out until they are used, which is how it came down from over 200 KB in the first build.
What I learned
Getting the data model right first made the rest simpler: the exports, undo, the demo and the tests all work on the same document. And a number is only useful with where it was measured: every figure on this page names its source in my notes.
What I did
- Set what it had to become: real walls instead of boxes, plans that keep working after the change, exports to scale, and a demo anyone can open.
- Set the quality bar: measured numbers, contrast-checked colours, every tool usable from the keyboard, and checks run against broken copies of the code.
- Chose the look: the site’s cream paper with bronze in light mode, ink with champagne in dark mode, shared with my whiteboard.
- Kept what already worked for me: zoom out stops at 50 %, the background themes, and the export window with its preview.
Tech Breakdown
TypeScript and React 19 · the plan in SVG, the grid on a Canvas2D layer · zustand with immer patches for state and undo · zod for every plan that comes in · Radix primitives, loaded when opened · jsPDF for the PDF to scale, and DXF written by hand · Next.js 16 on Vercel, plans in Vercel KV · the Node test runner and Playwright