Skip to main content

part()

part(name, callback) declares a named part. Everything the callback does — sketches, features, connectors, exposures, parameters, properties — belongs to that part.

import { part, sketch, circle, extrude } from 'fluidcad/core';

export const disc = part('Disc', () => {
sketch('xy', () => {
circle([0, 0], 40);
});
extrude(5);
});

Two rules​

  • Every part is exported. A part is export const disc = part('Disc', () => { … }) at the top level of its file: the export is how an assembly imports it and how the Insert dialog finds it. A .name() or .material() chain on the statement, a top-level const listed in an export { disc } clause, and an exported function that returns the part (export const bolt = (length = 20) => part('Bolt', …)) count as exported too. A part() nothing exports, one exported only as default, and one written inside another part's or assembly's body are refused.
  • Part names are unique within a file. The name is what the Part Parameters panel, the configurations tables and the timeline tell the file's parts apart by. The first part() of a name builds; a later one with the same name is refused.

A refused part does not build: its timeline row shows the reason as a build error and the rest of the file renders. The messages name the fix:

part 'Disc': a part must be exported — write it as export const disc = part('Disc', …) at the top level of the file.
part 'Disc': another part in this file is already named 'Disc' — give each part its own name.

An agent writing the file through the MCP server is stopped before the file is written, with the same messages.

In the viewport​

Click Part on the toolbar. FluidCAD appends export const part1 = part('Part 1', () => {}) (the next free Part N) to the file, activates it, and routes the next features into its body. Rename it from the timeline row's right-click menu: the name in part('…') is rewritten and the exported variable is renamed after it (Fixed leaf binds fixedLeaf), in the files that import the part too. A name another part of the file already has is refused. There is no Apply: the statement is written the moment you click.

The definition is lazy​

part() returns a definition, not built geometry. The callback runs:

  • when the file renders on its own — the open part file stays what-you-see-is-what-you-get, so every part of the file shows in the viewport, inserted or not;
  • once per variant when an assembly inserts it: insert(def) and insert(def, { Width: 120 }) are two builds, while two insert(def, { Width: 120 }) share one.

Because the body runs later, it must be self-contained: read parameters with param() inside the callback, not from variables computed outside it.

Arguments​

ArgumentMeaning
nameThe part's display name — in the timeline, the Parts panel, and the STEP product tree on export.
callbackThe body. Its return value is ignored; publish geometry with expose().

What the definition gives you​

MemberMeaning
def.features.<name>The source object an expose() published, for another part to build on: extrude(15, donor.features.profile).
def.properties.<name>A value a property() published, from the default variant: donor.properties.pocketDiameter.
insert(def)In an assembly: an instance of the part with instance.connectors.<name>, instance.features.<name> and instance.properties.<name> bound to it.

Material​

A part can carry a material, and Shape properties turns its volume into a mass with that material's density.

  1. Click the ⋮ button at the right edge of the part's row in the History panel (or right-click the row) and choose Set material….
  2. The Set material dialog lists the built-in materials under Built-in and the custom ones under Custom — the project's own, tagged in project, and yours from Settings → Materials. The current one is checked and first in its group; None removes the material. Click a row and Apply.
  3. Open Shape properties (the scale icon at the bottom right), choose the Part tab, click the part in the viewport — every solid of the part highlights — and click Calculate.

The Set material dialog on a part row

Shape properties in Part mode, with the mass

The code behind it
plate.part.js
import { part, sketch, line, circle, extrude, chamfer } from 'fluidcad/core';
import { coincident, distance, fix, horizontal, vertical } from 'fluidcad/constraints';

// A mounting plate: an 80 x 50 rectangle with a clearance hole near each
// corner, 6 mm thick, top edges chamfered. Its material is a chain on the
// part() statement — Set material… on the timeline row writes it.
export const plate = part('Plate', () => {
sketch('xy', () => {
const b = line([-40, -25], [40, -25]);
const r = line([40, -25], [40, 25]);
const t = line([40, 25], [-40, 25]);
const l = line([-40, 25], [-40, -25]);
coincident(b.end(), r.start());
coincident(r.end(), t.start());
coincident(t.end(), l.start());
coincident(l.end(), b.start());
horizontal(b);
horizontal(t);
vertical(r);
vertical(l);
fix(b.start(), [-40, -25]);
distance(b.start(), b.end(), 80);
distance(r.start(), r.end(), 50);
// One M5 clearance hole inset 8 mm from each corner.
for (const sx of [-1, 1]) {
for (const sy of [-1, 1]) {
circle([sx * 32, sy * 17], 2.75);
}
}
});
const e = extrude(6);
chamfer(1, e.endEdges());
}).material('fluidcad-aluminum-6061');

The pick is a .material('<id>') chain on the part() statement, next to where .name() goes. The argument is an id, never a density:

IdWhere it comes from
fluidcad-steel-1020, fluidcad-stainless-304, fluidcad-aluminum-6061, fluidcad-aluminum-1060, fluidcad-aluminum-7075, fluidcad-brass-c260, fluidcad-copper, fluidcad-titanium-6al4v, fluidcad-cast-iron-gray, fluidcad-bronze, fluidcad-pc, fluidcad-abs, fluidcad-pla, fluidcad-nylon-pa6, fluidcad-carbon-fiber, fluidcad-pine, fluidcad-carbon-steelBuilt in. Always available; listed under Built-in.
alloy-steel, acme-pla, …A key of the materials map in the project's fluidcad.json. Listed under Custom, with your own materials from Settings → Materials; applying one of those copies its entry into the map, so the project carries what it uses.

A material that is in neither list is added first — to Settings → Materials, or by hand to fluidcad.json — then picked. An id the lists do not know is a warning rather than a build error: the part still builds, its row shows a warning triangle, and Shape properties reads Unknown material: <id> with no mass.

Only parts carry a material. A solid outside any part is measured with a material picked in Shape properties for that calculation alone; nothing is written to the file. See Shape properties.

Export it​

An assembly can only insert what the part file exports:

export const bracket = part('Bracket', () => { /* … */ });

The Insert dialog scans the workspace for exported definitions and lists each with a thumbnail and the file it came from. Two files may each export a part — the assembly's import gets a local alias automatically when the dialog writes it.

Fusion boundary​

Solids inside a part fuse with each other and with nothing outside it: put a bolt and the bracket it sits in into two parts and they stay two solids. Inside one part, .new() keeps a feature as a separate body.

Units​

The part's numbers are in its file's unit. Inserted into a project with a different unit it is rescaled on the way in — a 2 in boss is 50.8 mm in a millimetre assembly. insert(def, { Length: 10 }) means 10 in the part's unit. See Units.