New Project

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 the tenons-meet rule refuses the pair.
  • wedge on a round_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 rectangular mortise_and_tenon has had wedge since M15; this is the round one.
  • profile "ogee" (or any moulding) on stile_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 write tip mitre=#true on 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); depth must be at least flare_depth and 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): declare grain on 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 — see docs/KDL_AUTHORING.md.
  • params — a stuck profile needs both profile_size and profile_face; an unknown profile or face word is named. profile_size/profile_face with profile "square" is only a warning (they do nothing).
  • cope-profile — the sticking would cut into the panel groove (profile_size larger 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_face names a narrow edge of the rail or a way no member's side face looks, or the shoulder is off square.
  • profile_face is 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: clearance belongs 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 round wedge, and the stile_and_rail stuck-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.kdl and examples/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"
}

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