# Kerf — Project Brief
 
**Working Directory:** `/vmPool/r/repos/xpltdco/kerf`
**Deployment Target:** Docker container (self-hostable or cloud-hosted)
**Primary Use Case:** Raster-to-vector conversion engine + 2D sign/patch design canvas + DXF export workflow
 
---
 
## Vision
 
Kerf is a modular, Docker-deployed web application with two distinct but composable layers:
 
1. **The Kerf Engine** — a standalone, API-first raster-to-vector conversion module. This is proprietary IP. It must be built with clean, well-documented input/output contracts so it can be extracted and embedded into future applications independently of this one.
 
2. **The Kerf App** — a full-featured 2D design canvas and sign configuration workflow that consumes the Kerf Engine and delivers a complete end-to-end experience: upload an image or design from scratch, refine the vector output, compose a sign layout, and download a production-ready DXF file.
 
The two layers must remain architecturally decoupled. The Engine is not a feature of the App — the App is a consumer of the Engine.
 
---
 
## Repository Structure
 
```
/vmPool/r/repos/xpltdco/kerf/
  /engine/          ← Kerf Engine (standalone module, own package.json / pyproject)
  /app/             ← Kerf App frontend (React)
  /server/          ← Kerf App backend API (Python/FastAPI)
  /docker/          ← Dockerfiles and compose configs
  /docs/            ← Engine API docs, architecture notes
  README.md
  docker-compose.yml
```
 
---
 
## Part 1: The Kerf Engine
 
### What It Is
 
A self-contained service that accepts raster image input and returns clean vector output. It also accepts existing vector input (SVG) for simplification passes. This is the hardest, most valuable piece of the entire project. Build and validate this first before touching the app canvas.
 
### Processing Pipeline
 
The engine runs a multi-stage pipeline internally:
 
```
Input (raster or vector)
  → Preprocessing (OpenCV)
  → Vectorization (Potrace or VTracer, mode-dependent)
  → Post-processing (path simplification, cleanup)
  → Output (SVG, DXF, or JSON path data)
```
 
#### Stage 1 — Preprocessing (raster inputs only)
Uses OpenCV. The following operations are applied in sequence, each tunable via parameters:
- Grayscale conversion
- Denoise (bilateral filter — preserves edges better than Gaussian for this use case)
- Contrast enhancement (CLAHE — adaptive histogram equalization)
- Threshold (Otsu auto-threshold as default, manual override available)
- Edge detection mode (optional — Canny, for line-art inputs)
- Dilation/erosion (for cleaning up noisy inputs before tracing)
 
#### Stage 2 — Vectorization
Two modes, selectable per request:
 
**Mode A: Potrace** (default)
- Fast, deterministic, excellent for high-contrast logos and line art
- Exposes Potrace tuning parameters: `turdsize`, `alphamax`, `opticurve`, `opttolerance`
- Best for: clean logos, stencils, bold graphics, sign art
 
**Mode B: VTracer**
- Better handling of photographic or noisy inputs, color-aware
- Exposes VTracer params: `colormode`, `hierarchical`, `filter_speckle`, `color_precision`, `layer_difference`, `corner_threshold`, `length_threshold`, `splice_threshold`
- Best for: complex images, multi-color inputs, detailed illustrations
 
The engine selects Mode A by default. The calling application (or user via preset) can override.
 
#### Stage 3 — Post-Processing
- **Path simplification:** Ramer-Douglas-Peucker algorithm, `epsilon` tunable. Also applies to vector-only inputs (simplification-only mode).
- **Island detection:** Identify and flag interior counter paths (letter holes, enclosed shapes) for proper nesting in DXF output
- **Open path detection and repair:** Flag or auto-close open endpoints
- **Node count reporting:** Return node count per path so the UI can warn the user if complexity is too high for practical cutting
 
#### Stage 4 — Output
Supported output formats:
- `SVG` — standard, browser-renderable
- `DXF` — AC1015+ (AutoCAD 2000 compatible), via makerjs or direct entity generation
- `JSON` — raw path data (array of bezier/polyline commands) for consuming applications to render or further process
 
All outputs include metadata:
```json
{
  "format": "svg",
  "path_count": 12,
  "node_count_total": 847,
  "open_paths": 0,
  "warnings": ["High node count — consider increasing simplification"],
  "processing_ms": 340
}
```
 
---
 
### Engine API Contract
 
The Engine exposes a clean HTTP API. This is the stable interface other applications will consume.
 
