Desktop tracing tool for drawing SVG line overlays on top of reference images, then saving the result as:
- a
.lines.jsonproject file for the editor - a generated
.tsxReact component for app consumption
The app runs as Tauri + React + TypeScript and uses vite+ for the web toolchain.
brew install whaleen/tap/linesThe app includes an auto-updater — when a new version is available it will prompt you to install and relaunch without leaving the app.
Taurifor the desktop shell, file I/O, and updaterReactfor the editor UITypeScriptfor the document model and generatorsZustandfor editor stateVite+for dev, build, lint, format, and type checksRadix UIfor tooltips and context menus
- Open any folder as a project; components are saved to the project's
components/lines/directory - Load a reference image into the canvas; control its opacity with the topbar slider
- Trace open or closed line paths — click to place points or press+drag for freehand
- Select paths and points; shift+click for multi-select, ⌘A to select all
- Drag points (node edit) or drag entire paths (select tool)
- Copy, cut, paste, and duplicate paths
- Control z-order (bring forward/back, send to front/back)
- Group paths (⌘G)
- Right-click context menu for duplicate and delete
- Edit fill and stroke color per path using shadcn CSS variable tokens or explicit values
- Edit stroke width and path opacity; style persists to new paths
- Toggle paths open/closed
- Manage layers — visibility, lock, opacity, rename, reorder
- Resize canvas with a 3×3 anchor grid dialog (paths and image shift to match)
- Crop canvas — drag handles to define region, Enter to commit
- Code view tab shows the generated component source in real time
- Auto-save: saves both
.lines.jsonand.tsxwhenever the document is dirty
The reference image is an editor-only layer. The generated component contains only the traced SVG output.
Each traced asset produces two files in the project's components/lines/ directory:
something.lines.json— editor source of truthsomething.tsx— app-facing React component
The generated component uses shadcn CSS variable references (hsl(var(--foreground)) etc.) and hot-reloads inside any React frontend.
| Key | Action |
|---|---|
P / D |
Draw (pen) tool |
V |
Select / Move tool |
A |
Node edit tool |
C |
Crop tool |
Enter |
Finish active path / commit crop |
Escape |
Cancel active path / cancel crop |
Delete / Backspace |
Delete selected path or point |
⌘A |
Select all paths |
⌘D |
Duplicate selected path(s) |
⌘C / ⌘X / ⌘V |
Copy / Cut / Paste |
⌘G |
Group selected paths |
⌘] / ⌘[ |
Bring forward / Send backward |
⌘⇧] / ⌘⇧[ |
Bring to front / Send to back |
Space + drag |
Pan canvas |
| Scroll | Zoom |
Primary web toolchain commands:
npm run dev
npm run build
npm run check
npm run check:fixDesktop commands:
npm run desktop:dev
npm run desktop:build- Tauri uses
vp devandvp buildinternally viasrc-tauri/tauri.conf.json. - The editor document model lives in
src/types/lines.ts. - The generated React component output is produced by
src/lib/component-generator.ts. - File writes and project detection are handled by Tauri commands in
src-tauri/src/lib.rs. - SVG coordinate mapping uses
createSVGPoint().matrixTransform(getScreenCTM().inverse())for pixel-accurate pointer conversion at any zoom/pan level.
Releases are built and published via GitHub Actions:
- Push a version tag (
git tag v1.2.3 && git push origin v1.2.3) release.ymlbuilds a signed universal macOS binary and publishes a GitHub releaseupdate-manifest.ymlfires on the published event and writeslatest.jsonto the homebrew-tap- Running instances pick up the update on next launch
Signing requires TAURI_SIGNING_PRIVATE_KEY and TAURI_SIGNING_PRIVATE_KEY_PASSWORD secrets in the repo.
vp check
vp build
cargo check --manifest-path src-tauri/Cargo.toml@vitejs/plugin-react currently emits a Vite+ warning about deprecated esbuild-oriented options during vp build and vp check. The app still builds and checks cleanly. I left it in place because the current @vitejs/plugin-react-oxc package metadata does not yet declare Vite 8 compatibility.