Project · Intermediate · 3D Printing
First Functional Bracket in CadQuery
Parametric M5 extrusion mount with AI-assisted parameter naming.
Project template
- Goal & materials
- Steps / firmware
- Troubleshooting
- AI assist notes
- Related gear & books
CadQuery is a Python library for parametric CAD. Instead of clicking through sketches, you describe a part in code, change a variable, and rerun. That makes it a good fit for simple functional parts such as brackets, where you often need the same shape in a few sizes. This guide builds an L-bracket for 2020 aluminum extrusion with M5 hardware and shows how AI can help with naming and readability without being trusted for dimensions.
Setup
- Install Python 3, then install CadQuery with
pip install cadqueryin a virtual environment. Conda is also supported; follow the CadQuery documentation if pip gives you trouble on your platform. - Pick a viewer: CQ-editor (a standalone CadQuery IDE) or the OCP CAD Viewer extension for VS Code.
- Create a file called
bracket.py.
Measure first
Extrusion and T-nut dimensions vary between suppliers. Before modeling, measure or look up:
- The extrusion face width (20 mm for 2020).
- The slot width, which matters if you add alignment tabs.
- The M5 screw and T-nut you will use, including how far the screw must reach into the nut.
For M5 clearance holes, 5.5 mm is the ISO 273 medium-fit size. Printed holes often come out slightly undersize, so test a small coupon and adjust.
The model
import cadquery as cq
# Dimensions in millimeters
leg_length = 40.0 # length of each leg from the outside corner
width = 20.0 # matches the 2020 extrusion face
thickness = 5.0 # wall thickness of each leg
hole_diameter = 5.5 # M5 clearance
hole_offset = 25.0 # outside corner to hole center
inner_fillet = 4.0 # radius at the inside corner
# Horizontal leg along X, vertical leg along Z
horizontal_leg = cq.Workplane("XY").box(
leg_length, width, thickness, centered=(False, True, False))
vertical_leg = cq.Workplane("XY").box(
thickness, width, leg_length, centered=(False, True, False))
bracket = horizontal_leg.union(vertical_leg)
# Round the inside corner to reduce stress concentration
bracket = (bracket.edges("|Y")
.edges(cq.selectors.NearestToPointSelector((thickness, 0, thickness)))
.fillet(inner_fillet))
# Hole through the horizontal leg (drilled along Z)
hole_h = (cq.Workplane("XY").workplane(offset=-1)
.center(hole_offset, 0).circle(hole_diameter / 2)
.extrude(thickness + 2))
# Hole through the vertical leg (drilled along X)
hole_v = (cq.Workplane("YZ").workplane(offset=-1)
.center(0, hole_offset).circle(hole_diameter / 2)
.extrude(thickness + 2))
bracket = bracket.cut(hole_h).cut(hole_v)
cq.exporters.export(bracket, "bracket.step")
cq.exporters.export(bracket, "bracket.stl")
In CQ-editor, add show_object(bracket) at the end to display it.
How it works
- Two boxes, one union. Each leg is a box positioned from the origin, and
unionmerges them into one solid. - Selecting the inside edge.
edges("|Y")picks edges parallel to Y, and the nearest-point selector narrows that to the inside corner, which gets the fillet. - Holes as cut cylinders. Each hole is a circle extruded slightly longer than the wall and subtracted, so it always cuts fully through.
- Exports. STEP keeps exact geometry for other CAD tools; STL goes to the slicer.
Making it useful
- Longer legs, two holes each: add a second hole offset and repeat the cut.
- A gusset: extrude a triangle on the XZ plane at the center of the bracket and union it for much stiffer corners.
- Counterbores: CadQuery has
cboreHoleon a face workplane for screw heads that sit flush. - Sizes as a function: wrap the code in a function that takes the parameters and returns the solid, then export several sizes in a loop.
Printing it
- Print it lying on one leg's outer face so layers run along both legs. Standing it on its edge puts layer lines right at the corner, where it will crack.
- Use plenty of perimeters (four or more) so the bolt holes are surrounded by solid plastic.
- PETG or ASA handle warmth and impact better than PLA for frame parts.
Using AI for parameter naming, not dimensions
AI assistants are good at tidying code: suggesting clearer variable names, adding comments, or turning a script into a function. A safe way to use one here:
- Paste your working script and ask for clearer names and comments without changing any numbers or geometry.
- Diff the result against your original. Every numeric value should be unchanged.
- Rerun and compare the exported part, or at least its bounding box, to the original.
Do not ask a model for extrusion slot widths, T-nut dimensions, or screw lengths. Those come from your calipers and the supplier's drawings.
Common mistakes
- Hole positions that collide with the other leg or the fillet. Keep
hole_offsetcomfortably larger thanthickness + inner_fillet. - Holes printed too tight. Adjust the diameter after a test print rather than drilling every part.
- Selector errors such as "no edges selected" after changing dimensions. Print the selected objects or check the point you pass to the selector.
- Exporting only STL, then needing to edit the part later in another CAD tool. Keep the STEP and the script.
Summary
A CadQuery bracket is a few dozen lines of Python: two boxes, a fillet, and two cut holes, all driven by named parameters. Measure your extrusion and hardware, print on the flat face with strong walls, and let AI help with readability while your calipers decide the numbers.
Related
- Projects hub
- Newsletter
- Books for deeper reading