Web tool for designing nickel/copper busbars over cylindrical-cell battery packs (21700, 18650) in hex holders. Flask + build123d backend exports STEP/DXF/SVG; vanilla JS frontend with live preview, multi-project SQLite persistence, snapshot history. Deploy scripts in deploy/ (proxmox-lxc.sh, install.sh, update.sh).
Busbar Designer
Web tool for designing nickel/copper busbars over cylindrical-cell battery packs (21700, 18650, ...) built with hex-shaped cell holders.
Workflow:
- Import cell-center coordinates (paste from OpenSCAD console, CSV, JSON — or generate from
cell_dia / wall / rows / cols). - View cells on a 2D canvas at real mm scale.
- Click cells to select; group selected cells into named busbars (parallel groups), then chain busbars in series.
- Each busbar is drawn as a strip of configurable width with circular pads + welding-window holes over each cell center.
- Export busbar geometry to STEP (mandatory), plus DXF and SVG for laser/waterjet cutting.
Quick start
Requires Python 3.10+. On Windows / PowerShell:
cd busbar-designer
python -m venv .venv
.\.venv\Scripts\Activate.ps1
pip install -r requirements.txt
python app.py
Then open http://localhost:5000 in your browser.
First-time install pulls build123d (~ 200 MB; bundles OpenCASCADE via OCP) and may take several minutes.
Linux / macOS
cd busbar-designer
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
python app.py
Geometry source of truth
All cell-center math matches Addy's Hex-Cell-Holder/hex_cell.scad:
| Variable | Formula | 21700 default |
|---|---|---|
hex_w |
cell_dia + 2*wall |
22.8 mm |
hex_pt |
hex_w / 2 / cos(30°) |
13.164 mm |
opening_dia |
cell_dia − 2*cell_top_overlap |
15.2 mm |
| row pitch (Y) | 1.5 * hex_pt |
19.746 mm |
| col pitch (X) | hex_w |
22.8 mm |
rect row shift |
0 (even) / 0.5*hex_w (odd) |
11.4 mm |
Import formats
The importer auto-detects:
- OpenSCAD ECHO:
ECHO: "Cell 1: x = 0.0, y = 0.0"(paste straight from console).- If your
hex_cell.scaddoesn't print these, dropscad_snippet.scad(in this repo) at the bottom of the file.
- If your
- CSV:
index,x,y(header optional). - JSON:
[{"id":1,"x":0,"y":0}, ...]or[[x,y], ...]. - Generator tab: enter
cell_dia / wall / rows / cols / pack_style— coordinates are computed with the exact OpenSCAD formulas.
Persistence
State is stored in a SQLite file (data/busbar.db by default; override with BUSBAR_DB env var):
| Table | What |
|---|---|
projects |
Full editor state (cells + busbars + params) per project |
presets |
Named param bundles you save from the params panel |
snapshots |
Auto-history per project; max SNAPSHOT_RETENTION (default 20) kept |
REST API (all JSON):
| Method | Path | What |
|---|---|---|
| GET | /api/projects |
list projects |
| POST | /api/projects |
create {name, data} |
| GET | /api/projects/{id} |
full project |
| PUT | /api/projects/{id} |
update {name?, data?, snapshot?, note?} |
| DELETE | /api/projects/{id} |
delete (cascades to snapshots) |
| GET | /api/projects/{id}/snapshots |
list snapshots |
| GET | /api/snapshots/{sid} |
full snapshot |
| POST | /api/snapshots/{sid}/restore |
roll project back |
| GET | /api/presets |
list presets |
| POST | /api/presets |
create {name, params} |
| PUT | /api/presets/{id} |
update |
| DELETE | /api/presets/{id} |
delete |
UI behaviour:
- Active project ID is in the URL:
?p=42. Bookmark or open from another device → same state. - Auto-save fires 1.5 s after the last change. The first save in any 60 s window also creates a history snapshot.
- "History" button shows the snapshot list with a Restore action.
- Presets are saved server-side and apply to any project with one click.
Backup: the entire DB is one file. Copy data/busbar.db (or the data/ folder in Docker) for offline backup.
Export
| Format | Use | Backend |
|---|---|---|
| STEP | CAD (FreeCAD, Fusion, SolidWorks) | build123d → OpenCASCADE |
| DXF | Laser cutter / CNC (2D) | build123d → ezdxf |
| SVG | Quick preview, illustrator | build123d |
STEP files are written as flat 3D faces (not solids) so a fab shop can lay them out before cutting. If you need a thick solid (e.g., 0.2 mm nickel) toggle "Extrude busbars" — the backend will extrude each strip to the configured thickness.
Project layout
busbar-designer/
├── app.py # Flask server: static files + /api/export/{step,dxf,svg}
├── busbar_export.py # build123d → STEP / DXF / SVG
├── requirements.txt
├── scad_snippet.scad # paste into hex_cell.scad to echo per-cell coordinates
├── CLAUDE.md # architecture notes for Claude / future contributors
├── tests/
│ └── test_export.py
└── static/
├── index.html
├── styles.css
└── js/
├── app.js
├── importer.js
├── viewport.js
├── groups.js
├── geometry.js
└── exporter.js
Deploy to a home server
Three supported paths — pick one. Full docs in deploy/README.md.
Option A — Proxmox VE (one-liner from the PVE host)
bash -c "$(curl -fsSL https://gitea.local/me/busbar-designer/raw/branch/main/deploy/proxmox-lxc.sh)"
Creates a Debian 12 LXC and installs the service inside. Whiptail prompts for container ID, hostname, disk/CPU/RAM, network, repo URL, branch. Defaults to 4 GB disk, 2 cores, 1 GB RAM, dhcp.
Option B — Inside an existing Debian/Ubuntu (LXC, VM, bare)
REPO_URL=https://gitea.local/me/busbar-designer.git \
bash -c "$(curl -fsSL https://gitea.local/me/busbar-designer/raw/branch/main/deploy/install.sh)"
Sets up the venv, installs deps, drops a systemd unit, starts the service. Update with bash /opt/busbar-designer/deploy/update.sh.
Option C — Docker
git clone <repo> busbar-designer && cd busbar-designer
mkdir -p data
docker compose up -d --build
The data/ folder is mounted into the container at /app/data so the SQLite DB survives docker compose down.
Reverse proxy (optional)
If you want it behind your existing nginx / Caddy / Traefik:
location / {
proxy_pass http://127.0.0.1:5000;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_read_timeout 120s; # STEP export can take a few seconds
client_max_body_size 5m;
}
For Caddy:
busbar.example.com {
reverse_proxy 127.0.0.1:5000
}
Security
The app has no authentication. Either:
- expose only on your LAN (default), or
- put it behind an authenticating reverse proxy (Caddy
basic_auth, Authelia, Pocket-ID, etc.).
Troubleshooting
pip install build123dfails on Windows / Python 3.13 — the prebuilt OCP wheels lag the latest Python release. If yourpython --versionis 3.13, install Python 3.12 from python.org and use it for the venv:py -3.12 -m venv .venv.- STEP opens empty in FreeCAD — make sure at least one busbar exists and contains ≥ 1 cell. The exporter writes only assigned busbars.
- Port 5000 in use — set
PORT=5050 python app.py.
License
MIT.