Block Printing
- Started
- August 2026
- Status
- in progress
- Stack
- Swift, SwiftUI, Clipper2, earcut
- Built with
- Parlay and Claude Code
Why
Carving a linoleum block takes an evening and a steady hand, and the first pull tells you what you got wrong. A 3D printer can produce the block instead, but getting from a drawing to a printable mesh means a chain of CAD tools that were never meant for printmakers.
I wanted one window: drop in the drawing, tune a few parameters that mean something at the press, look at the block in 3D, and export. The app is that window.
What it does
- Relief workspace From image to block Import a design, set the threshold so the right areas read as foreground, choose relief heights and a border buffer, draft the walls so thin lines survive an edition, size the block in millimetres, mirror it for stamp printing, and export the STL.
- Counterform A frame so repeat pulls register An optional second model, offset from the block by wall width and fit clearance, so every print lands in the same place.
- Model inspection Judge the mesh before printing it Orbit, zoom and pan the built block, see it seated in its frame, and keep the viewpoint while parameters change.
- Printability check Find the whites that will fill in A draft angle can crowd narrow channels shut. The app measures those channels on the built geometry, marks them on the block, and leaves the decision to print with the printmaker.
- Block tiling Blocks bigger than the printer Cut an oversized block into pieces along its own whitespace, so seams fall where no ink is carried. A clean cut first, the fewest pieces second.
How it is built
The app is the first real application built with Parlay. Each feature above started as a set of intents in Markdown, went through dialogs and specs, and came out as generated SwiftUI code with its own test suite. The relief workspace alone was forty-one files and a green suite in its first two days.
The geometry kernel is the one unit Parlay does not generate. It turns an image into a mesh in stages: tonal split, contour tracing, scaling to millimetres, relief construction, wall drafting, counterform construction and mesh emission, over vendored Clipper2 and earcut so that two exports of the same workspace produce identical bytes. It was built with Claude Code against its own spec and tests, and Parlay cites it as a declared unit rather than writing it.
What I learned
Generated code can be complete, correct and fully covered while being absent from the window. Three times a component was built, tested and never mounted: a viewport that drew nothing, a drop target that was silently lost, tiling controls that could not be switched on. Every one was found by a person looking at the running app, none by the suite. The fix went into the project's rules: every declared region gets a test that asserts it is reachable from the route.
The app also produced a log of places where Parlay's own validators disagreed with each other. That log became the backlog for Parlay's next release.
References
- Parlay, the toolkit the app was built with. parlay
- Clipper2, polygon clipping and offsetting. github.com/AngusJohnson/Clipper2
- earcut, polygon triangulation. github.com/mapbox/earcut