#### `POST /engine/trace`
Trace a raster image to vector.
 
**Request:** `multipart/form-data`
```
file          — image file (PNG, JPG, BMP, TIFF, WebP)
mode          — "potrace" | "vtracer" (default: potrace)
output_format — "svg" | "dxf" | "json" (default: svg)
preset        — "sign" | "patch" | "stencil" | "detailed" | "custom" (default: sign)
params        — JSON string of override parameters (optional, merges over preset defaults)
```
 
**Response:** `application/json`
```json
{
  "output": "<svg>...</svg>",
  "format": "svg",
  "metadata": { ... }
}
```
 
#### `POST /engine/simplify`
Simplify an existing SVG vector.
 
**Request:** `multipart/form-data`
```
file          — SVG file
epsilon       — float, RDP simplification tolerance (default: 1.0)
output_format — "svg" | "dxf" | "json"
```
 
**Response:** same shape as `/engine/trace`
 
#### `GET /engine/presets`
Returns the full list of available presets and their parameter values.
 
---
 
### Presets
 
Presets are named configurations that set all tuning parameters to sensible defaults for a given application. Users pick a preset first, then fine-tune from there.
 
| Preset | Description | Key Biases |
|---|---|---|
| `sign` | Metal signage, bold text cutouts | High contrast, aggressive simplification, low node count |
| `patch` | Embroidered patches, fabric cutting | Medium detail, smooth curves, closed paths enforced |
| `stencil` | Physical stencil cutting | Simplified, bridges flagged, no islands |
| `detailed` | High-fidelity illustration work | Low simplification, maximum path fidelity |
| `custom` | All params exposed, no defaults applied | — |
 
Presets are stored as JSON config files in `/engine/presets/` so new ones can be added without code changes.
 
---
 
### Engine Testing Checkpoint
 
**Stop here and validate the engine before building anything else.**
 
Prompt the human to:
1. Submit a clean high-contrast PNG logo via the API and confirm the SVG output renders correctly in a browser
2. Submit the same image in `dxf` output mode and open the result in Inkscape or LightBurn — confirm paths are closed and geometry is clean
3. Submit a noisy or photographic input and compare Mode A vs Mode B output
4. Submit an existing complex SVG and run it through `/engine/simplify` — confirm node count drops and shape is preserved
5. Test each preset and confirm the outputs differ meaningfully
 
**Do not proceed to the App canvas until the human explicitly signs off on engine output quality.**
 
---
 
## Part 2: The Kerf App
 
### Overview
 
A React-based single-page application served by a FastAPI backend. Deployed as a Docker container. Functions both as a standalone web app (direct URL access) and as an embeddable component (script tag + div).
 
The App is composed of three views that function as a linear workflow with the ability to jump back:
 
```
[1. Import & Convert] → [2. Design Canvas] → [3. Export]
```
 
---
 
### View 1: Import & Convert
 
This is the Kerf Engine's UI surface. The user arrives here first.
 
#### Import Options
- **Upload raster image** (PNG, JPG, BMP, TIFF, WebP) — primary flow
- **Upload existing vector** (SVG) — routes to simplification mode
- **Start blank** — skip import, go directly to canvas with empty artboard
 
#### Vectorization Controls (shown after upload)
Layout: image preview on the left, controls on the right, live output preview updates as controls change.
 
**Preset Selector**
- Visual cards for each preset (icon + label + one-line description)
- Selecting a preset populates all sliders with preset defaults
- User can then adjust individual sliders freely
 
**Control Sliders / Toggles**
All controls update the preview in real time (debounced, ~300ms):
 
| Control | Type | Description |
|---|---|---|
| Detail Level | Slider | Master control — maps to simplification epsilon. Low = more detail, High = simpler paths |
| Threshold | Slider | Black/white cutoff for rasterized input preprocessing |
| Noise Filter | Slider | Speckle/noise removal aggressiveness |
| Smooth Curves | Slider | Curve fitting vs sharp corners |
| Path Mode | Toggle | Outline only vs filled regions |
| Color Mode | Toggle (VTracer only) | B&W vs color-aware tracing |
| Advanced | Expandable panel | Exposes all raw Potrace/VTracer parameters for power users |
 
**Output Info Bar**
Below the preview — shows live stats: path count, total node count, open path warnings, estimated file size. Color-coded: green (good), yellow (high complexity warning), red (open paths or unusable geometry detected).
 
