Installation
FluidCAD ships as a desktop app for Windows, Linux and macOS, as an npm package for running it from a Node.js project in your browser, and as a Docker image for keeping your projects on a server. Pick the download for your system below, or skip to the npm installation if you prefer to work from a terminal.
Models are .part.js files (parts) and .assembly.js files (assemblies), written by the viewport as you work.
The links below point at the current release, FluidCAD 0.0.48; every build is also on the GitHub releases page. The app updates itself from there afterwards: it checks quietly in the background and installs the next version when you quit.
Windows
- Installer (x64):
FluidCAD-0.0.48-win-x64.exe
Run the installer and follow the prompts. The installer is not code-signed, so Windows SmartScreen shows Windows protected your PC on first launch; choose More info → Run anyway.
Linux
- AppImage (x64):
FluidCAD-0.0.48-linux-x86_64.AppImage - Debian package (x64):
FluidCAD-0.0.48-linux-amd64.deb
For the AppImage, mark it executable (chmod +x FluidCAD-*.AppImage) and run it. For the .deb, install it with sudo apt install ./FluidCAD-*.deb. The AppImage updates itself; the .deb is updated by installing the next release's package.
macOS
- Disk image (Apple Silicon):
FluidCAD-0.0.48-mac-arm64.dmg - Zip archive (Apple Silicon):
FluidCAD-0.0.48-mac-arm64.zip
Open the disk image and drag FluidCAD into Applications. The build is signed and notarized, so it opens without a Gatekeeper prompt.
npm installation
If you would rather run FluidCAD from a terminal and model in your browser, run it with npx: on its own for the start screen, or inside a project to open just that one.
Prerequisites
- Node.js version 24 or higher
- npm (comes with Node.js)
The start screen
npx fluidcad
opens the start screen in your browser, the same one the desktop app shows: your
recent projects, New Project, Open Project, and the engine each project
runs on. Each project opens in a tab of its own. Leave the command running while
you work; Ctrl+C stops FluidCAD and every project it opened. See fluidcad
in the CLI Reference.
Create a new project
To set a project up from the terminal instead:
mkdir my-hinge && cd my-hinge
npm i fluidcad
npx fluidcad init
npx fluidcad serve
init creates a project with the following structure:
my-hinge/
├── package.json
├── jsconfig.json
├── fluidcad.json ← project configuration (engine pin, unit)
├── init.js ← required project entry point
└── part1.part.js ← your first part, empty
serve starts the FluidCAD server and opens the viewport in your browser. Leave it running while you model; press Ctrl+C to stop it.
| Flag | Description | Default |
|---|---|---|
-w, --workspace <path> | Path to your project | Current directory |
-p, --port <port> | Server port — if it's already taken, the next free one is used | 3100 |
--no-open | Don't launch a browser — for CI and remote sessions | opens by default |
To run from elsewhere, point -w at your project: npx fluidcad serve -w ./my-app.
fluidcad.json records which FluidCAD version the project was authored against and, optionally, its default length unit. See Project configuration.
FluidCAD model files use the .part.js extension (assemblies use .assembly.js). The viewer only picks up files with this naming convention.
FluidCAD is installed per-project and run with npx fluidcad …; a global install (npm install -g fluidcad) is not supported. The engine and your editor's type hints both resolve from the project's node_modules, so the package must live there. If you see Cannot find module 'fluidcad' imported from …, run npm i fluidcad inside the project.
The init.js file
Every FluidCAD project must have an init.js file at its root. It initializes the engine and must be present before any .part.js file can run:
import { init } from 'fluidcad';
export default await init();
Do not modify this file — it is generated by npx fluidcad init and is required for the viewer to work. Project configuration covers what it does and what else lives in the project folder.
The starter file
Open part1.part.js. This is the file that was generated for you, and it is the part the viewport opens on when the server starts:
import { part } from 'fluidcad/core';
export const part1 = part('Part 1', () => {
});
part('Part 1', () => { ... }) declares a named part and exports it as part1. Everything inside the callback builds that part, and the export is what an assembly would later insert(). The callback is empty, so the viewport is too: every sketch and feature you add, from the toolbar or in code, lands inside it and becomes a row in the History panel.
Rename the file and the part to what you are building; Parts covers the convention.
Beyond serve
The same CLI writes STEP, STL, and PNG files without opening the UI, and runs the MCP server that lets AI agents drive your workspace:
npx fluidcad export step # every shape → <entry>.step
npx fluidcad export png --view front --open
See the CLI Reference for every command and flag, or run npx fluidcad --help.
Docker
To keep your projects in one place, on a server or on a machine others on your
network use, run the start screen in a container. The image is
ghcr.io/fluid-cad/fluidcad, built for x64 and ARM64 and tagged with each
release's version (0.0.47) and latest:
docker pull ghcr.io/fluid-cad/fluidcad:latest
The container runs the start screen with a projects folder
at /app/projects: the start screen lists every project in it, and New
Project creates the next one there. Mount a folder of your own on it so the projects outlive the
container. On Linux that folder has to be writable by uid 1000, the user the
container runs as (sudo chown 1000:1000 projects).
The second mount, /home/node/.fluidcad, keeps what FluidCAD remembers between
runs: engines downloaded for projects pinned to another FluidCAD version, recent
projects and previews.
On your own machine
mkdir projects
docker run -d --name fluidcad \
-p 127.0.0.1:3100:3100 \
-e FLUIDCAD_ALLOWED_HOSTS=localhost \
-v "$PWD/projects:/app/projects" \
-v fluidcad-home:/home/node/.fluidcad \
ghcr.io/fluid-cad/fluidcad:latest
docker logs fluidcad
The logs print a sign-in link, http://localhost:3100/?token=…. Open it once in
your browser; FluidCAD then remembers the browser until the container restarts,
which prints a new link. The port is published on 127.0.0.1 only, so no other
machine reaches it, and FLUIDCAD_ALLOWED_HOSTS=localhost makes the link name
localhost rather than the container's own host name.
On a server
Pick the example that matches your network, save it as compose.yaml next to a
projects folder, and run docker compose up -d.
On a network you trust (home LAN, Tailscale), with no sign-in:
services:
fluidcad:
image: ghcr.io/fluid-cad/fluidcad:latest
ports:
- "3100:3100"
environment:
FLUIDCAD_NO_AUTH: "1"
# Every name you open FluidCAD by; any other is refused.
FLUIDCAD_ALLOWED_HOSTS: "fluidcad.example.com,192.0.2.20"
volumes:
- ./projects:/app/projects
- fluidcad-home:/home/node/.fluidcad
restart: unless-stopped
volumes:
fluidcad-home:
Open http://fluidcad.example.com:3100 from any device. Anyone who can reach
that port can read and change every project, and run code on the server through
them, so don't expose it beyond that network.
On a shared network (office, school), behind an HTTPS reverse proxy on the same machine (Caddy, nginx, Tailscale Serve) that forwards WebSocket upgrades:
services:
fluidcad:
image: ghcr.io/fluid-cad/fluidcad:latest
ports:
- "127.0.0.1:3100:3100"
environment:
FLUIDCAD_PUBLIC_URL: "https://fluidcad.example.com"
volumes:
- ./projects:/app/projects
- fluidcad-home:/home/node/.fluidcad
restart: unless-stopped
volumes:
fluidcad-home:
The port is published on 127.0.0.1, so only the proxy reaches it. Sign in with
the link from docker compose logs fluidcad, once in each browser.
FluidCAD is not built to face the internet. Keep it on a network you control, and reach it from outside through a VPN such as Tailscale.
Settings
The container is configured through environment variables, each standing in for
a flag of fluidcad:
| Variable | Flag | Description |
|---|---|---|
FLUIDCAD_ALLOWED_HOSTS | --allowed-host | Comma-separated names the start screen is reached by; any other is refused |
FLUIDCAD_NO_AUTH | --no-auth | 1 drops the sign-in link; needs FLUIDCAD_ALLOWED_HOSTS |
FLUIDCAD_PUBLIC_URL | --public-url | The origin a reverse proxy serves FluidCAD at, such as https://cad.example.com |
Reaching FluidCAD from other machines and Without a sign-in link explain what each one protects against.
Updating
With Compose:
docker compose pull
docker compose up -d
With docker run, pull the new image, remove the container with
docker rm -f fluidcad and run it again with the same command. Your projects
and the fluidcad-home volume stay as they were. To stay on one release
instead of following latest, use its version as the tag:
ghcr.io/fluid-cad/fluidcad:0.0.47.
To build the image yourself from a clone of the
repository, replace image: with
build: . in either Compose file.
Editor setup
FluidCAD runs on its own — no editor required. Every option drives the same engine and the same live 3D viewport; pick whichever fits your workflow.
The built-in editor (recommended)
The desktop app, npx fluidcad and npx fluidcad serve all open the whole product: the 3D
viewport, every interactive modelling tool, and a code editor with completion
driven by the engine's own type declarations — so extrude( shows its signature
and edge().onPlane( completes, always matching the version you're running.
The code editor stays hidden until you ask for it. Open it from the ☰ menu or
with Ctrl+B; it takes width from the left, so the model
narrows rather than being covered. Files are tabs in the top bar, added with
+ — there's no file tree, because the editor already knows about every file
in the workspace.
Any other editor
npx fluidcad serve works alongside any editor too: leave the browser tab on
the viewport and edit .part.js in whatever you prefer — the model rebuilds on
save. Opening the same file in two editors at once is the one thing to avoid.
Next
Getting started builds a butt hinge from an empty part to an animated assembly, one tool per step.