← How-Tos
3d-printing Sep 7, 2026 ◑ 9 views ◯ 3 min read

Parametric Design with OpenSCAD: Generate Custom Bolts, Nuts, and Hardware

openscadparametric design3d printinghardwarecadboltshex nut

Most parametric CAD tools make you drag handles and click through dialog boxes to change a dimension. OpenSCAD flips that around: you write code, and the model is the output of that code. Change one variable โ€” bolt diameter, hole spacing, wall thickness โ€” and the entire model regenerates instantly. For anything you need in a family of sizes (mounting brackets, spacers, hardware, enclosures with configurable dimensions), that's a fundamentally faster workflow than redrawing geometry by hand each time.

Why OpenSCAD Instead of a GUI-Based CAD Tool

Fusion 360, FreeCAD, and similar tools are genuinely better for organic shapes, complex assemblies, and anything where you're visually sculpting a form. OpenSCAD is better specifically when the thing you're designing is really a formula with a few inputs โ€” a bolt is diameter, length, and head shape; a project box is width, height, depth, and wall thickness. Once you've written that formula once, generating a new size is changing a number, not redrawing a shape. The tradeoff is a steeper initial learning curve, since you're writing code instead of clicking, and no native fillets/chamfers as easy as GUI tools make them (`minkowski()` can approximate rounded edges, but it's slow to render on complex geometry).

The Core Mental Model

OpenSCAD models are built from a small set of primitive solids โ€” cube(), cylinder(), sphere() โ€” combined using boolean operations: union() to merge shapes, difference() to subtract one from another (this is how you cut holes), and intersection() to keep only the overlap between shapes. Everything else is variables, loops, and modules (OpenSCAD's version of functions) built on top of those primitives.

A Parametric Hex Bolt and Matching Nut

Here's a working example that generates a hex-head bolt and a matching hex nut, both driven by the same diameter and thread-pitch variables so they stay consistent with each other:

// ---- Parameters ---- bolt_diameter = 6; // shaft diameter, mm (M6-ish) bolt_length = 25; // shaft length, mm head_height = 4; head_width = bolt_diameter * 1.8; // flat-to-flat hex width nut_height = 5; // ---- Hex bolt ---- module hex_bolt() { union() { // Hex head โ€” cylinder() with $fn=6 draws a hexagonal prism cylinder(h=head_height, d=head_width, $fn=6); // Shaft translate([0, 0, head_height]) cylinder(h=bolt_length, d=bolt_diameter, $fn=32); } } // ---- Hex nut (head shape with a hole through it) ---- module hex_nut() { difference() { cylinder(h=nut_height, d=head_width, $fn=6); // Slightly oversized hole for print tolerance translate([0, 0, -1]) cylinder(h=nut_height+2, d=bolt_diameter+0.3, $fn=32); } } hex_bolt(); translate([head_width*1.5, 0, 0]) hex_nut();

The trick worth noticing: cylinder() with a low $fn value doesn't draw a circle, it draws a polygon โ€” $fn=6 gives you a perfect hexagon for free, instead of manually plotting six points. This is the single most useful shortcut for hardware-style parts in OpenSCAD.

On Actual Threads

Notice the shaft above is a plain smooth cylinder, not threaded. That's deliberate โ€” real ISO/UTS thread geometry (helical grooves at the correct pitch and profile angle) isn't something worth hand-rolling from scratch, and a naive thread approximation can produce a bolt that looks right in the preview but doesn't actually thread into a real nut. For working printable threads, use an established library instead: threads.scad is a solid, focused option, and the more comprehensive BOSL2 library includes correct thread modules alongside a large set of other mechanical primitives. Both are drop-in include files โ€” this smooth-shaft version above is meant as a heat-set-insert-friendly bolt substitute (works well combined with a printed heat-set insert and a real machine screw) rather than a fully self-threaded fastener.

Making It Actually Parametric

The example above is already parametric in the sense that matters โ€” every dimension is a named variable at the top, not a magic number buried in the geometry. To make a whole family of bolt sizes, wrap the parameters and the two modules in a single generator module that takes size as an argument, and call it once per size you need. That's the same pattern used in the OpenSCAD bolt/nut generator paste linked below โ€” take a look at the real, tagged version for a more complete implementation with a size table built in.