Skip to content

Twin tenon corner

joints.twin_tenon_corner

A wide rail at a frame corner (e.g. the bottom rail of a door) with twin tenons.

A single tenon as wide as the rail would need a long mortise weakening the stile, and would shrink and swell too much across its width; two tenons side by side, each in its own mortise, keep the material between them. The outer shoulder keeps the mortises away from the end of the stile.

Twin tenon corner, assembled

Twin tenon corner, exploded

Parameters

Parameter Default
stile_length 500
rail_length 300
stile_width 70
rail_width 150
outer_shoulder 20
stock 20 mm board, oak

Change them in a design file (see Change an example):

from woodwright.examples import joints

design = joints.twin_tenon_corner(stile_length=625)

Drawings

The plans in one PDF: plans.pdf.

Assembly

assembly

Parts

parts

Rail

rail

Stile

stile

Cut list

stile  500 x 70 x 20 mm  oak
       - 2 x mortise 40 x 8 mm, 47 deep, in back_edge
rail   345 x 150 x 20 mm  oak
       - 2 tenons 40 x 8 mm, 45 long, 40 apart, on left_end

Code

From woodwright/examples/joints.py, which imports the names it uses (see From an example to your own design):

def twin_tenon_corner(
    stile_length: float = 500,
    rail_length: float = 300,
    stile_width: float = 70,
    rail_width: float = 150,
    outer_shoulder: float = 20,
    stock: Stock = OAK,
) -> Assembly:
    """A wide rail at a frame corner (e.g. the bottom rail of a door) with twin tenons.

    A single tenon as wide as the rail would need a long mortise weakening
    the stile, and would shrink and swell too much across its width; two
    tenons side by side, each in its own mortise, keep the material between
    them. The outer shoulder keeps the mortises away from the end of the stile.
    """
    asm = Assembly("twin_tenon_corner", root_location=STANDING)
    stile = asm.add(Board("stile", stock, length=stile_length, width=stile_width))
    rail = asm.add(Board("rail", stock, length=rail_length, width=rail_width))
    asm.join(
        MortiseTenon(
            tenon=rail.left_end,
            mortise=stile.back_edge,
            position=flush_with(stile.right_end),
            shoulder=(outer_shoulder, 10),  # the front edge is outer, at the end of the stile
            tenons=2,
            tenon_length=45,
        )
    )
    return asm

Exported with woodwright 0.9.0 on 2026-10-25.