Building a Gear Housing

In this tutorial, you'll build a gear housing based on exercises from Too Tall Toby. It covers filleting, angled chamfers, multi-level extrusions, draft cuts, arc profiles, complex sketches with rounded corners, drilling, counterbores, circular copy patterns, and mirror symmetry.
Create a new file called gear-housing.fluid.js in your project.
Setup
Start with the imports and parameters for the support brackets:
import { arc, chamfer, circle, copy, cut, extrude, fillet, hMove, mirror, move, plane, pMove, rect, repeat, sketch, vMove } from "fluidcad/core";
let supportWidth = (150 - 63) / 2;
let supportThickness = 12;
The gear housing is 150mm wide overall. The central gap between the support brackets is 63mm, so each bracket is (150 - 63) / 2 = 43.5mm wide. The brackets are 12mm thick.
Step 1: Support Bracket
Sketch the bracket profile
The first bracket sits to the right of center. hMove(63 / 2) shifts the cursor to the edge of the central gap, then rect() draws the bracket profile. .centered('vertical') centers it vertically so it extends equally above and below the origin.
sketch("xy", () => {
hMove(63 / 2)
rect(supportWidth, 115).centered('vertical')
});
Extrude and add edge treatments
Extrude the bracket, fillet two side edges to round them, and add an angled chamfer to the end edges. chamfer(8, 90 - 25, true, ...) uses a distance of 8mm and an angle of 65° — the third argument true means the second parameter is an angle rather than a second distance.
const e1 = extrude(supportThickness);
fillet(12, e1.sideEdges(2, 3));
chamfer(8, 90 - 25, true, e1.endEdges())

Step 2: Main Housing Body
Lower body
Sketch a centered rectangle on the "top" plane and extrude it 130mm upward to form the main housing block. Also create a reference plane on the bracket's side face — you'll use rightPlane later for the slot and bolt hole.
sketch("top", () => {
rect(116, 77).centered();
});
const e2 = extrude(130);
const rightPlane = plane(e1.sideFaces(2))
Upper section
Sketch a slightly narrower rectangle on the end face of the lower body and extrude it 38mm more. The width change from 77mm to 68mm creates a stepped profile. Chamfer the top edges to finish.
sketch(e2.endFaces(), () => {
rect(116, 68).centered();
});
const e3 = extrude(168 - 130);
chamfer(8, e3.endEdges());

Step 3: Internal Cavity
Sketch a centered rectangle on the "xy" plane and cut downward 158mm with a 3° draft angle. The negative depth cuts downward, and .draft(-3) tapers the cavity walls inward — typical for cast parts where draft helps with mold release.
const p1 = plane("xy");
sketch(p1, () => {
rect(100, 62).centered();
});
cut(-158).draft(-3)

Step 4: Side Slot and Bolt Hole
Sketch the slot profile
On rightPlane, build a keyhole-shaped profile: a narrow rectangle topped by a semicircular arc. vMove() positions the cursor vertically, rect(20, 4).centered('horizontal') draws the narrow slot, then arc(10, 0, 180) adds a 180° semicircle on top.
sketch(rightPlane, () => {
move([0, 0]);
vMove(16)
vMove(-4)
rect(20, 4).centered('horizontal')
vMove(4)
arc(10, 0, 180)
});

Extrude the slot and cut the bolt hole
Extrude the slot profile 20mm inward, then sketch a circle on the same plane and cut through for the bolt hole.
extrude(-40 / 2)
sketch(rightPlane, () => {
move([0, 0]);
vMove(16)
circle(9);
});
cut();

Step 5: Side Ribs
Sketch the rib profile
On the side face of the upper section, sketch a profile made of two stacked rectangles with rounded corners. .radius(8, 8, 0, 0) rounds the top corners of the lower rectangle, while .radius(0, 0, 8, 8) rounds the bottom corners of the upper one, creating a smooth transition.
sketch(e3.sideFaces(0), () => {
const rect1Width = 77;
const offset = 90;
const rect1Height = 130 - offset;
move([-rect1Width / 2, offset]);
rect(rect1Width, rect1Height).radius(8, 8, 0, 0)
const leftOffset = (rect1Width - 68) / 2;
hMove(-rect1Width + leftOffset);
const rect2Width = 68;
const rect2Height = 152 - 130;
rect(rect2Width, rect2Height).radius(0, 0, 8, 8)
});

Extrude and mirror
Extrude the rib by (128 - 116) / 2 = 6mm. .drill(false) prevents the extrusion from cutting into the existing body. Then mirror("yz") creates the matching rib on the opposite side.
const e5 = extrude((128 - 116)/2).drill(false)
mirror("yz")

