- "app/src/api/engine.ts" - "app/src/embed.tsx" - "app/vite.embed.config.ts" - "app/tsconfig.node.json" GSD-Task: S03/T01 |
||
|---|---|---|
| .bg-shell | ||
| .gsd | ||
| app | ||
| docker | ||
| engine | ||
| .dockerignore | ||
| .gitignore | ||
| docker-compose.yml | ||
| GSD-INITIATE.md | ||
| package-lock.json | ||
| package.json | ||
| README.md | ||
| REQUIREMENTS.md | ||
| tsconfig.json | ||
| vitest.config.ts | ||
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:
- Web App → http://localhost:3000
- Engine API → http://localhost:8000/engine/health
- Interactive API Docs → http://localhost:8000/docs
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 Ramer–Douglas–Peucker 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.