Skip to main content
Built-in Elements

<assembly.printedpart />

assembly.printedpart adds a mechanical part to an assembly.device. Supply JSCAD JSX with jscad, or an existing model with model, modelUrl, or cadModel. The part has no PCB footprint or schematic symbol.

For a motor mounted to a printed bracket and a controller on the same base, see Advanced Assembly.

Mount a printed spacer between a motor and a board​

The assembly below connects NEMA17.backface → SPACER.motor, then SPACER.board → the controller PCB. The spacer has a 4 mm plate, four hollow posts, and a 30 mm center opening. Its total height is 10 mm, including the plate.

The complete example starts with the assembly connections. MotorSpacer defines the printable geometry and its named mounting faces; MotorController forwards mounting props to its underlying board.

import { assembly, jscad } from "tscircuit"
import type { BoardProps } from "@tscircuit/props"

const holeCenters = [-15.5, 15.5].flatMap((x) =>
[-15.5, 15.5].map((y) => [x, y] as const),
)

export default () => (
<assembly.device>
<assembly.motor
name="NEMA17"
model="nema17_backfaceholes"
shaftFacingDirection="z-"
/>
<assembly.printedpart
name="SPACER"
jscad={<MotorSpacer height={10} />}
mountedTo="NEMA17.backface"
mountFace="motor"
/>
<MotorController mountedTo="SPACER.board" />
</assembly.device>
)

function MotorSpacer({ height = 10 }: { height?: number }) {
return (
<>
<jscad.subtract>
<jscad.union>
<jscad.cuboid size={[42, 42, 4]} center={[0, 0, 2]} />
{holeCenters.map(([x, y]) => (
<jscad.cylinder
key={[x, y].join(",")}
radius={4}
height={height}
center={[x, y, height / 2]}
/>
))}
</jscad.union>
<jscad.cylinder
radius={15}
height={height + 2}
center={[0, 0, height / 2]}
/>
{holeCenters.map(([x, y]) => (
<jscad.cylinder
key={[x, y].join(",")}
radius={1.6}
height={height + 2}
center={[x, y, height / 2]}
/>
))}
</jscad.subtract>

{/* Plate underside: local Z=0, facing the motor. */}
<jscad.rotate angles={[0, Math.PI, 0]}>
<jscad.rectangle name="motor" size={[42, 42]} reference />
</jscad.rotate>
{/* Post tips: local Z=height, facing the PCB. */}
<jscad.translate offset={[0, 0, height]}>
<jscad.rectangle name="board" size={[42, 42]} reference />
</jscad.translate>
</>
)
}

function MotorController(props: BoardProps) {
return (
<board
width="42mm"
height="42mm"
thickness="1.6mm"
routingDisabled
{...props}
>
{holeCenters.map(([x, y]) => (
<hole
key={[x, y].join(",")}
diameter="3.2mm"
pcbX={x}
pcbY={y}
/>
))}
{/* Add your controller components and traces here. */}
</board>
)
}
3D Circuit Preview

The motor sits below the PCB, with its shaft pointing down. Omitted mountGap values default to zero: the plate touches the motor's backface and the PCB rests on the post tips. Add mountGap="1mm" to the printed part for motor-to-spacer clearance, or to MotorController for spacer-to-PCB clearance.

DimensionValue
Plate42 × 42 × 4 mm
Total spacer height10 mm; change height to a value greater than 4 mm
PostsFour, 8 mm outside diameter; extend 6 mm beyond the plate
Screw holes3.2 mm diameter M3 clearance holes through the plate and posts
Hole centersX and Y at ±15.5 mm, giving a 31 × 31 mm pattern
Center opening30 mm diameter

nema17_backfaceholes selects a NEMA17 model with open rear holes instead of protruding rear screw heads. Match the rear-hole pattern to your actual motor. The controller here is a board with mounting holes; replace its contents with your circuit, or pass the same mounting props through your existing controller component.

Name a mounting face in JSCAD​

A <jscad.rectangle name="…" reference /> marks a mounting face. It adds no printable material and is removed from the rendered model. Place reference rectangles alongside the solid geometry in a fragment, then move and rotate them with JSCAD transforms.

Reference in the examplePosition in the partOutward direction
motorPlate underside at Z = 0−Z, using a half-turn around Y
boardPost tips at Z = height+Z, the rectangle's default direction

The rectangle's center is the attachment point, its local +Z is the outward direction, and its local +X controls the in-plane alignment. JSCAD dimensions are in millimetres and rotation angles are in radians. Reference names must be unique within the part.

On the printed part, mountedTo="NEMA17.backface" chooses the target face and mountFace="motor" chooses its own face. Supply these two props together. The faces meet with opposing outward directions and aligned in-plane X directions. A board only needs mountedTo="SPACER.board"; it does not need a mountFace prop.

Mounting keeps the PCB's existing XY layout and its center plane at Z = 0, moving the attached parts to meet it. Board mounting requires a target face parallel to XY; motor–spacer–board chains support shaft directions z+ and z-. One board can anchor each connected chain of parts. Targets resolve by name inside the same assembly.device, including targets declared later.

Use an existing CAD model​

Provide exactly one of jscad, model, modelUrl, or cadModel:

<assembly.printedpart name="SPACER" modelUrl="./spacer.stl" />
<assembly.printedpart name="BRACKET" model="./bracket.glb" />
<assembly.printedpart
name="COVER"
cadModel={{
glbUrl: "./cover.glb",
positionOffset: { x: 0, y: 0, z: 12 },
}}
/>

Use your own asset paths. model accepts a modelprinter/footprinter specification or a model URL. cadModel accepts the existing CAD model formats and transforms described in mounting 3D models.

Imported models do not automatically provide named mounting faces. For the face-based mounting shown above, author the reference rectangles through the jscad prop.

Printed part properties​

PropertyTypeDescription
namestringRequired name used in references such as SPACER.board.
displayNamestringOptional display label.
jscadReactElementJSCAD JSX from jscad-fiber, available as jscad from tscircuit.
modelstringModel specification or model URL.
modelUrlstringURL or asset path for an existing CAD model.
cadModelCadModelPropExisting CAD model configuration or CAD JSX.
mountedTostringTarget part and face, such as NEMA17.backface.
mountFacestringThis part's named reference face; supply together with mountedTo.
mountGapstring | numberNonnegative surface clearance in mm or a unit string. Defaults to zero; requires mountedTo.

JSCAD JSX can contain synchronous function components, fragments, and arrays. Hooks, async components, and raw JSCAD kernel geometry are not supported in the jscad prop.