**Action Buttons**
- "Use This" — accepts current output and advances to the Design Canvas, carrying the vector data forward
- "Re-import" — start over with a new file
 
---
 
### View 2: Design Canvas
 
A 2D design environment. Think Illustrator-lite meets a CNC layout tool. Built with **Konva.js + React** (react-konva).
 
#### Artboard Setup
On first entering the canvas (or when starting blank), the user defines their artboard:
 
**Shape:**
- Rectangle
- Square
- Circle
- Oval/Ellipse
- Shield (common patch shape)
- Pennant
- Custom (width + height freeform)
 
**Dimensions:**
- Width and Height inputs (inches)
- Units toggle: inches / mm
- The artboard renders at a scaled representation — 1:1 real-world proportion maintained
 
#### Canvas Objects
 
All objects are layered, selectable, moveable, resizable, and deletable. Standard selection handles. Multi-select supported.
 
**Text Objects**
- Add text via toolbar button
- Font picker — reads from `/fonts/fonts.json` manifest (same pattern as the sign component: local `.otf` files, dynamic manifest, per-font warning flags)
- Font size, letter spacing, line height
- Alignment: left, center, right
- Text renders using opentype.js for accurate glyph representation
- Toggle: "Convert to paths" — flattens text to vector paths for export (required for DXF)
 
**Imported Vector Object**
- The output from View 1 drops onto the canvas as a vector object
- Fully moveable, scaleable, rotatable
- Can be duplicated
 
**Basic Shape Objects**
- Rectangle / Square
- Circle / Ellipse
- Line — with style variants:
  - Solid
  - Dashed (configurable dash/gap length)
  - Dotted
  - Double line
  - Centerline (long-short-long pattern, common in CAD)
- Stroke weight control
- Fill toggle (filled vs outline only)
 
**Object Panel**
Right sidebar showing layer stack — all objects listed, reorderable via drag, visibility toggle per object, lock toggle per object.
 
#### Canvas Toolbar
Top bar with:
- Select tool
- Text tool
- Shape tools (rectangle, circle, line)
- Zoom in / out / fit to screen
- Undo / Redo (full history stack)
- Grid toggle (snap to grid, configurable grid size)
- Rulers toggle
 
#### Alignment Tools
When one or more objects are selected:
- Align left / center / right (relative to artboard or to selection)
- Align top / middle / bottom
- Distribute horizontally / vertically
- Center on artboard (single click to center both axes)
 
---
 
### View 3: Export
 
Clean, focused export screen. No distractions.
 
#### File Format Selector
- DXF (default — AC1015+)
- SVG
- PNG (raster export at specified DPI)
 
#### DXF-Specific Options
- All text must be converted to paths before DXF export — if any unconverted text objects exist on canvas, warn the user and offer a one-click "Convert All Text to Paths" before proceeding
- Layer assignment — assign canvas objects to named DXF layers (e.g., "cut", "engrave", "score")
- Units: inches or mm
 
#### Filename
- Default pattern: `[project-name]_[width]x[height].[ext]`
- Editable before download
 
#### Download Button
- Label: "Download File"
- Shows spinner during generation
- Triggers browser file download immediately on completion
 
#### Export Validation
Before generating the file, run a pre-export check and display results:
- ✅ All paths closed
- ✅ No open endpoints
- ⚠️ High node count (suggest simplification)
- ❌ Unconverted text objects (block export until resolved)
 
---
 
## Embeddability
 
Kerf App can run in two modes:
 
**Standalone** — accessed directly via URL, full-page experience
 
**Embedded** — dropped into an existing website as a component:
```html
<script src="https://your-kerf-host.com/kerf.js"></script>
<div id="kerf-app"></div>
```
 
In embedded mode:
- Renders within its container div
- All styles scoped (Shadow DOM or prefixed classes)
- Communicates back to host page via postMessage events (e.g., on file download, on export complete)
- No host page dependencies required
 
---
 
## Docker Deployment
 
### Services
```yaml
services:
  kerf-engine:     # Python/FastAPI — vector processing
  kerf-app:        # Node/React — frontend build served by nginx
  kerf-server:     # Python/FastAPI — app backend API
```
 
`kerf-engine` can be deployed independently if consuming apps only need the engine API.
 
### Environment Config
```env
KERF_ENGINE_URL=http://kerf-engine:8000
KERF_FONTS_DIR=/app/fonts
KERF_PRESETS_DIR=/app/presets
KERF_MAX_UPLOAD_MB=20
KERF_OUTPUT_FORMATS=svg,dxf,json
```
 
