New Project

Frame Joinery#

Mitred corners and stile-and-rail panel frames

Names: miter stile_and_rail mitred_moulding angle groove_width groove_depth stub_tenon_length profile

When to use#

  • miter: two boards that meet at a corner, both cut back to the plane bisecting it (a plinth, a picture frame, a box lid rim).
  • stile_and_rail: the corner of a panel frame (a door, a lid frame, a cabinet back) where a rail meets a stile and both carry a panel groove. The rail gets a stub tenon that fills the stile's groove.
  • mitred_moulding (#460): a mitred corner — miter's own two symmetric ends, no T, no cope — where both members also carry the same stuck profile the whole way to the corner, so the moulding runs on round it (a door's own moulded frame corner, not a panel-frame T-joint).

For a rail into a leg without a panel groove, use mortise_and_tenon (joinery-tenons). The marks, join and the layout rule are in joinery-contract.

Syntax#

joinery miter          name=<N> { angle <deg> }
joinery stile_and_rail name=<N> {
    groove_width <mm>  groove_depth <mm>  stub_tenon_length <mm>  [profile "square"]
}
  • miter: the marks sit on the two boards' ends, facing out along each board. Both boards run full length to the corner's outer edge, so the two end faces meet in that edge; each is cut back to the plane bisecting it. angle is each end's cut off square, as a mitre saw reads it: 45 for a square corner, 30 for a hexagon's. It is checked against the placement: the declaration and the corner disagree is an error. A mitre has no cavity, so clearance is unused.

  • stile_and_rail: both parts declare a groove target=panel (a part feature; see edge-and-face-cuts) with the same groove_width and groove_depth as the joint. The rail's male mark sits on its end, the stile's female mark on the face the rail meets. The stub tenon is groove_width thick, stub_tenon_length long, from the edge nearer the stile's end to the rail's own panel groove (cut back groove_depth there, so the panel runs on past it), into the stile's groove.

  • profile: only "square" (flat sticking), which is also the default. Any other value is reported unsupported. A stuck moulding with coped shoulders is not synthesised by this joint as built here; check INDEX.md for a newer file that adds it.

  • mitred_moulding: angle means the same thing miter's own does, and the marks sit on the two members' ends the same way. profile/profile_size/profile_face are stile_and_rail's own three (the six moulding sections, tenon-tips-wedges-and-coped-rails has the full syntax). Both members are stuck the whole length, then both are mitred — the mitre cuts through the sticking, not a plain box. profile "square" degenerates to exactly joinery miter's own geometry. Which side face carries the moulding (its "inside" edge, opposite profile_face's own show face) is not a parameter: it is derived from the corner itself (the width-axis face farther from the mitre's own outer edge) — place the components so it lands where intended, the same way placement already decides which face profile_face resolves to.

    joinery mitred_moulding name=<N> {
        angle <deg>
        profile "ogee"           // ovolo cove ogee thumbnail half_round cockbead; "square" is flat
        profile_size <mm>
        profile_face "'neg_y'"   // pos_x neg_x pos_y neg_y pos_z neg_z
    }
    

Example#

project name="Frames" units=mm schema_version=1 {
    params { glue_clearance 0.2 }
    materials { material Oak type=hardwood }
    component Board role=board {
        stock Oak 300.0 20.0 60.0
        mark End x=0.0 y=10.0 z=-30.0 normal=neg_x
    }
    component Stile role=stile {
        stock Oak 60.0 20.0 400.0
        groove target=panel face=pos_x width=6.0 depth=10.0 offset=7.0
        mark Seat x=60.0 y=10.0 z=-30.0 normal=pos_x
    }
    component Rail role=rail {
        stock Oak 300.0 20.0 60.0
        groove target=panel face=neg_z width=6.0 depth=10.0 offset=7.0
        mark End x=0.0 y=10.0 z=-30.0 normal=neg_x
    }
    joinery miter name=Corner {
        angle 45.0
    }
    joinery stile_and_rail name=FrameCorner {
        groove_width 6.0
        groove_depth 10.0
        stub_tenon_length 10.0
        profile "square"
    }
    assembly Frames {
        part Front instance=Board { by top_sw; pos x=0.0 y=1000.0 z=0.0 }
        part Side instance=Board { by top_nw; pos x=0.0 y=1000.0 z=0.0; rot z=90.0 }
        join joint=Corner male=Front@End female=Side@End

        part Stile_A instance=Stile { by top_sw; pos x=0.0 y=1500.0 z=0.0 }
        part Rail_A instance=Rail { by top_sw; pos x=60.0 y=1500.0 z=0.0 }
        join joint=FrameCorner male=Rail_A@End female=Stile_A@Seat
    }
}

Pitfalls and diagnostics#

  • angle must match the corner: two boards meeting at 90 degrees are each cut 45. A mismatch reads "angle is 30.0, but Front and Side meet at 90.0, which a mitre halves". angle is in the range 1 to 89.
  • A compound mitre (boards that lean as well as turn, a splayed box) is reported unsupported (corner, RFC-0022); so are ends that do not meet in a corner edge, or a plane that misses a board or cuts it through its length.
  • A mitre's boards must both run to the outer edge. Writing one short of the corner leaves the bisecting plane missing it.
  • stile_and_rail without the parts' own grooves has nothing for the stub tenon to fill: declare groove target=panel ... on both parts first, matching the joint's groove_width and groove_depth. A profile other than "square" is reported unsupported.
  • A muntin or mid-rail into the middle of a stile is a T, not a corner: use a plain mortise_and_tenon (panel_door_and_window.kdl's MuntinTenonJoint), and cross_lap where two muntins cross.
  • mitred_moulding's own checks: params/cope-profile (a stuck profile needs profile_size and profile_face; an unknown profile or face word is named; a sticking deeper than half the member's own width, on either end). corner — a stuck profile on a genuinely compound corner (a member leaning as well as turning) is refused: no side face of a leaning member lines up with any world direction for profile_face to resolve at all, so this combination never reaches the chord-by-chord mirror check profile "square" reuses from miter's own compound-mitre handling unchanged.

See also#

  • docs/KDL_AUTHORING.md §8 (stile_and_rail, miter, mitred_moulding); ADR-0013; RFC-0022 (oriented marks, compound mitres).
  • examples/blanket_chest.kdl (PlinthMiter, LidFrameJoint), examples/filing_cabinet_lateral.kdl (PlinthMiter), examples/welsh_dresser.kdl (DoorFrameJoint), examples/panel_door_and_window.kdl, docs/styles/models/mitred-moulding-corner.kdl (#460).
  • joinery-contract.md, joinery-tenons.md, joinery-laps-and-boxes.md, edge-and-face-cuts.md (grooves, mouldings), tenon-tips-wedges-and-coped-rails.md (the stuck-profile syntax mitred_moulding reuses).

Names#

Every name this page declares, how the example library uses it, and the shortest real use.

miter#

joinery kind; value in 6 of 116 examples (6 uses).

Shortest real use, from serpentine_chest_bracket_feet.kdl:

joinery miter name=FootMiter {
    angle 45.0
}

stile_and_rail#

joinery kind; value in 9 of 116 examples (9 uses).

Shortest real use, from ebonised_incised_cabinet.kdl:

joinery stile_and_rail name=PanelFrame {
    groove_width panel_th
    groove_depth groove_d
    stub_tenon_length stub_l
    profile "square"
}

mitred_moulding#

joinery kind; not used by any example yet.

angle#

property; node in 6 of 116 examples (6 uses); property in 10 of 116 examples (22 uses); value in 2 of 116 examples (3 uses).

Shortest real use, from blanket_chest.kdl:

angle 45.0

groove_width#

node in 9 of 116 examples (9 uses).

Shortest real use, from arts_crafts_cabinet_on_stand.kdl:

groove_width panel_th

groove_depth#

node in 16 of 116 examples (16 uses); value in 7 of 116 examples (23 uses).

Shortest real use, from acrylic_panel_frame.kdl:

groove_depth 8.0

stub_tenon_length#

node in 9 of 116 examples (9 uses).

Shortest real use, from arts_crafts_cabinet_on_stand.kdl:

stub_tenon_length 10.0

profile#

word-valued property; node in 11 of 116 examples (12 uses).

Shortest real use, from arts_crafts_cabinet_on_stand.kdl:

profile "square"

Settings

Region

A region picks sensible defaults; change any of these separately.

Units

In inches, type lengths the way you say them: 34 1/2, 3/4", 1'-2" or 12.7mm. A length that can't be read is flagged, never rounded to something else.

Paper
Date order
Clock