Derek Gee
bV

bambuVault

In use

Five drawers in this house are organised by a program, and a sixth is on the printer. bambuVault takes a drawer's measurements, works out how a 42 mm grid fits inside it, and generates what it takes to make the grid fit that drawer — the baseplate tiles, the bins, the lids, the lift-out trays, and the wedges that take up the slack. There is no interface, because the drawer is the interface.

StartedJune 2026
Commits68
Ground trutha successful print
Drawers6

Figures measured 2026-07-14.

What it does

a compiler whose output you can hold

It does the arithmetic you would get wrong. A drawer gets measured in inches, with a tape, by hand. Gridfinity is a 42 mm grid. The script converts one to the other and works out how many whole cells actually fit — always rounding down, because a grid that overhangs the drawer is a grid that does not go in. What is left over is a rim of stray millimetres around the edge, and that rim is the entire problem: an unanchored baseplate slides every time the drawer is opened. So the script sizes filler pieces to exactly the leftover and wedges the grid still.

It generates the parts — all of them. Seven kinds: the baseplate tiles that the grid clips into, the bins, drop-on lids, lift-out trays, the anti-slide wedges, plus the to-scale layout plan and the cross-sections the script draws of its own output. The tiles and the bins are a shared library rather than a per-drawer one — a bin that fits one drawer fits every drawer, which is the entire point of standardising on a grid, and it is why a sixth drawer needs no new tiles. What is cut to a specific drawer is the wedging: the fillers are sized to that drawer's leftover millimetres and would not fit any other.

Two storeys of drawer. The lift-out tray is the best piece of geometry in the repo: a deck that seats on the tall wells of the layer beneath it and turns one deep drawer into two levels of bins. That is drawer-6, which is designed, generated, and not yet printed. Five drawers are printed and in daily use; the sixth is the next thing on the printer.

The code is the artifact. The STLs are rubbish. There are 58 of them and they are all build output — delete the lot, run the script, get them back. The thing worth keeping is the 1,505 lines that know what shape the furniture is.

Walkthrough

no screenshots — there is no screen

There is no app here to photograph. So this is the plan the script draws of its own output, followed by the parts that came off the printer and the drawers they went into. These are real photographs of real drawers in a real house, which is the point: everything else on this site renders on a screen, and this is the one project you can open.

Six to-scale top-down plans, one per drawer, drawn by the script itself. Each shows a grey baseplate grid filling most of the drawer, ringed by coloured filler pieces — blue corner wedges, orange front and back fillers, green left and right fillers — with red dots marking the locating pegs. The drawers differ in size and in how much filler each one needs; the first is captioned 'no pegs (butt-fit)'.
The script's own layout plan, to scale. The grey is the grid; the colours are the leftover millimetres it has to fill.
Printed parts sitting loose in an empty white cabinet: a deep open bin, a flat plate with two round finger holes for lifting it out, and behind them the baseplate tiles, showing their grid of square cells and slotted edges.
The parts, before a drawer happens to them — a bin, a lift-out plate, and the baseplate tiles they clip into.
A household drawer seen from above, filled edge to edge with printed bins sitting on a grid. One bin holds loose batteries; beside it a printed magazine holds rows of AA and AAA cells standing on end, with a strip of 9V cells alongside. Smaller bins hold coin cells, keys and padlocks, screws, brass hooks, spare toothbrush heads and a box of matches.
The utility drawer. The grid and the bins are generated for this drawer; the battery magazine is somebody else's design, downloaded from MakerWorld and printed — which is what standardising on a grid buys you.
A second household drawer, also gridded: cotton swabs, cleaning-cloth refills, tissues, toothpaste, sunscreen, travel plug adapters, razors, and a bicycle inner tube with a blue hand pump, each in its own printed bin.
The bathroom drawer. Not one of these compartments is a thing you could have bought at the right size.

The crooked drawer

where the whole idea earns its keep

Drawer-2 is not square. Its right wall runs about an eighth of an inch shorter than its left — a real piece of furniture, built by people, in a house that has settled. You can measure it as carefully as you like. It stays crooked.

Here is what that costs, in full:

_DRAWER2 = Drawer("drawer-2", 22.5, 18.5, 3.75, length_in_right=18.375)  # right wall 1/8" short

That is the fix, entire. length_in_right is a second measurement taken down the right-hand side, and everything downstream reads it. The right-hand column does not come out narrower — it comes out shorter. The script gives that side its own pair of corner pieces, each trimmed front-to-back, so that between them they give back exactly the eighth of an inch the wall is missing; the long filler between them is unchanged, and the column simply ends sooner. The defect stops being something a person has to remember and becomes a number that other numbers are derived from. This is the argument for the whole project in one line — a physical flaw in a piece of furniture, captured as data, from which a differently-shaped part falls out automatically.

Drawer-3 is the deeper drawer in the same cabinet. It was never re-measured: the script declares its footprint to be drawer-2's — crooked wall included — and takes a fresh number only for the height. The two drawers accept the same fillers because, seen from above, they are the same hole.

How it's built

boring on purpose
LanguagePython
CADCadQuery · cqgridfinity
PrinterBambu Lab X2D
Output58 STL files
Sourceprivate repo

The print bed is 256 mm square, which is smaller than every drawer here. So a baseplate is never one part — the script tiles it, and holds each tile to 210 mm, five grid cells, rather than the six that would technically fit. The last few millimetres of a build plate are where prints go wrong, and there are dozens of tiles: every one of them has to come out right. Individual bins are allowed to break that cap where a single unbroken part is worth it, and four of them run to around 251 mm. Tiles never do.

Changes go through the same pipeline as the rest of the fleet — planned, built, then read by two independent AI reviewers before anything lands. That process is a project in its own right, and it has its own page. This repo differs from its siblings in exactly one way: there is no public copy of it, so the two readers are the only review it gets, and then it merges locally.

What I learned

the printer has opinions and they are correct

The feature that would not print. A Gridfinity bin can carry a label shelf, and mine did — a small tab at the front to take a strip of tape. It is a steep inward overhang, around 50° off vertical, and it prints near the top of a tall part, which is exactly where the part cooling is weakest. On the first print it drooped and frayed. I could have chased it: more cooling, a support structure, a different orientation, an evening of tuning. What I did instead was delete it. The house style now drops the label shelf and the scoop, and the flat top of the lid became the labelling surface — a shallow recess sized for 12 mm tape, printing as a short bridge on the first layer where nothing can sag. A feature that only survives when everything goes right is not a feature, it is a liability. Design for the print you actually get, not the one in the render.

The furniture is wrong, and that is data. My first instinct on the out-of-square drawer was to treat it as a nuisance to be handled at print time — shave a part, pack the gap with a folded card, remember the trick next time. That is knowledge stored in a head, and a head is the worst database available: it is unreadable by anyone else and it fails silently at 11pm, six months from now, when the drawer needs one more bin. Admitting the drawer's real shape into the model cost one argument on one line, and now the crookedness is something the parts are derived from rather than something I have to survive. The best place to put a hard-won fact is in the source, where it can do work.

Next in the fleet

the other three vaults