Video.mp4
Instant 3D-printable enclosures for your electronics projects — built for the Zoo.dev API Makeathon.
Every IoT project ends the same way: a beautiful circuit… zip-tied to a shelf, or entombed in a gutted Tupperware. Real enclosure design means hours in CAD measuring port positions with calipers. zapim turns "Raspberry Pi 4 + screw-down lid + side vents" into a print-ready case + lid in about a minute — port cutouts, standoffs, screw bosses and all.
Actual engine output for a Pi 4B + L298N build — 160.4 × 73.2 × 42 mm, 97.4 cm³, ≈121 g of PLA for both parts. The app's front page walks through the whole workflow with screenshots; npm run dev and open http://localhost:3000.
board preset ─┐
options ──────┤→ resolver (TS) → KCL source ─→ offline validation ─→ Zoo Design API engine ─→ STL/STEP/GLB/OBJ
│ (all geometry math) (kcl-wasm-lib: (via the zoo CLI) + 3D preview
custom cuts ──┘ parse + mock-exec) + volume→grams
The generated KCL is a first-class artifact — commented, parameterized, and openable in Zoo Design Studio to keep designing by hand where zapim leaves off.
| Zoo tech | Where zapim uses it |
|---|---|
| KCL | every enclosure is emitted as clean, parametric KCL (modern keyword-arg dialect) |
| Design API engine | geometry is built server-side via zoo kcl export (Design API under the hood) |
kcl-wasm-lib |
offline parse + mock-execution validates every model before spending engine time |
Text-to-CAD API (/ai/text-to-cad?kcl=true) |
the /ai lab generates companion parts (knobs, brackets, mounts) with KCL source |
Iteration API (/ml/text-to-cad/iteration) |
the ✨ AI-edit bar prompt-edits the current enclosure's KCL ("honeycomb vents on the lid") |
File API (/file/volume) |
material volume → filament grams per build |
npm install
npm run setup:zoo # downloads the zoo CLI binary for your platform into ./bin
cp .env.example .env.local # then paste your token from https://zoo.dev/account/api-tokens
npm run dev # → http://localhost:3000The designer and live KCL preview work with no setup at all; Generate / downloads / AI modes need the token + CLI. (You can also paste a token in the in-app Setup panel instead of using .env.local.) The env var must be spelled exactly ZOO_API_TOKEN — /api/health reports tokenConfigured: false if the app can't find it:
curl -s localhost:3000/api/health
# {"tokenConfigured":true,"cli":{"found":true,"version":"zoo 0.2.170"},"wasmOk":true}The app's front page is a full screenshot-led tour of all six steps — this is the short version.
1 · Lay it out. Pick a board and the box auto-sizes around it; drop in companion modules, drag them around the cavity floor, then click two terminal dots to wire them. A router paths every wire around standoffs and bosses, bundles them into corridors, and reports the jumper lengths to order.
2 · Build it. ⚡ Generate validates offline in milliseconds, then the Zoo engine builds watertight geometry in 15–60 s. Four view modes; Simulated x-rays the shell so you can inspect the harness inside the case before committing four hours of printer time.
3 · Keep the source. Every design is commented, parameterized KCL — hardware shopping list and wiring totals in the header, tunable parameters at the top, every cutout labeled. Download it and keep designing in Zoo Design Studio.
| Doc | What's in it |
|---|---|
| Setup guide | detailed install, token & CLI options, health checks, and a troubleshooting decoder ring for every error code |
| User guide | every control explained + seven start-to-finish recipes (Pi case, wired motor driver, custom modules, fit-test-first workflow, AI edits…) |
| Architecture | the config → resolver → KCL → validate → engine pipeline, the wire router's A*, the viewer's plate-split math, and the decisions we'd defend at a whiteboard |
| Zoo platform field notes | 17 actionable bug reports & API suggestions for the Zoo team — engine boolean limits, hung sessions, ML job realities — each with repro shape, shipped workaround, and proposed fix |
| Roadmap | shipped features with scoping notes, and the honest menu of what's next |
- 21 board presets — Raspberry Pi 5 / 4B / 3B+ / Zero 2 W / Pico, Arduino Uno R3 & R4 / Leonardo / Mega 2560 / Nano / Nano Every / MKR, ESP32 DevKitC & DevKit V1, NodeMCU ESP8266, Seeed XIAO, Teensy 4.0 / 4.1, STM32 Black Pill, Adafruit Feather, Wemos D1 Mini — with real dimensions, mounting holes and port positions (plus a no-board parametric box mode)
- Custom modules for everything non-standard (motor drivers, buck converters, the whole Elegoo sensor drawer): a sketch-style editor sets the bounding box and mounting holes — click to add, drag to place, snap-to-grid, quick patterns — with per-module mount style (standoffs / tray / none) and standoff height. Modules save to a personal library; presets included (L298N, LM2596, MB102, relay, generic sensor)
- Floor-plan tab: drag the board and modules around the cavity, rotate in 90° steps, and watch the auto-sized box re-fit live; overlap and out-of-bounds turn red, and the box height follows the tallest item
- Boards and modules without mounting holes get tray-mount retainer posts automatically
- Port cutouts auto-placed from board data, each with its own clearance margin; board rotation remaps everything
- Screw-down lid (corner bosses, pilot holes, lip notches, hardware callouts) or slip-fit lid; vents per wall or lid (auto-dodging ports); custom rect/circle cutouts; wall-mount tabs
- Cutout part presets — PG7/PG9 cable glands, KCD1 rocker, 16mm pushbutton, MTS-102 toggle, USB-C plug pass-through, SMA bulkhead, 5.5×2.1 barrel jack, 0.96" OLED window — drop in centered with the manufacturer's recommended opening, no datasheet digging
- Shareable design links — the whole config lives deflate-compressed in a versioned URL hash: refresh restores your work, and 🔗 Share copies a link that reopens the exact design anywhere (
npm run test:shareproves the codec headlessly) - AI quick-edit chips — five curated one-click prompts (honeycomb lid, rounded edges, cable channel, zip-tie slots, foot recesses) through the Zoo iteration API, with the validate-before-render guard still in the loop
- 🔌 Wiring routing + animation — boards and modules carry real connection terminals (full 40-pin GPIO maps for every 40-pin Pi — 5, 4B, 3B+, Zero 2 W — plus the Pico; module presets named after their silkscreen, plus a terminals tool in the module sketch editor). Click two terminal dots on the floor plan to draw a logical net ("GPIO4 → sensor DATA"); a Manhattan-ish router paths every wire across the cavity floor — dodging standoffs and screw bosses, hopping over crossings, bundling into shared corridors — and the 3D view renders the harness as colored tubes (5V red, GND black) with an animated current pulse. Where routes bundle, zapim prints zip-tie saddles into the case KCL — the wiring designs part of the enclosure — and reports per-wire lengths with standard jumper sizes. Harness height is wired into auto-size: the cavity grows for headroom (or warns in manual mode).
npm run test:wiringproves the router invariants headlessly - 🎫 Fit-test coupon — one click crops a slice of one wall (real openings, real wall thickness, one real standoff at its true distance, the real lid lip) and builds that instead. Check the USB-C lines up on a short print instead of finding out four hours in. Opening sizes, heights above the floor and along-wall spacing are bit-identical to the full case —
npm run test:couponasserts exactly that, then parses all ten sample coupons - Both parts lie flat on one plate — no supports, FDM-friendly
- Print plate / Simulated / Assembled / Exploded views: the viewer splits the exported plate into case + lid client-side, animates the lid flipping onto the case, shows translucent ghost boards/modules at their real heights, and floats the lid screws in exploded view — and Simulated x-rays the shell and fades the lid away so the pulsing wire harness is the star (
npm run test:assemblyproves the transform math headlessly) - Live, syntax-highlighted KCL with hand-edit mode; downloads: STL · STEP · OBJ · GLB · KCL
npm run test:kcl generates 50 enclosure variants (every board × lid style + kitchen-sink, module and wiring-saddle cases) and runs each through the real KCL interpreter (@kittycad/kcl-wasm-lib in mock-execution mode) — syntax errors, deprecations and semantic errors fail CI without ever touching the network. The same validation guards the /api/generate route, so bad KCL is rejected in milliseconds instead of engine-minutes.
The zoo CLI is pinned to v0.2.170 (scripts/setup-zoo-cli.mjs) so the executor speaks exactly the same KCL as the bundled validator. Override with ZOO_CLI_VERSION=latest npm run setup:zoo at your own risk.
Geometry that mock-executes fine can still be rejected by the real engine. The short version below; the full write-up — 17 structured bug reports and API suggestions with repro shapes and proposed fixes — is in docs/zoo-api-notes.md. zapim's emitter works around rules discovered the hard way:
- Union two bodies at a time.
union([a, b, c, …])with many solids fails with "Batch edit result is not valid" — so same-height posts are merged into one multi-profile extrude and solids are folded in pairwise. - Never leave boolean faces exactly coplanar with body faces. Boss tops flush with the case rim, or subtract tools whose caps sit exactly on a surface, fail with "cannot handle this 3D subtraction yet" — everything is embedded or sunk by 0.15–0.5 mm instead (which is also why mount tabs ship as a separate 1 mm-overlapping body that slicers merge).
- Chunk big subtracts. Dozens of cutout tools in one
subtractcall fail the same way — the emitter cuts in batches of 8. - Tools must not overlap each other. Vent slots automatically skip any span already claimed by a port or custom cutout.
- Engine sessions sometimes hang. ~1 in 4 exports during our matrix run simply never returned; the server retries once with a fresh session automatically.
All 20 variants of the 2026-07-24 matrix build successfully on the live engine (the heaviest case — rotated Pi 4B, 30 cutouts, vents, tabs — takes ~55 s). Since then the wired case with a printed zip-tie saddle — the design in the front-page tour — earned its own engine receipt on 2026-08-04. Boards added after the matrix run are offline-validated only: same emitter, same invariants, no engine receipt yet.
lib/enclosure/boards.ts board database (dims, holes, ports)
lib/enclosure/config.ts config types + resolver — all geometry math, in plain testable TS
lib/enclosure/cutoutPresets.ts named panel-opening presets for common parts
lib/enclosure/kclgen.ts KCL emitter (resolved primitives → commented KCL)
lib/enclosure/coupon.ts fit-test coupon — crops a resolved enclosure to one wall
lib/enclosure/wiring.ts terminals + nets → floor-routed wires, lengths & zip-tie saddles
lib/enclosure/validate.ts offline parse + mock-exec via kcl-wasm-lib
lib/client/share.ts design-link codec (config ⇄ versioned, compressed URL hash)
lib/zoo.ts zoo CLI runner + REST (text-to-cad, iteration, volume)
app/api/* generate | text-to-cad | iterate | health
app/design the designer (config panels, 3D preview, KCL tab, AI edit)
app/ai Text-to-CAD lab
scripts/ setup-zoo-cli.mjs · validate-kcl.ts · test-assembly.ts
test-share.ts · test-coupon.ts · test-wiring.ts
docs/ setup · user guide · architecture · Zoo API field notes
- Board port positions come from published mechanical drawings — verify against your actual board before printing (margins default to 1.5 mm to forgive small errors).
- Filament estimate is solid-volume; real prints use less (infill) plus a bit more (walls/brims).
- Screw-lid corner bosses need ~6 mm side clearance — auto-size accounts for this.
- The
/aiText-to-CAD lab currently shows no 3D preview. Since 2026-08-04,POST /ai/text-to-cad/{format}?kcl=truereturnscompletedwith good KCL but an emptyoutputsmap — no mesh to render. The KCL is still returned and downloadable; the enclosure pipeline (Design API engine) and the ✨ AI edit bar are unaffected. Repro and suggested fix: ZAP-17.
zapim is released under the MIT License — see LICENSE. The enclosures it generates are yours; the emitted KCL carries no strings either, so take it into Zoo Design Studio and keep going.
The zoo CLI that npm run setup:zoo downloads is Zoo's own binary (never vendored into this repo), and npm dependencies keep their respective licenses.
zapim — Zoo.dev API Makeathon 2026. Case closed. 📦



