Skip to content

How the catalogue works

This page as Markdown/docs/catalogue/how-the-catalogue-works.mdView .md

The catalogue is the shared data a design references. You do not author it and nothing is copied into your file — you name entries from it, and the compiler resolves them.

catalogs:
materials: std/lumber@1
fixtures: std/fixtures@1
standards: std/standards@1

All three default to the bundled std/…@1, so this section is normally omitted.

Family Ids look like What an entry is
Materials lumber.hardwood.s4s, sheet.plywood.birch A stock family and the sizes it is actually milled in
Fixtures fixtures.wood_screw.4x50 A solid, plus a machining recipe, plus design rules
Standards standards.bed.slat_gap_max A published number, with its citation

Species sit alongside materials: walnut, pine, white_oak and the rest carry the physical properties that solid-lumber families inherit.

materials:
- id: rail_stock
from: lumber.hardwood.s4s # ← a material family
species: walnut # ← a species
thickness: 38
width: 190
parameters:
- id: mattress
type: catalog_ref
catalog: standards.mattress # ← a standard, as a parameter
value: us-queen
- id: max_slat_gap
type: length
derived: standards.bed.slat_gap_max # ← a standard, in an expression
joints:
- id: cleat_to_rail_left
fixture: fixtures.wood_screw.4x50 # ← a fixture

An id that does not exist is RES-005 or RES-009, and the finding lists what does — near misses first. Invented ids are the single most common way an LLM-authored design fails, so the failure is fast, specific and repairable rather than mysterious.

lumber.hardwood.s4s carries nine species, seven thicknesses and eleven widths. A design narrows it to one real board:

- id: post_stock
from: lumber.hardwood.s4s
species: walnut
thickness: 75
width: 75

A combination that is not milled is rejected, and the finding names the nearest two that are. The sizes are actual, never nominal — see Solid lumber.

This is the part that has no equivalent in any open woodworking library, and it is the reason hardware in a kaicad design is structural rather than decorative.

A fixture entry is:

  1. A solid — a mesh or a couple of primitives, for the 3D view. Threads are never modelled; a smooth shank with a head is all a preview needs and a fraction of the triangles.
  2. A machining recipe for its neighbours — what to cut in the part the fastener passes through, and what to cut in the part it goes into. Every hole in a compiled design comes from one of these.
  3. The design rules it imposes — minimum edge distance, end distance, engagement, spacing, and whether it may go into end grain.
  4. The dimensions it determines — a counterbore diameter, a cross-dowel depth.
machining:
through_from: opposite
through_part:
- { kind: hole, diameter: 9, through: true }
- { kind: counterbore, diameter: 18, depth: 8 }
receiving_part:
- { kind: hole, diameter: 9, depth: 100, axis: from_mating_face }
- { kind: cross_hole, diameter: 12.5, at_depth: 80, depth: through_width }

The joint supplies the position; the fixture supplies the operations. You never write a pilot hole.

through_from is the field that catches people

Section titled “through_from is the field that catches people”
Value Means
mating The fastener enters on the face that touches the other part — a screw through a cleat into a rail.
opposite It enters on the far face — a bed bolt through a post from the outside, counterbore and head away from the rail.

Getting this wrong puts an 18 mm counterbore in the wrong surface and runs the clearance hole down the length of the board instead of across it. That design compiles and exports cleanly and cannot be built, which is why the fixture declares the direction rather than the joint guessing it. Your side of it is the joint’s through: part.

Some rules are written against the fixture’s nominal diameter:

rules:
min_edge_distance: "3 * d"
min_end_distance: "6 * d"
min_spacing: "8 * d"

d is nominalDiameter. For a 4 mm screw that is 12 mm from an edge, 24 mm from an end and 32 mm between screws — the usual shop rules, applied by something that does not forget them.

- id: standards.bed.slat_gap_max
kind: limit
source: >
Consensus of mattress-maker warranty conditions (Tempur, Sealy, IKEA and
others all specify 75–80 mm); 76 mm is the most commonly stated figure.
limit: { value: 76, direction: max, unit: mm }

source is required. An uncited number is an opinion, and the whole value of this validator is that it is not giving you opinions — when a report says a slat gap is too wide, it can say who says so.

Four kinds:

Kind Shape Example
dimension_set Named sizes standards.mattress.us-queen
limit One bound, max or min standards.bed.slat_gap_max
range min, max, typical standards.table.dining_height
rule A requirement in prose, with a condition standards.bed.centre_rail_required

A dimension_set used as a catalog_ref parameter behaves like the entry it names, so mattress.width reads naturally. A limit or a range field can be referenced directly in an expression.

Page
Species Fourteen timbers, with density, stiffness, movement and screw holding
Solid lumber Three families, and every milled thickness and width
Sheet goods Plywood, MDF and veneered MDF, with sheet sizes
Wood screws Six sizes, with pilot, clearance and countersink
Bed bolts Four sizes, and the five holes each one cuts
Knock-down hardware Threaded inserts, cam locks, dowels, shelf pins
Cable management Grommets and tie mounts
Standards Mattress sizes, slat gaps, ergonomic ranges — each cited

Coming in v2: concealed hinges, side-mount and undermount slides, pulls and knobs, levelling feet, and figure-8s, Z-clips and buttons.

The catalogue is CC0-1.0 — public domain, and meant to be adopted elsewhere. It encodes published standard dimensions and cites vendor part numbers; it never redistributes vendor CAD files. See Licences.

If you build something else that needs to know that an M8 bed bolt wants a 12.5 mm cross bore at 80 mm, take the data. That is what it is for.