Next.js app for building Eurorack and VCV Rack patch diagrams with PATCH & TWEAK patch symbols.
91SVG symbol assets loaded directly frompublic/symbols- A drag-and-drop patch canvas with pan, zoom, reset view, fit-to-content, and grid snapping
- Tool modes for selection, cable patching, and inline text annotations
- Cable drawing with sound, modulation, gate/trigger, clock, and pitch cable colors
- IndexedDB-backed local patch library plus JSON import/export
- SVG and PNG export
- A bundled sample patch
npm install
npm run dev
npm run buildThis is still a relatively small application from an architecture perspective, but most of the behavior is concentrated in components/PatchEditor.jsx. That file is the main complexity hotspot and the place contributors should read first before making editor changes.
The app is intentionally simple and mostly client-side:
app/page.jsxis the route entry and renders the editorapp/layout.jsxdefines metadata, global CSS, and analyticscomponents/PatchEditor.jsxcontains the editor state machine, canvas interactions, persistence hooks, export logic, and most UIcomponents/SymbolIcon.jsxrenders symbol assets frompublic/symbolslib/symbols.jsis the symbol catalog and filename contract for SVG assetslib/patchLibrary.jswraps IndexedDB for named local patch storagepublic/symbolscontains the official PATCH & TWEAK SVG assets used by the UI and export pipeline
The editor is built around a few core state objects:
nodes: placed symbols on the stageconnections: cables between node ids, each with a signal color/typeview: camera state withx,y, andscale
Each node also stores annotation data:
note: a freeform note attached to the symbol itselfportNotes: optional notes attached totop,right,bottom, andleftpatch points
The stage is a large fixed virtual canvas:
- node positions are stored in world coordinates
- panning and zooming only change the camera transform
- drag/drop, cable creation, marquee selection, export, and note placement all resolve through the same world-coordinate model
Connections are constrained by signal type:
soundruns horizontally fromright -> leftmodulation,gate,clock, andpitchrun vertically fromtop -> bottom
Tool modes are explicit:
Selectis the normal mode for selecting, marquee, and moving nodes- cable color tools activate connection creation for that signal type
Textlets contributors add notes directly to symbols or patch points
Patch files and stored patches share the same basic structure:
{
"version": 1,
"name": "Patch name",
"nodes": [
{
"id": "node-id",
"symbolId": "low-pass-filter",
"x": 288,
"y": 64,
"note": "optional symbol note",
"portNotes": {
"top": "",
"right": "",
"bottom": "",
"left": ""
}
}
],
"connections": [
{
"id": "connection-id",
"from": "node-a",
"to": "node-b",
"color": "sound"
}
],
"view": {
"x": 0,
"y": 0,
"scale": 1
}
}- browser autosave uses
localStorage - named patches are stored in IndexedDB through
lib/patchLibrary.js - JSON import/export is kept for portability and backup
- SVG export builds a standalone document from the current patch state
- PNG export rasterizes that SVG in-browser
components/PatchEditor.jsxcomponents/SymbolIcon.jsxlib/symbols.jslib/patchLibrary.jsapp/layout.jsxapp/globals.csspublic/symbols.github/workflows/deploy-pages.yml
- if you add or rename a symbol, update
lib/symbols.jsand keep the filename inpublic/symbolsaligned with the symbol id - most editor behavior currently lives in one file,
components/PatchEditor.jsx, so changes there should be tested across drag, selection, patching, text mode, save/load, and export - the project currently favors straightforward state and local helper functions over deeper abstraction; if the editor keeps growing, a sensible next refactor would be to split canvas math, export logic, and persistence concerns into separate modules
- because this is a static-exported Next.js app, anything that relies on browser APIs must stay in client components or client-only helpers
- the app expects PATCH & TWEAK SVG files to live in
public/symbolsusing the symbol ids fromlib/symbols.jsas filenames - deployment is handled through GitHub Pages via
.github/workflows/deploy-pages.yml
Symbols used from the free-to-use PATCH & TWEAK patch symbols.
- Symbol overview: https://www.patchandtweak.com/patch-symbols-explained/
- Symbols and licensing/download info: https://www.patchandtweak.com/symbols/