Skip to content

Frame and panel

frames.frame_and_panel

A mortise-and-tenon frame with a panel in grooves along its inside edges.

The panel's design size is the opening of the frame; the grooves add to it. The grooves run through the stiles, so the tenons are as thick as the grooves are wide and have haunches filling the grooves out to the ends.

Frame and panel, assembled

Frame and panel, exploded

Parameters

Parameter Default
stile_length 600
rail_length 300
width 60
shoulder 10
stock 20 mm board, oak
panel_stock 10 mm board, oak

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

from woodwright.examples import frames

design = frames.frame_and_panel(stile_length=750)

Drawings

The plans in one PDF: plans.pdf.

Assembly

assembly

Parts

parts

Panel

panel

Rail

rail

Stile

stile

Cut list

stile  600 x 60 x 20 mm  oak, 2 pieces: stile_left, stile_right
       - 2 x mortise 40 x 10 mm, 42 deep, in back_edge
       - haunch mortise 10 x 10 mm, 10 deep, in back_edge at right_end
       - haunch mortise 10 x 10 mm, 10 deep, in back_edge at left_end
       - groove 10 mm, 10 deep, in back_edge
rail   380 x 60 x 20 mm  oak, 2 pieces: rail_top, rail_bottom
       - haunched tenon 40 x 10 mm, 40 long, haunch 10 long, on left_end
       - haunched tenon 40 x 10 mm, 40 long, haunch 10 long, on right_end
       - groove 10 mm, 10 deep, in back_edge
panel  500 x 320 x 10 mm  oak

Code

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

def frame_and_panel(
    stile_length: float = 600,
    rail_length: float = 300,
    width: float = 60,
    shoulder: float = 10,
    stock: Stock = OAK,
    panel_stock: Stock = THIN_OAK,
) -> Assembly:
    """A mortise-and-tenon frame with a panel in grooves along its inside edges.

    The panel's design size is the opening of the frame; the grooves add to it.
    The grooves run through the stiles, so the tenons are as thick as the
    grooves are wide and have haunches filling the grooves out to the ends.
    """

    def corner(rail_end: SideRef, stile_edge: SideRef, position: Position, outer: SideRef) -> Joint:
        return MortiseTenon(
            tenon=rail_end,
            mortise=stile_edge,
            position=position,
            shoulder=shoulder,
            tenon_thickness=panel_stock.thickness,
            haunch=outer,
        )

    asm, (stile_left, stile_right, rail_top, rail_bottom) = _frame(
        "frame_and_panel", corner, stile_length, rail_length, width, stock
    )
    panel = asm.add(Board("panel", panel_stock, length=stile_length - 2 * width, width=rail_length))
    for groove, edge in [
        (stile_left.back_edge, panel.front_edge),
        (stile_right.front_edge, panel.back_edge),
        (rail_top.back_edge, panel.right_end),
        (rail_bottom.front_edge, panel.left_end),
    ]:
        asm.join(GrooveJoint(groove=groove, edge=edge))
    return asm

Exported with woodwright 0.9.0 on 2026-10-25.