### Volumes
```
./fonts      → /app/fonts       (font .otf files + fonts.json manifest)
./presets    → /app/presets     (preset JSON configs)
./uploads    → /app/uploads     (temp storage, auto-purged)
```
 
---
 
## Repository README
 
Must cover:
- What Kerf is (app + engine overview)
- Quick start (docker-compose up)
- Engine API reference (endpoint docs, request/response shapes, preset list)
- How to add fonts (drop .otf + update fonts.json)
- How to add presets (drop JSON config into /presets/)
- Embed snippet for host site integration
- Engine standalone usage (for developers consuming just the engine)
- Known limitations
- License
 
---
 
## Build Order
 
Build in this sequence. Do not skip ahead.
 
1. **Kerf Engine** — pipeline, API, presets → **Checkpoint 1: Engine validation (human review)**
2. **Canvas + Artboard** — Konva setup, artboard shape/size, basic object manipulation → **Checkpoint 2: Canvas UI review (human plays with it)**
3. **Text + Font system** — font manifest loading, opentype rendering, path conversion
4. **Import flow** — View 1 UI, Engine integration, vector lands on canvas
5. **Export flow** — View 3 UI, DXF generation, pre-export validation → **Checkpoint 3: DXF opened in LightBurn/Inkscape (human confirms geometry)**
6. **Docker packaging** — compose file, env config, volumes
7. **Embed mode** — script tag delivery, scoped styles, postMessage events → **Checkpoint 4: Embedded in a plain HTML test page (human confirms no style bleed, component works)**
 
---
 
## Testing & Review Checkpoints
 
### Checkpoint 1 — Engine Output Quality
Human must:
- Submit a clean logo PNG → confirm SVG output in browser
- Submit same file as DXF → open in Inkscape or LightBurn, confirm closed paths
- Submit a noisy photo → compare Potrace vs VTracer output
- Submit a complex SVG → run simplification, confirm node count drops
- Test `sign` and `detailed` presets, confirm outputs differ meaningfully
 
**Do not build the App canvas until this is signed off.**
 
### Checkpoint 2 — Canvas UI Review
Human must:
- Create an artboard in each available shape
- Add text, change fonts, resize, move
- Add shapes and lines, test all line styles
- Test undo/redo stack
- Test alignment tools against artboard
 
**Do not build the import/export flows until this is signed off.**
 
### Checkpoint 3 — DXF Export Validation
Human must:
- Design a sign with text and an imported vector object
- Export as DXF
- Open in Inkscape or LightBurn
- Confirm all paths closed, geometry clean, no open endpoints, correct scale
 
**Do not proceed to Docker packaging until this is signed off.**
 
### Checkpoint 4 — Embed Mode Validation
Human must:
- Drop embed snippet into a plain HTML page
- Confirm component renders correctly inside host page
- Confirm no style bleed into surrounding page
- Confirm download works from embedded context
 
---
 
## Key Technical Decisions
 
| Concern | Decision |
|---|---|
| Engine language | Python + FastAPI (OpenCV, Potrace, VTracer all native here) |
| Frontend framework | React + react-konva |
| Canvas library | Konva.js |
| Font rendering | opentype.js — same object reused for preview and DXF path extraction |
| Font loading | Local `.otf` files + `fonts.json` manifest, resolved relative to server font volume |
| DXF generation | makerjs (handles opentype integration and DXF export natively) |
| Raster tracing | Potrace (Mode A) + VTracer (Mode B), OpenCV preprocessing |
| Path simplification | Ramer-Douglas-Peucker |
| Vectorization API | REST over HTTP, JSON responses — engine is stateless |
| Deployment | Docker Compose, engine as independent service |
| Embed delivery | Single bundled JS + scoped CSS via Shadow DOM |
 
---
 
## What Success Looks Like
 
- Engine accepts a dirty raster logo and returns a clean, cuttable SVG or DXF with no manual cleanup required for a typical sign input
- Engine runs as an independent API that a separate app can consume with no knowledge of the Kerf App
- User can upload a logo, tune vectorization with intuitive sliders, place it on a correctly-sized artboard, add business name text, and download a DXF that 1:1 represents their design at real-world scale
- DXF opens in LightBurn with zero geometry errors and is ready to cut
- Entire app ships as a single `docker-compose up` command
- Component can be embedded in a third-party site with two lines of HTML
 
---
 
*Engine first. Everything else is a cakewalk once the engine is solid.*
