Parametric SVG generator for 3mm laser-cut board card trays / dispensers / boxes.
This project focuses on:
- Correct cavity sizing (inner dimensions are the source of truth)
- Reliable finger joints that always mate (deterministic edge pairing)
- Practical kerf + fit handling for press-fit / friction-fit
- Browser-first workflow via a static Pyodide web app (GitHub Pages)
Current version: v0.6
Live web app:
tray_open_front: open top, lowered/open front, optional scoopdispenser_slot_front: front present with dispense slotwindow_front: front with large window cutout + thumb notchbox_with_lid: box + slip lid
- Base:
BOTTOM,BACK,LEFT,RIGHT, optionalFRONT - Lid (preset
box_with_lid):LID_TOP,LID_BACK,LID_FRONT,LID_LEFT,LID_RIGHT
CUT(red stroke,0.2)ENGRAVE(text/labels, black)
Instead of choosing a “phase” per panel edge, the generator defines mating edge pairs.
Each pair shares one computed FingerPlan (finger count + segment widths). One side uses the plan,
the other side uses the complement (tabs vs slots), so the two edges always match.
Finger count is stable:
Then n is forced odd.
Optional: force fixed counts per joint family:
--finger-count-outer--finger-count-vertical
Parameters:
--kerf-mm: laser kerf (typical ~0.15–0.25mm)--clearance-mm: desired slot–tab clearance (0.00 tight → 0.25 looser)
We model in-plane finger width compensation (so tabs/slots fit after cutting):
- Tabs (external features) shrink after cutting by ~
kerf. - Slots (internal openings) grow after cutting by ~
kerf.
Symmetric drawn-width rule used in the generator:
Widths are normalized per edge so the total length stays exactly
Acceptance example:
python3 cardboxgen_v0_1.py --preset tray_open_front --inner-width 135 --inner-depth 90 --inner-height 225 --thickness 3 --kerf 0.2 --clearance 0.15 --out out.svg
Optional holding tabs (bridges so parts don’t drop out while cutting):
python3 cardboxgen_v0_1.py --preset tray_open_front --inner-width 135 --inner-depth 90 --inner-height 225 --thickness 3 --kerf 0.2 --clearance 0.15 --holding-tabs --tab-width 2 --out out.svg
Calibration SVG (mating strips across clearances):
python3 cardboxgen_v0_1.py --calibration --kerf 0.2 --thickness 3 --out calibration.svg
The web app runs fully in your browser via Pyodide.
- Sync generator into the web folder:
python3 tools/sync_docs.py
- Start a local static server:
python3 -m http.server 8000
- Open:
http://localhost:8000/docs/
python3 examples/generate_examples.py
Outputs in examples/:
tray_open_front.svgdispenser_slot_front.svgbox_with_lid.svgcalibration_mating_strips.svg
Dev deps:
pip install -r requirements-dev.txt
Run:
pytest -q
This repo includes an Actions workflow to deploy docs/ to GitHub Pages.
Steps:
- Push to
mainormaster - GitHub repo → Settings → Pages → Source: GitHub Actions
- Wait for the “Deploy GitHub Pages” workflow to finish
Your site URL will be:
https://<user>.github.io/<repo>/
- The generator version is defined in
__version__in cardboxgen_v0_1.py. - The web app version text lives in docs/app.js (
APP_VERSION) and docs/i18n/ (app.version). - The GitHub Pages app runs the copy in docs/cardboxgen_v0_1.py, so keep it synced.
Release checklist (for a new version):
- Bump
__version__in both generator copies (or bump root + runpython3 tools/sync_docs.py). - Update
APP_VERSIONandapp.versionstrings. - Run tests:
pytest -q - Commit, then tag and publish:
git tag -a vX.Y -m "CardBoxGen vX.Y"git push origin vX.Y- (optional)
gh release create vX.Y --title "vX.Y" --notes-file CHANGELOG.md
See CHANGELOG.md for published versions.