A visual planar linkage design and synthesis tool. Build mechanisms interactively on a canvas, simulate their motion, and synthesize 4-bar linkages from constraints.
- Interactive canvas -- draw links, place joints (revolute, prismatic, tracker), snap connections, animate motion
- Mechanism synthesis -- path generation, function generation, and motion generation for 4-bar linkages
- Simulation -- run kinematic simulations and visualize coupler trajectories (loci)
- Undo/redo -- full history (50 states) via Zundo
- Example library -- browse and load prebuilt mechanisms
- Keyboard shortcuts -- mode selection and common operations
React 18, TypeScript, Zustand, Konva (react-konva), TanStack React Query, Vite
A static build is deployed at https://hugofara.github.io/pylinkage-editor/.
There is no Python server behind it: the page runs the same
pylinkage_editor_server FastAPI app inside the browser with
Pyodide (a Web Worker, see src/pyodide/). The first
visit downloads the Python runtime plus numpy and scipy (about 30 MB, cached
by the browser afterwards); while that loads, the bundled examples
(src/data/examples.json, regenerated by server/scripts/dump_examples.py)
and the Design tab's client-side solver already work. Long optimizations run
slower than on the native server, and DXF/STEP export (build123d) is not
available there.
To reproduce the deployed page locally:
npm run build:wheel # package the server for the browser (needs uv)
npm run build && npm run preview
npm run test:wasm # run the server under Pyodide in Node, hit the main routesSet VITE_WASM_BACKEND=off at build time to ship the frontend without the
in-browser backend.
The editor is a browser frontend plus a Python backend that runs pylinkage. Both live in this repository. You need Node and uv.
npm install
npm run server # Python backend on http://localhost:8000
npm run dev # frontend on http://localhost:5173, in another terminalThe dev server proxies /api requests to the backend. See
server/README.md for configuration, optional CAD export
dependencies, and the route list.
| Command | Description |
|---|---|
npm run dev |
Start frontend dev server |
npm run server |
Start Python backend (cd server && uv run pylinkage-editor-server) |
npm run build:wheel |
Build the server wheel into public/wheels/ for the in-browser backend |
npm run test:wasm |
Run the server under Pyodide in Node and exercise the main routes |
npm run build |
Type-check and build for production |
npm run preview |
Preview production build |
npm run lint |
Run ESLint |
npm run type-check |
Run TypeScript type checking |
server/ # Python backend (FastAPI + pylinkage), see server/README.md
src/
├── api/ # Backend API client (CRUD, simulation, synthesis) and backend probe
├── data/ # Example library dumped from the server for the static demo
├── pyodide/ # In-browser backend: Pyodide worker running the FastAPI app
├── components/
│ ├── canvas/ # Interactive Konva canvas and toolbar
│ ├── examples/ # Example browser panel
│ ├── layout/ # App shell, sidebar, tab bar
│ ├── sidebar/ # Animation controls, link list, example loader
│ └── synthesis/ # Synthesis canvas and sidebar
├── hooks/ # Keyboard shortcuts, simulation streaming
├── stores/ # Zustand stores (mechanism, editor, synthesis)
├── types/ # TypeScript type definitions
└── utils/
The editor uses a link-first data model: links are primary entities and joints are derived from their connections. The frontend communicates with the Python backend in server/ over /api for computationally intensive tasks like synthesis and simulation; the backend is a thin FastAPI layer over pylinkage.
State is managed with Zustand stores split by concern:
- mechanismStore -- links, joints, mechanism data, undo/redo
- editorStore -- UI mode, selection, canvas state
- synthesisStore -- synthesis inputs and results