In Two-layer keychains, upload the base and raised artwork as separate SVGs. This fixed example uses a 60 × 30 mm tag, a 2 mm white base, and a 2 mm Carolina blue star. Choose a step to slow down what the app does. For a name with no SVG, use Bubbly name keychains.
Predict before printing: at what height should the star’s color begin? If you swap white and blue, what changes in the file, and what stays the same?
Read the code as a recipe
This readable version is teaching shorthand. Intersection means keep the area that belongs to both shapes; translate means move it without changing its size.
supportedArt = intersection(topDrawing, baseDrawing)
basePart = extrude(baseDrawing, baseHeight)
topPart = moveUp(extrude(supportedArt, addedHeight), baseHeight)
3MF = package(basePart → filament 1, topPart → filament 2)
- Find support in X and Y. Intersect the top drawing with the base. Artwork outside the base or over a keyring hole is removed.
- Build the base in Z. A 2 mm extrusion occupies Z = 0–2 mm.
- Lift the second part. Another 2 mm extrusion starts at Z = 0–2 mm; moving it upward by 2 mm places it at Z = 2–4 mm. They meet at Z = 2 mm. Total height is 2 + 2 = 4 mm.
- Attach material instructions. Both parts retain the same X/Y placement. The file names them Base and Raised top and assigns filament 1 and 2. Color choices change the preview color stored for each assignment, not the geometry.
Actual source excerpt · geometry and 3MF assembly
layers-geometry.js builds the color top after clipping the artwork. keep() tracks temporary shapes so the engine can release them later.
const colorTop = keep(
keep(supported.extrude(topThickness))
.translate([0, 0, baseThickness])
);
// Returned as two named meshes:
colorParts: [
{ name: 'Base', ...asMesh(body) },
{ name: 'Raised top', ...asMesh(colorTop) }
]
layers-3mf.js writes each mesh’s vertices and triangles. Its assembly then refers to both objects, preserving their shared coordinates:
<object id="4" type="model" name="Keychain">
<components>
<component objectid="2"/> <!-- Base -->
<component objectid="3"/> <!-- Raised top -->
</components>
</object>The object name follows your base filename. The IDs above connect the assembly to its two mesh objects; Creality metadata assigns their filaments.
What is inside the 3MF, and what happens next?
| Package entry | Its job |
|---|
3D/3dmodel.model | Triangle surfaces, millimetre units, two material colors, and the assembly. |
Metadata/model_settings.config | Names the parts and assigns Base to filament 1, Raised top to filament 2. |
Metadata/project_settings.config | The two preview colors and a generic PLA palette. Choose profiles for your actual spools in Creality Print. |
[Content_Types].xml and _rels/.rels | Tell the 3MF reader what the package contains and where its model is. |
Creality Print supplies your printer/nozzle profile and slicing settings. Confirm the two part assignments, slice, inspect the layers, then map the filaments to the loaded CFS slots. Filament numbers are not physical slot numbers. This export contains no sliced toolpaths.
Try the two-layer keychain workshop