Woodshop Designer — Living Docs

Single source of truth for the current state of the project. Updated whenever code changes, decisions are made, or open questions resolve.

Sections

Where we are

M1 done M2 done M3 next M4

M2 is complete. All four sections (Materials, Constraints, Assemblies, Parts) are editable. Recalculate is pinned to the top bar with a live calc summary (orange when there are unapplied changes; constraint blurs auto-recalc). The height-driven primary-part logic visibly resizes the cabinet as you change caster height, top allowance, etc. Save / Load / New, CSV export, Print Cut List all live. Project name is click-to-rename. Side panels collapse. Color picker on materials updates the 3D view live. Ready for an end-to-end walkthrough via the Getting Started section above. Next: M3 formulas.

App: index.html · Plan: plan.html · Brief: brief/brief.md

Getting started

What is this?

A single-file HTML tool for designing shop projects in 3D. You define materials, parts, and constraints; it gives you a parametric 3D view and an accurate cut list. Built for cabinets, workbenches, rolling carts — the everyday shop stuff.

Open it

Double-click index.html in this folder. It opens in your default browser. No build step, no server, no internet needed once Three.js loads.

What you'll see on first load

Mobile Tool Cart 36" − 4" − 1" − 0" = 31" → Left Side [Recalculate] · · · Help · Save · Load · New
Left panel
Materials (editable cards)
Project Constraints (editable)
Assemblies (editable)
Parts (editable cards)
3D viewport · view buttons across the top
Cut list
Grouped by material
Sorted by area, biggest first
Sheet count + board feet
[CSV] [Print] buttons
Status bar — parts count · board feet · sheets · last recalc time
The default Mobile Tool Cart loads with five parts, three materials, and a working set of constraints. The calc summary and Recalculate button live in the top bar so they're always visible.

The view bar

Front / Top / Side are flat orthographic views. 3D is perspective with mouse-drag orbit. Reset snaps the 3D view back to the default angle.

Editing your first part

  1. In the left panel, find the Parts section. Click the on any card (e.g. "Left Side") to expand it.
  2. Change the W value from 0.75 to 1.5. Tab to the next field — Tab navigates through inputs natively.
  3. Look at the Recalculate button on the right. It just turned orange with a dot — that means you have unapplied changes.
  4. Click Recalculate. The 3D view updates with the thicker sides, the cut list refreshes, and the button goes back to white.
Left Side
W0.75
H31
D24
X0
Y4
Z0
An expanded part card. Always-visible row 1: name, height-driven star, material, ⋮ toggle. Row 2: W / H / D. Below the divider: position, grain, height-driven checkbox, notes, plus Duplicate and Delete.
Recalculate button states. White = clean (nothing to apply). Orange = you've edited something and the 3D view + cut list are stale until you click it.

Adding a new part

At the bottom of the parts list, click + Add Part. A new card appears with default dimensions (12 × 12 × 0.75), expanded for editing, with the name field selected. Type a name, Tab through W/H/D, pick a material from the dropdown.

Duplicating a part

Click on any card to expand it, then click Duplicate. A copy is added with "(copy)" appended to the name and offset 2" in X so it doesn't sit on top of the original.

Try the height-driven Recalculate (the centerpiece feature)

This is the trick that makes the tool actually useful. The cabinet's "primary" part (Left Side, marked with ★) auto-resizes to keep your overall target height correct as casters, top thickness, and toe kick change.

  1. Open the Project Constraints section in the left panel.
  2. Find Caster height. Change 4 to 5. Tab away.
  3. The Left Side instantly shrinks by 1" to keep the cabinet at 36" total. The 3D view, cut list, and top-bar calc summary all update.
  4. Now toggle Casters off entirely. Left Side grows by the former caster height. Cabinet still 36" total.
  5. Change Top allowance from 1 to 2. Left Side shrinks by 1".

This same logic works for any cabinet — set your target height, mark the part you want auto-resized as "Height-driven" in its expanded card, and pick it as the Primary part. Done.

Editing materials — name, color, type, sheet dimensions

Each material is a card with a color swatch, name, and type badge (sheet/lumber). Click the swatch to open a color picker — the 3D view updates live as you drag. Click to expand for thickness, type, sheet width, sheet length. Click + Add Material to define a new one.

Deleting a material that's used by parts shows a confirm with what'll happen — those parts get reassigned to the next available material so you don't end up with broken references.

Editing assemblies

Most projects have one assembly (the default "Base Cabinet"). For a multi-part project — say a workbench with separate cabinets — click + Add Assembly, give it a name, set its X/Y/Z position. Then in any part's expanded card, pick the new assembly from the Assembly dropdown. Parts inherit their assembly's position offset so you can move whole sub-assemblies in one go.

Saving and loading projects

Your work doesn't auto-save (deliberately — no localStorage). Use the top bar buttons:

Exporting the cut list

Top of the right panel:

Collapsing the side panels

Each side panel has a thin "rail" at the top with a toggle button. Click on the left panel (or on the right) to fold the panel into a 36px-wide strip. The 3D view grows to fill the recovered space. Click again to bring the panel back.

← collapsed left panel; click ▶ to expand
When collapsed, the side panel shows only the rail. The 3D viewport fills the space.

Tips

Visual reference

Quick-reference of the main UI elements. Mockups update as the app changes.

App layout

Project name Help · Save · Load · New
Left (320px)
Project panel — collapsible
3D viewport (flex)
Right (380px)
Cut list — collapsible
Status bar

