SVG-to-potrace laser cut path engine
Find a file
2026-03-26 06:46:20 +00:00
.bg-shell init: GSD project scaffolding for Kerf — 3 milestones, requirements, decisions 2026-03-26 03:55:59 +00:00
.gsd docs: Rewrote README.md with 8 sections: quick start, repo structure, a… 2026-03-26 06:46:20 +00:00
app feat: Built complete ExportView with DXF/SVG/PNG format selector, valid… 2026-03-26 06:29:21 +00:00
docker feat: Create Dockerfile.app (node→nginx multi-stage), nginx.conf (SPA +… 2026-03-26 06:43:59 +00:00
engine feat: Extended generate_dxf() with units/scale_factor/layer_map params… 2026-03-26 06:17:06 +00:00
.dockerignore feat: Created multi-stage Dockerfile.engine with healthcheck endpoint;… 2026-03-26 04:49:38 +00:00
.gitignore chore: Created engine/ Python project with FastAPI skeleton, all depend… 2026-03-26 04:07:16 +00:00
docker-compose.yml feat: Create Dockerfile.app (node→nginx multi-stage), nginx.conf (SPA +… 2026-03-26 06:43:59 +00:00
GSD-INITIATE.md init: GSD project scaffolding for Kerf — 3 milestones, requirements, decisions 2026-03-26 03:55:59 +00:00
package-lock.json feat: Create Dockerfile.app (node→nginx multi-stage), nginx.conf (SPA +… 2026-03-26 06:43:59 +00:00
package.json feat: Create Dockerfile.app (node→nginx multi-stage), nginx.conf (SPA +… 2026-03-26 06:43:59 +00:00
README.md docs: Rewrote README.md with 8 sections: quick start, repo structure, a… 2026-03-26 06:46:20 +00:00
REQUIREMENTS.md init: GSD project scaffolding for Kerf — 3 milestones, requirements, decisions 2026-03-26 03:55:59 +00:00
tsconfig.json feat: Create Dockerfile.app (node→nginx multi-stage), nginx.conf (SPA +… 2026-03-26 06:43:59 +00:00
vitest.config.ts feat: Create Dockerfile.app (node→nginx multi-stage), nginx.conf (SPA +… 2026-03-26 06:43:59 +00:00

Kerf

Modular raster-to-vector conversion engine paired with a 2D sign and patch design canvas. Upload a raster image (PNG, JPEG, BMP), trace it into clean vector paths using Potrace or VTracer, and export as SVG or DXF — ready for CNC routers, vinyl cutters, laser engravers, and embroidery machines.

Quick Start

docker compose up -d

Once both services are healthy:

Check service health:

docker compose ps

Tear down:

docker compose down

Repository Structure

engine/              Kerf Engine — standalone Python/FastAPI vectorization API
  api/               API route definitions
  pipeline/          Preprocessing, vectorization, and post-processing stages
  output/            SVG, DXF, and JSON output generators
  presets/           Built-in preset configurations (JSON)
  tests/             Engine test suite (pytest)
app/                 Kerf App — React/TypeScript design canvas (Vite + Konva)
  src/               Application source code
  public/            Static assets including bundled fonts
docker/              Dockerfiles and nginx configuration
  Dockerfile.engine  Multi-stage build for the engine (Python 3.11)
  Dockerfile.app     Multi-stage build for the app (Node 22 → nginx 1.27)
  nginx.conf         SPA routing + /engine reverse-proxy
docker-compose.yml   Full-stack orchestration with healthchecks

Engine API Reference

The engine exposes four endpoints under the /engine prefix. All endpoints accept and return JSON unless otherwise noted.

GET /engine/health

Healthcheck endpoint for container orchestration.

Response:

{ "status": "ok" }

GET /engine/presets

List all available presets and their parameter values.

Response:

{
  "presets": {
    "sign": { "name": "sign", "description": "Metal signage, bold text cutouts", "..." : "..." },
    "patch": { "name": "patch", "description": "Embroidered patches, fabric cutting", "..." : "..." }
  }
}

POST /engine/trace

Convert a raster image to vector output through the full preprocessing → vectorization → post-processing pipeline.

Content-Type: multipart/form-data

Field Type Default Description
file file (required) Raster image (PNG, JPEG, BMP)
mode string from preset Vectorization engine: potrace or vtracer
output_format string svg Output format: svg, dxf, or json
preset string sign Preset name (see Presets)
params string {} JSON string of parameter overrides

Example — trace with the sign preset:

curl -X POST http://localhost:8000/engine/trace \
  -F file=@logo.png \
  -F preset=sign \
  -F output_format=svg

Example — trace with custom parameters:

curl -X POST http://localhost:8000/engine/trace \
  -F file=@photo.jpg \
  -F preset=detailed \
  -F mode=vtracer \
  -F 'params={"filter_speckle": 4, "epsilon": 0.3}'

Response (SVG/JSON formats):

{
  "output": "<svg ...>...</svg>",
  "format": "svg",
  "metadata": {
    "format": "svg",
    "path_count": 12,
    "node_count_total": 483,
    "open_paths": 0,
    "island_count": 2,
    "warnings": [],
    "processing_ms": 142.57
  }
}

Response (DXF format): Raw DXF bytes with Content-Type: application/dxf and metadata in the X-Kerf-Metadata response header.

POST /engine/simplify

Simplify an existing SVG using RamerDouglasPeucker path simplification. Optionally export to DXF with unit and scale control.

Content-Type: multipart/form-data

Field Type Default Description
file file (required) SVG file to simplify
epsilon float 1.0 RDP simplification tolerance (higher = fewer points)
output_format string svg Output format: svg, dxf, or json
units string none DXF unit metadata: inches or mm
scale_factor float 1.0 DXF coordinate scale factor

Example — simplify and export to DXF in millimeters:

curl -X POST http://localhost:8000/engine/simplify \
  -F file=@drawing.svg \
  -F epsilon=2.0 \
  -F output_format=dxf \
  -F units=mm \
  -F scale_factor=25.4

Presets

Presets bundle tuned parameter sets for each pipeline stage — preprocessing, vectorization, and post-processing — optimized for specific use cases.

Preset Description Mode Epsilon Notes
sign Metal signage, bold text cutouts potrace 2.5 Aggressive denoising, auto-close enabled
patch Embroidered patches, fabric cutting potrace 1.0 Moderate smoothing, fine detail retention
stencil Physical stencil cutting potrace 3.0 Heavy simplification, fixed threshold at 128
detailed High-fidelity illustration work potrace 0.5 Minimal smoothing, preserves fine curves
custom All params exposed, no defaults potrace Pass all parameters explicitly via params

Use the params field on /engine/trace to override any preset value. For example, to use the sign preset but switch to VTracer mode:

curl -X POST http://localhost:8000/engine/trace \
  -F file=@image.png \
  -F preset=sign \
  -F 'params={"mode": "vtracer"}'

Font System

The web app bundles three fonts for text-to-path conversion, enabling text elements to be converted to SVG outlines for cutting/engraving:

Font File
Roboto Roboto-Regular.ttf
Open Sans OpenSans-Regular.ttf
Lato Lato-Regular.ttf

Fonts are parsed client-side using opentype.js and converted to SVG path data with configurable font size and letter spacing. The conversion handles glyph positioning, coordinate system flipping, and path assembly — no server round-trip required.

Engine Standalone Usage

The engine runs independently of the web app. Use it as a standalone API service or build just the engine Docker image:

Docker (standalone):

docker build -f docker/Dockerfile.engine -t kerf-engine .
docker run -p 8000:8000 kerf-engine

Local development (Python):

cd engine
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"
uvicorn main:app --host 0.0.0.0 --port 8000 --reload

API docs are available at http://localhost:8000/docs (Swagger UI) and http://localhost:8000/redoc (ReDoc).

Development

Engine (Python)

cd engine
python -m venv .venv
source .venv/bin/activate
pip install -e ".[dev]"

# Run the API server with auto-reload
uvicorn main:app --host 0.0.0.0 --port 8000 --reload

# Run tests
pytest

System dependencies for pypotrace: libpotrace-dev, libpotrace0, libagg-dev (Debian/Ubuntu).

App (React/TypeScript)

npm install
npm run dev --workspace=app

The Vite dev server proxies /engine/* requests to http://localhost:8000 — start the engine first for full functionality.

Full Stack (Docker Compose)

docker compose up --build

The app is served on port 3000 with nginx reverse-proxying /engine/* to the engine container.

Known Limitations

  • Single-image processing — the engine processes one image per request; batch endpoints are not yet available.
  • Binary vectorization only — both Potrace and VTracer operate in binary (black/white) mode; color/multi-layer tracing is not supported.
  • No authentication — the API is open; add a reverse proxy with auth for production deployments.
  • Font selection — the app ships with three bundled fonts; custom font upload is not yet supported.
  • DXF fidelity — DXF export covers basic polyline geometry; advanced CAD features (layers, blocks, hatches) are not included.