Tenon Tips & Coped Rails#
Mitred tenon tips, round-tenon wedges, and coped stile-and-rail joints
Names: tip wedge stile_and_rail
Three gaps in the tenon family, closed by ADR-0026. Source of truth for the language is
docs/KDL_AUTHORING.md §8 (the joinery section); this page is the agent's quick card.
When to use#
tip mitre=#true— two rails tenon into the same post from different faces (a desk's apron and side apron into one leg; a chair's seat rail and side rail). Their tenons would cross inside the leg; mitring the tips lets each be long. Without it thetenons-meetrule refuses the pair.wedgeon around_tenon— a round tenon driven through its mortised part and wedged in a kerf (a stool leg through its seat, a chair stretcher through a leg). The rectangularmortise_and_tenonhas hadwedgesince M15; this is the round one.profile "ogee"(or any moulding) onstile_and_rail— a cope-and-stick door or frame: the inside edges are stuck with a moulding, and each rail end is coped to it.profile "square"(the default) is still the flat frame.
Syntax#
Mitred tips — one line in the body of both joints that meet:
joinery mortise_and_tenon name=Apron_to_Leg {
tenon_thickness 10.0
tenon_length 48.0
clearance 0.2
tip mitre=#true
}
Round-tenon wedge — the tenon must be through (through #true, or length reaching the
far face); the kerf is sawn across the grain of the mortised part:
joinery round_tenon name=Leg_to_Seat {
diameter 22.0
length 40.0
through #true
wedge kerf=3.0 depth=18.0 flare=2.0 flare_depth=10.0
}
Stuck profile — profile is a moulding name, profile_size its projection in mm, and
profile_face the way the frame's show face looks in the assembly's axes, written as
a CEL string ("'neg_y'"):
profile "ogee" // ovolo cove ogee thumbnail half_round cockbead; "square" is flat
profile_size 5.0
profile_face "'neg_y'" // pos_x neg_x pos_y neg_y pos_z neg_z
Example#
A single door, stiles and rails 20 mm thick, the front (neg_y) stuck with a 5 mm ogee.
The right stile is the left turned half round and the bottom rail is turned over; the
sticking still lands on the front of all four members, because profile_face is a world
direction.
project name="stuck_door" units=mm schema_version=1 {
materials {
material Softwood type=softwood
}
component DoorStile {
stock Softwood 60.0 20.0 500.0
groove target=panel face=pos_x width=8.0 depth=10.0 offset=6.0
mark RailSeat_Top x=60.0 y=10.0 z=-30.0 normal=pos_x
mark RailSeat_Bot x=60.0 y=10.0 z=-470.0 normal=pos_x
}
component DoorRail {
stock Softwood 280.0 20.0 60.0
groove target=panel face=neg_z width=8.0 depth=10.0 offset=6.0
mark Stile_Left x=0.0 y=10.0 z=-30.0 normal=neg_x
mark Stile_Right x=280.0 y=10.0 z=-30.0 normal=pos_x
}
joinery stile_and_rail name=DoorFrameJoint {
groove_width 8.0
groove_depth 10.0
stub_tenon_length 12.0
profile "ogee"
profile_size 5.0
profile_face "'neg_y'"
}
assembly Root {
part DoorStile_L instance=DoorStile {
pos x=0.0 y=0.0 z=0.0
}
part DoorStile_R instance=DoorStile {
pos x=400.0 y=20.0 z=0.0
rot z=180.0
}
part DoorRail_Top instance=DoorRail {
pos x=60.0 y=0.0 z=0.0
}
part DoorRail_Bot instance=DoorRail {
pos x=60.0 y=20.0 z=-500.0
rot x=180.0
}
join joint=DoorFrameJoint male=DoorRail_Top@Stile_Left female=DoorStile_L@RailSeat_Top
join joint=DoorFrameJoint male=DoorRail_Top@Stile_Right female=DoorStile_R@RailSeat_Top
join joint=DoorFrameJoint male=DoorRail_Bot@Stile_Left female=DoorStile_L@RailSeat_Bot
join joint=DoorFrameJoint male=DoorRail_Bot@Stile_Right female=DoorStile_R@RailSeat_Bot
part DoorPanel role=panel {
stock Softwood 296.0 8.0 396.0
pos x=52.0 y=6.0 z=-52.0
}
}
}
Pitfalls and diagnostics#
tenons-meet— two tenons run into each other inside one part. Shorten them, or writetip mitre=#trueon both joints.tip-mitre— the mitre needs tenons that meet at an angle (parallel axes have no bisector), and the bisector plane may not cut a tenon's own rail: use shorter tenons. The mortises are not clipped to the mitre (they stay the full rectangular pockets); only the male tips are.wedge-kerf— the wedge needs a through round tenon (through #true);depthmust be at leastflare_depthand at most three quarters of the tenon's run through the mortised part; a kerf may be no closer than 1.5× its width to the tenon's surface or another kerf.wedge-grain— the wedges spread the tenon along the mortised part's grain (spreading across it splits the part): declaregrainon it, otherwise the longer of its two faces square to the tenon is taken; a tenon in end grain is refused.wedge-flare,wedge-frame— seedocs/KDL_AUTHORING.md.params— a stuckprofileneeds bothprofile_sizeandprofile_face; an unknown profile or face word is named.profile_size/profile_facewithprofile "square"is only a warning (they do nothing).cope-profile— the sticking would cut into the panel groove (profile_sizelarger than the wood between the show face and the groove: for a 20 mm member with an 8 mm groove, 6 mm), is deeper than half the rail's width,profile_facenames a narrow edge of the rail or a way no member's side face looks, or the shoulder is off square.profile_faceis a world direction, never part-local: a door's right stile and bottom rail are usually the same component turned. Check the face against the assembly.- The cope has no clearance:
clearancebelongs to the groove (D8, ADR-0012). The cope is the stile's sticking void exactly, to the chord of the 16-segment section.
See also#
docs/KDL_AUTHORING.md§8 — "Mitred tips", the roundwedge, and thestile_and_railstuck-profile paragraph.docs/adr/0026-tenon-tips-wedges-and-coped-rails.md— the three decisions and their evidence; RFC-0041, RFC-0126, RFC-0127.docs/agent-reference/nodes.md— the node index.- Examples:
examples/desk.kdlandexamples/dining_chair.kdl(tip mitre=#true);docs/styles/models/stile-and-rail.kdl(the glossary's frame joint).
Names#
Every name this page declares, how the example library uses it, and the shortest real use.
tip#
node in 15 of 116 examples (22 uses).
Shortest real use, from deco_console_table.kdl:
tip mitre=#true
wedge#
node in 6 of 116 examples (8 uses).
Shortest real use, from wedged_post_and_rung_stool.kdl:
wedge kerf=3.0 depth=18.0 flare=2.0 flare_depth=10.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"
}