View bar

Active view button highlighted in brown. Reset is styled in muted italic to read as an action, not a view.

Part card — collapsed

Right Side
W0.75
H31
D24

Part card — expanded (orange border)

Left Side
W0.75
H31
D24
X0
Y4
Z0

Recalculate button states

clean — nothing to apply

dirty — you have unapplied edits

Milestone plan

MilestoneScopeStatus
M1 Skeleton that renders. Layout, Three.js scene, view buttons, default cart visible, grid + axis indicator, status bar. No editing. done
M2 Editing (materials, parts, assemblies, constraints), cut list refinements, save/load JSON, CSV export, Print Cut List, Recalculate button (numeric only), top-bar calc summary, project name click-to-rename. done
M3 Formulas. Recursive-descent parser. part(...), mat(...), constraint(...), min/max. Topological sort, cycle detection, inline errors, fx icons, height-driven primary part logic. later
M4 Polish. Click-to-select in 3D, Cmd shortcuts, print stylesheet, confirmation dialogs, status-bar math summary, hover/disabled states, brief's full 10-item verify checklist. later

Change log

Newest first. Append entries here on every change.

2026-04-25 · M2 closing

Bug fixes + assemblies + CSV + Print + top-bar Recalculate (UX #4)

2026-04-25 · M2 partial

Editable materials — color picker, type, sheet dims, delete with reassign

2026-04-25 · M2 partial

Save / Load / New + project rename

2026-04-25 · M2 partial

Editable constraints panel — Recalculate height-driven logic now visible

2026-04-25 · docs

Help link in app + Getting Started + visual mockups

2026-04-25 · M2 partial

Editable parts cards + Recalculate dirty state (UX #2, #3 resolved)

2026-04-25 · M2 partial

Iso → 3D + Reset View (UX #7 resolved)

2026-04-25 · M2 partial

Collapsible side panels (UX #1 resolved)

2026-04-25 · M1 complete

Initial skeleton — render-only

Open UX questions

Questions waiting on user input. Each links to where it would land in the milestone plan.

1. Target screen size? — resolved
Resolved by adding collapsible side panels (2026-04-25). Click the ◀ / ▶ in each rail to fold the panel to a 36px strip; click again to bring it back. The 3D viewport reflows automatically.
2. Parts editing flow — forms, side panel, or inline table? — resolved
Resolved as inline editable cards (2026-04-25). Always-visible row: Name, Material, W, H, D. Expand a card for X, Y, Z, grain, height-driven, notes, plus Duplicate / Delete. Tab navigation works natively.
3. Duplicate-part button? — resolved
Yes. Each expanded card has a Duplicate button. Clones with "(copy)" suffix and a 2" X-offset.
4. Constraints + Recalculate placement? — resolved
Resolved (2026-04-25) by pinning the calc summary + Recalculate button to the top bar so they're always visible. The constraints panel itself stays in the left column for editing.
5. Formula reference picker?
Typing part("Left Side").height is verbose. A "+" button next to formula fields opening a picker (pick part → pick property → inserts the reference) speeds entry ~3×. Lands in M3.
6. Cut list vs 3D — split or tabs?
When designing, 3D matters most; when prepping for the shop, cut list does. A tab toggle on the right column ("3D | Cut List") would let the active view take all the space. Lands in M2 if chosen.
7. Iso vs Orbit — collapse into one? — resolved
Resolved by replacing Iso + Orbit with a single 3D view button plus a separate Reset action (2026-04-25). 3D preserves the angle across view switches; Reset snaps back to default.

Locked-in decisions

Architectural choices made. Don't relitigate without a strong reason.

Single resolve(value) chokepoint

Every dim and position is read through one function. M1–M2 it returns numbers; M3 swaps in the formula parser without touching any callsite. Why: avoids a rewrite when formulas land.

Data model frozen at brief shape

Materials, Parts, Assemblies, Constraints, top-level Project with version: 1. Any change here breaks save files. Why: save format must round-trip from M2 onward.

One renderer, one scene, swap the camera object

Ortho for Front/Top/Side, perspective for Iso/Orbit. Custom orbit controls — no OrbitControls import (single CDN script tag rule). Why: simplest mental model, no juggling render targets.

No eval(), no browser storage, single HTML file

Hard requirements from the brief. Not negotiable.

Section banners in JS

DATA · RESOLVE · RENDER · UI · IO · BOOT. New code goes in the matching section; cross-section calls go through the documented entry points only.

Known issues / TODO

SeverityItemLands in
done All sections (Materials, Constraints, Assemblies, Parts) editable. Save / Load / New, CSV export, Print Cut List, top-bar Recalculate summary all live. M2
limitation Toggling casters on/off doesn't move part positions in M2 (positions are hardcoded numbers). Fully fixed when formulas land in M3 — parts can reference constraint("casterHeight") in their position.y. M3
deferred No formula support; default cart's formula strings are pre-resolved to numbers. M3
deferred Click-to-select in 3D and parts list highlight not wired up. M4
deferred Print stylesheet, CSV export, keyboard shortcuts. M2 / M4
verify Side view looks from +X (right side). Confirm this is the wanted convention; some users expect the left side. M2
verify Top view "up" is set to −Z so the back of the cabinet is at screen-top. Confirm this matches the user's mental model. M2

Last updated: 2026-04-25 — M2 done · ready for end-to-end test via Getting Started