Parts
A part is a blank — a rectangular board — plus the features cut into it. Nothing about where it sits in the piece appears here; that is what joints are for.
parts: - id: side_rail label: Side rail instances: [left, right] material: rail_stock grain: length blank: length: deck_length width: rail_stock.width thickness: rail_stock.thickness features: - kind: roundover edges: [top_left, top_right] radius: 3| Key | ||
|---|---|---|
id |
required | Referenced by joints, expressions and groups. |
material |
required | A materials id. |
blank |
required | length, width, thickness — all expressions. |
label |
What the cut list and the drawing call it. | |
instances |
Named copies — see below. | |
grain |
length (default), width or thickness. |
|
features |
What is cut into it — see Features. | |
note |
Free text, reaches the cut list and the drawing. |
The blank is the board, not the finished part
Section titled “The blank is the board, not the finished part”Give the size before the joinery. A tenon does not lengthen the blank and a dado does not shorten it; the resolver subtracts the features itself. Blank dimensions are what the cut list asks the timber yard for, with the material’s rough allowance added on top.
Size them from parameters rather than typing measurements:
blank: length: deck_length # a derived parameter width: rail_stock.width # the full width of the stock thickness: rail_stock.thicknessblank: length: side_rail.blank.length - 150 # another part's blankThe second form is how parts stay in step. The cleat is always 150 mm shorter than the rail, whatever the rail becomes.
length is the long axis, and it decides everything else
Section titled “length is the long axis, and it decides everything else”The three names are not interchangeable labels — they are the part’s own coordinate axes, and every face, edge and feature is named against them:
+X = length start ←→ end+Y = width left ←→ right+Z = thickness bottom ←→ topA board 800 × 195 × 25 is length: 800, width: 195, thickness: 25. Writing it as
length: 25 is legal and will produce a part whose top face is 800 × 195 — which is not
what any of your joints expect.
The full coordinate model is Anchors.
Which blank axis the long grain runs along. Defaults to length.
grain: length # the usual casegrain: width # a panel whose grain runs across its lengthIt drives the wood-movement checks, the end-grain fastener checks and the nesting on the cut list. A panel captured in a groove on all four sides will move across its grain and split the frame if it was not allowed room, and the validator can only tell you which way it will move if you have said which way the grain runs.
- id: headboard_panel material: panel_stock grain: width blank: { length: 1600, width: 560, thickness: 18 }That panel is wider than it is tall in the piece, and its grain runs vertically — the width
axis. Say so.
instances
Section titled “instances”Named copies of one part, cut from one cut-list row.
- id: head_post instances: [left, right]You then have head_post@left and head_post@right, and anchors address them with the @:
mate: a: side_rail@left:face.start b: head_post@left:face.topleft and right are special. A part with exactly those two instances is mirrored
about the design’s YZ plane. Any other set of instance names is copied unmirrored, and each
copy is positioned by its own joints.
Mirrored instances are the sharpest edge in the model
Section titled “Mirrored instances are the sharpest edge in the model”Mirroring flips the part, and it takes the part’s faces and features with it. The consequences are worth reading twice:
- The inner face of the left post is its
rightface; the inner face of the right post is itsleftface. Any joint that talks about “the inside” has to name a different face for each side, which is why rail-to-post joints are usually written out twice rather than withfor_each. - A feature arrives upside down on the mirrored copy. A groove on the
rightface of the left post is on therightface of the right post too — rotated 180°. A panel mating into both will go in backwards on one side unless you correct it withalign.roll: 180.
Both of these are visible in the worked example: the headboard
panel seats into the left post’s groove normally and into the right post’s with roll: 180.
If a part has three or more copies that are genuinely identical and evenly spaced — slats,
shelves, pickets — do not use instances. Use an array.
- id: centre_leg note: Trim to fit on site — floors are rarely flat.Free text that travels to the cut list and the drawing. Use it for the thing a person needs to know that no number captures.