Documentation
Write parametric 3D models as code, see live previews, and share via short URLs.
How it works
PrintParams uses PPSCAD (PrintParams Scripted CAD), a simple language designed for parametric 3D modeling. Write code in the editor, click Run (or press Cmd+Enter), and the model renders in real time in the 3D viewer.
All computation happens client-side in a sandboxed Web Worker. Your code runs in the browser — nothing is sent to a server for rendering.
Complete documentation for the PPSCAD scripting language.
Quick example
// A box with a cylindrical hole through it
param width: float = 30 [10:100] "Width (mm)"
param height: float = 20 [5:50] "Height (mm)"
param depth: float = 10 [2:30] "Depth (mm)"
param hole_radius: float = 4 [1:15] "Hole radius (mm)"
difference {
cube(width, height, depth)
translate(width / 2, height / 2, -1)
cylinder(h: depth + 2, r: hole_radius)
}This creates a box with a cylindrical hole through it. The parameters appear as sliders in the parameter panel on the right.
PPSCAD at a glance
PPSCAD is inspired by OpenSCAD and JSCAD, with a clean modern syntax:
Primitives
cube(size) or cube(x, y, z)Axis-aligned box. Single number creates a cube.
cylinder(h: 20, r: 5)Cylinder. Use r1/r2 for a cone. Supports named or positional args.
sphere(r)Sphere centered at the origin.
Boolean operations
union { ... }Combine all children into one shape.
difference { ... }First child minus all subsequent children.
intersection { ... }Keep only the overlapping volume.
Transforms
translate(x, y, z) childMove geometry. Takes a single child or { block }.
rotate(x, y, z) childRotate around each axis in degrees.
scale(factor) childScale uniformly or per axis.
2D to 3D
extrude(height) circle(r)Linear extrusion of a 2D shape.
revolve() translate(15, 0) circle(3)Rotational sweep around the Y axis.
Parameters
Parameters let users tweak your model without editing code. Declare them with the param keyword. When you change a slider, the model re-runs automatically.
Syntax
param name: type = default [min:max:step] "Label" "Description"Parameter types
// Number with slider
param teeth: int = 20 [6:200] "Number of teeth"
// Float with custom step
param module: float = 2.0 [0.5:10:0.01] "Module (mm)"
// Boolean toggle (checkbox)
param chamfer: bool = true "Add chamfer"
// Dropdown select
param style: choice = round ["round", "square", "hex"] "Head style"Variables, functions, and modules
// Variables
let outer_r = teeth * module / 2
// Functions (return values)
fn gear_radius(teeth, module) = teeth * module / 2
// Modules (reusable geometry)
mod rounded_box(w, h, d, r) {
hull {
translate(r, r, 0) cylinder(h: d, r: r)
translate(w - r, r, 0) cylinder(h: d, r: r)
translate(r, h - r, 0) cylinder(h: d, r: r)
translate(w - r, h - r, 0) cylinder(h: d, r: r)
}
}
rounded_box(40, 20, 5, 3)Control flow
// Conditional geometry
if (add_holes) {
translate(10, 10, -1) cylinder(h: 22, r: 3)
}
// For loop with range (inclusive)
for (i in [0:4]) {
translate(i * 15, 0, 0) cube(10)
}
// Range with step
for (angle in [0:30:330]) {
rotate(0, 0, angle) translate(25, 0, 0) cylinder(h: 10, r: 3)
}Units
All dimensions are in millimeters. The viewer shows bounding box dimensions in mm. STL exports are also in mm — most slicers (PrusaSlicer, Cura, etc.) expect this.
Keyboard shortcuts
Sharing
Click Save to store your design and get a short URL. Anyone with the link can open your model, adjust the parameters, and download the STL.
Parameters can also be shared via URL query strings, e.g. ?width=50&height=30.