Step 6: Bearing Bore and Counterbore
Cut a through-hole for the bearing with a 42mm radius circle, then add a larger 54mm radius counterbore 10mm deep. repeat("mirror", "yz", counterbore) mirrors the counterbore to the opposite side.
sketch(e5.endFaces(), () => {
move([0, 122])
circle(42);
});
cut()
sketch(e5.endFaces(), () => {
move([0, 122])
circle(54);
});
const counterbore = cut(10);
repeat("mirror", "yz", counterbore);

Step 7: Front Plate and Mounting Holes
Circular front plate
Sketch a large circle on the front face of the housing and extrude it 5.5mm to create the bearing mounting plate.
sketch(e2.sideFaces(3), () => {
circle(122)
});
const e6 = extrude(11/2)
Keyway notches
Cut narrow rectangular notches at the sides of the plate. repeat("mirror", "yz", c2) mirrors the notch to the other side.
sketch(e6.endFaces(), () => {
hMove(116 / 2);
rect(5, 40).centered('vertical')
});
const c2 = cut()
repeat("mirror", "yz", c2);
Bolt hole pattern
Use pMove() to position the cursor in polar coordinates, then draw a bolt hole with circle(9). copy('circular', [0, 65], ...) repeats the hole 4 times around center [0, 65] at equal 90° intervals. Finally, circle(85) adds the large central bore.
sketch(e6.endFaces(), () => {
pMove(103 / 2, 45)
circle(9)
copy('circular', [0, 65], {
count: 4,
angle: 360
});
circle(85)
});
cut()

Final mirror
mirror("front") mirrors the entire model across the front plane to complete the symmetric gear housing.
mirror("front")

Full code
import { arc, chamfer, circle, copy, cut, extrude, fillet, hMove, mirror, move, plane, pMove, rect, repeat, sketch, vMove } from "fluidcad/core";
let supportWidth = (150 - 63) / 2;
let supportThickness = 12;
sketch("xy", () => {
hMove(63 / 2)
rect(supportWidth, 115).centered('vertical')
});
const e1 = extrude(supportThickness);
fillet(12, e1.sideEdges(2, 3));
chamfer(8, 90 - 25, true, e1.endEdges())
sketch("top", () => {
rect(116, 77).centered();
});
const e2 = extrude(130);
const rightPlane = plane(e1.sideFaces(2))
sketch(e2.endFaces(), () => {
rect(116, 68).centered();
});
const e3 = extrude(168 - 130);
chamfer(8, e3.endEdges());
const p1 = plane("xy");
sketch(p1, () => {
rect(100, 62).centered();
});
cut(-158).draft(-3)
sketch(rightPlane, () => {
move([0, 0]);
vMove(16)
vMove(-4)
rect(20, 4).centered('horizontal')
vMove(4)
arc(10, 0, 180)
});
extrude(-40 / 2)
sketch(rightPlane, () => {
move([0, 0]);
vMove(16)
circle(9);
});
cut();
sketch(e3.sideFaces(0), () => {
const rect1Width = 77;
const offset = 90;
const rect1Height = 130 - offset;
move([-rect1Width / 2, offset]);
rect(rect1Width, rect1Height).radius(8, 8, 0, 0)
const leftOffset = (rect1Width - 68) / 2;
hMove(-rect1Width + leftOffset);
const rect2Width = 68;
const rect2Height = 152 - 130;
rect(rect2Width, rect2Height).radius(0, 0, 8, 8)
});
const e5 = extrude((128 - 116)/2).drill(false)
mirror("yz")
sketch(e5.endFaces(), () => {
move([0, 122])
circle(42);
});
cut()
sketch(e5.endFaces(), () => {
move([0, 122])
circle(54);
});
const counterbore = cut(10);
repeat("mirror", "yz", counterbore);
sketch(e2.sideFaces(3), () => {
circle(122)
});
const e6 = extrude(11/2)
sketch(e6.endFaces(), () => {
hMove(116 / 2);
rect(5, 40).centered('vertical')
});
const c2 = cut()
repeat("mirror", "yz", c2);
sketch(e6.endFaces(), () => {
pMove(103 / 2, 45)
circle(9)
copy('circular', [0, 65], {
count: 4,
angle: 360
});
circle(85)
});
cut()
mirror("front")
What you practiced
fillet()— rounds selected edges with a given radiuschamfer()with angle — creates chamfers using a distance and angle whenisAngleistrueplane()— creates a reference plane from an existing face for subsequent sketchescut().draft()— cuts material with tapered walls for mold-release draft anglesarc()— draws semicircular arcs to build keyhole-shaped profilesrect().radius()— creates rectangles with selectively rounded corners.drill(false)— extrudes material without cutting into the existing bodymirror()— mirrors geometry across a principal planerepeat("mirror", ...)— mirrors specific operations to the opposite sidecopy('circular', ...)— creates circular patterns of sketch elementspMove()— positions the cursor using polar coordinates