Features
Features are cut into a part’s blank. They do not change the blank’s size: a dado does not shorten a board and a tenon does not lengthen one. The blank is what you buy; the features are what you do to it.
parts: - id: head_post blank: { length: 900, width: 75, thickness: 75 } features: - kind: groove id: panel_slot on: right along: length width: 18 depth: 10 center: true stopped: 40 - kind: chamfer edges: [end_*] size: 3Every feature takes an optional id. Give it one if a joint needs to mate to it — that is
what turns the feature into an anchor,
and it is how a panel and the groove it sits in stay in step.
Most features also take an on: face. Faces, edges and the (u, v) frames they are measured in
are all on the Anchors page.
Positioning along an axis
Section titled “Positioning along an axis”Dados, grooves, mortises and notches sit somewhere along an axis, and there are four ways to say where. Give exactly one.
| Form | Means |
|---|---|
from: 120 |
120 mm from the start end to the feature’s near edge |
to: 300 |
300 mm from the start end to the feature’s far edge |
at: 210 |
210 mm from the start end to the feature’s centre |
center: true |
Centred on the axis |
Giving two, or none, is a RES- finding rather than a guess.
The resolver will not pick for you, because picking wrong puts a trench in the wrong place and
nothing downstream would notice.
from and to may be expressions, so a feature can follow a parameter:
- kind: dado on: right from: deck_height - shelf_stock.thickness width: 18 depth: 9The trenches
Section titled “The trenches”A square-bottomed trench across the grain, running the full width of the face unless stopped.
- kind: dado id: shelf_seat on: right along: width # optional — defaults to the short axis of `on` at: 400 width: 18 # the width of the trench, i.e. the thickness of what sits in it depth: 9 stopped: 12 # optional: stop 12 mm short of the far edgewidth is the trench’s width, not the part’s. Size it to the thickness of the part that
seats in it — or better, reference that part directly:
width: shelf.blank.thicknessgroove
Section titled “groove”The same cut, with the grain. It is a separate kind because the validation differs: a groove along the grain and a dado across it fail in different ways, and a groove is what captures a panel that will move seasonally.
Same keys as dado. stopped: leaves a blind end, which is what keeps a groove from showing
on the front edge of a post.
rabbet
Section titled “rabbet”An L-shaped cut along one edge of a face.
- kind: rabbet id: back_seat on: right # one of the six faces edge: end # which edge of that face it runs along width: 12 depth: 9 from: 0 # optional — run only part of the edge to: 400Note edge: here names an edge of the face, not one of the twelve blank edges.
mortise
Section titled “mortise”A blind or through rectangular slot.
- kind: mortise id: tenon_seat on: right along: length # the slot's long axis at: 300 length: 60 # along `along` width: 12 # across it depth: 30 # omit and set `through: true` for a through mortise ends: round # `round` (routed) or `square` (chiselled)ends matters to whoever cuts it: a router leaves round ends and a chisel leaves square ones,
and a tenon has to match whichever you chose.
A rectangle removed from a corner or an edge — the classic leg-and-apron cut-out.
- kind: notch on: top edge: start from: 0 length: 40 depth: 20Holes and pockets
Section titled “Holes and pockets”- kind: hole on: top diameter: 8 depth: 12 # or: through: true at: { u: 100, v: center } counterbore: { diameter: 14, depth: 7 } countersink: { diameter: 8.4, angle: 90 }at is a position in the face’s own (u, v) frame, measured from its minimum corner. Either
value may be center.
For more than one hole, use pattern: instead of at: — see below.
Most holes should not be authored. Every clearance hole, pilot hole, counterbore and countersink that belongs to a fastener comes from the fixture’s machining recipe when you declare a joint. Hand-placing a screw hole means the validator cannot check its edge distance or thread engagement, because as far as it knows there is no screw there. Author a hole for a cable exit, a bolt you are supplying yourself, or a shelf-pin array — not for a screw.
pocket
Section titled “pocket”A flat-bottomed rectangular recess that reaches no edge.
- kind: pocket on: bottom length: 120 width: 40 depth: 6 at: { u: center, v: center }Patterns
Section titled “Patterns”A repeated position. This is the shape behind every run of screw holes and every shelf-pin line.
pattern: along: length # required: which axis the run follows count: 10 spacing: auto # centre-to-centre, or `auto` to divide the span evenly margin: 80 # keep this clear at each end| Key | |
|---|---|
along |
Required. length, width or thickness. |
count |
How many. An expression, so it can be computed. |
spacing |
Centre-to-centre, or auto to divide the available span evenly. |
margin |
Clear space to leave at each end of the span. |
from / to |
Bound the run explicitly instead of using the whole axis. |
center |
Centre the run on the axis. |
offset |
Position on the face’s other axis. Defaults to centred. |
at |
Shorthand instead of count and spacing: any of start, end, centre, ends. |
# Ten screws down a cleat, evenly spread, 80 mm clear at each end.pattern: { along: length, count: 10, spacing: auto, margin: 80 }
# Two bolts, 100 mm apart, positioned at a computed height.pattern: along: length count: 2 spacing: bolt_pitch from: rail_centre_height - bolt_pitch / 2 to: rail_centre_height + bolt_pitch / 2
# Shelf pins on the 32 mm system.pattern: { along: length, count: 12, spacing: 32, from: 200 }The same pattern shape is used by joints[].fasteners.pattern, which is where you will
write it most of the time.
Edge treatments
Section titled “Edge treatments”chamfer and roundover
Section titled “chamfer and roundover”Both take edge selectors, and wildcards work:
- kind: chamfer edges: [top_end, bottom_end, left_end, right_end] size: 3
- kind: chamfer edges: [end_*] # the same four, shorter size: 3
- kind: roundover edges: [top_left, top_right] radius: 3Edge names and the wildcard rules are on the Anchors page. A chamfer or roundover has no frame, so it cannot be mated to.
A 2–3 mm break on every edge a hand will touch is worth authoring. It is also the cheapest thing in the file to change later.
A linear taper of one dimension along another axis — table and chair legs.
- kind: taper along: length # the axis the taper runs down reduce: width # the dimension that shrinks to: 30 # its size at the far end of `along` from: 150 # where the taper begins, from the `start` end sides: both # `both` (default), `near` or `far`sides: far tapers only the outward face, which is the usual choice for a leg that must stay
square where it meets an apron.
The ten kinds, at a glance
Section titled “The ten kinds, at a glance”| Kind | Positioned by | Mateable |
|---|---|---|
dado |
on + along-axis form |
yes |
groove |
on + along-axis form |
yes |
rabbet |
on + edge + from/to |
yes |
mortise |
on + along-axis form |
yes |
hole |
on + at or pattern |
yes |
pocket |
on + at |
yes |
notch |
on + edge + along-axis form |
no |
chamfer |
edges |
no |
roundover |
edges |
no |
taper |
along + reduce |
no |