A browser-based modular synthesizer. Build patches by connecting modules with virtual cables, the same way you would with a hardware Eurorack system.
npm install
npm run devOpen http://localhost:5173. Click Start to initialize the audio context (required by the browser before any sound can play).
- A browser with
AudioWorkletsupport (Chrome, Edge, Firefox, Safari 14.1+) SharedArrayBufferis required for display analyzer modules (scope,freq spectrum,tuner, andxy scope). The dev server is configured with the necessaryCross-Origin-Opener-PolicyandCross-Origin-Embedder-Policyheaders.
A built-in stress harness is exposed in development builds to baseline large-patch behavior and compare optimizations.
- Start dev server with
npm run dev, open the app, and click Start. - Open browser devtools console.
- Run:
await window.__modsynthPerf?.run()The harness creates a dense patch, runs scripted parameter sweeps + repatching, and returns metrics for frame timing, meter event volume, store update pressure, and worklet error counts. It clears the currently loaded patch as part of setup, so run it only when you are okay replacing the current session state.
Modular synthesis works by connecting individual signal-processing modules together. Each module does one thing: oscillate, filter, amplify, generate an envelope, display a waveform, and more. The patch you build determines the sound.
This instrument runs entirely in the browser. There is no server. Patches autosave to LocalStorage and can be exported and imported as JSON files.
Sampler audio is embedded in patch data, so loaded samples persist across refresh/import/export (larger samples create larger patch files).
- Press
spaceor/anywhere in the rack
This opens the command palette. It defaults to the all tab, and you can switch tabs for common, most used, or specific module categories, then press enter to place the highlighted module at your cursor position.
Type in the search field at any time to search across all modules by name, category, or id.
- Drag from any output port to start drawing a cable
- Release on an input port to complete the connection
- Cables are color-coded by signal type
- Right-click any cable to disconnect it
- Drag an existing cable's input end to re-patch it
- Audio <-> cv: allowed. Since all signals are the same data type under the hood (
Float32Arrayat audio rate), mixing them enables audio-rate modulation and other expressive techniques. - Gate <-> trigger: allowed. Both carry on/off signals and are electrically compatible.
- Audio/cv -> gate/trigger: not allowed. These signal families are logically incompatible.
There are 55 user-visible modules in the command palette. While drilled into a subpatch, you also get 2 internal proxy modules (in, out) used to expose container ports.
- vco - audio-rate oscillator with
sine,saw, andpulseoutputs, plus v/oct, fm, and pulse-width modulation inputs. - wavetable vco - morphing wavetable oscillator with bank cycling (
classic,hollow,digital,vocal), live wavetable display that follows wave-position modulation, v/oct + fm inputs, and amultcontrol (1-4) that multiplies waveform cycles (harmonic/octave shift behavior). - lfo - low-frequency modulator with
sine,saw,pulse, andtrianglecv outputs and cv-modulatable rate. - chaos - lorenz-attractor chaos source with correlated
x,y,zcv outputs. - noise - white, pink, and brown noise outputs.
- fm op - single fm operator with ratio, index, self-feedback, and phase-modulation input.
- pluck - karplus-strong plucked-string voice with trigger excitation, v/oct pitch, and optional external excitation audio.
- resonator - resonant string/body model excited by trigger or audio, with pitch cv support.
- sampler - sample player with gate + v/oct inputs, playback modes (
one-shot,gate,retrigger), reverse playback, loopable start/end region controls, waveform display, and moving playhead.
- button - manual gate + 4ms trigger generator.
- clock - integer bpm clock (
20-1000) with swing, reset, gate output, and 4ms trigger output. - clock div - clock divider with integer division factor (
2-16), reset, and output activity indicator. - euclid - euclidean trigger sequencer with
steps,pulses,offset, accent output, and output activity indicator. - cv seq - 4-pattern, 16-step cv/gate sequencer with draggable step voltages (
-2..2), global step length (1-16), pattern cycle length (1-4), and trigger-advanced pattern playback. - note seq - 4-pattern, 16-step pitch sequencer with draggable semitone steps (
-24..24), per-step velocity bars, global step length (1-16), pattern cycle length (1-4), and trigger-advanced pattern playback. - drum seq - 4-lane, 4-pattern, 16-step trigger sequencer with 808-style per-step toggles, per-pattern length (
1-16), cycle span (1-4), and four trigger outputs for drum/sample voices. Reset snaps to step 1 and immediately emits that step's triggers. - keyboard - computer-keyboard note entry (
a w s e d f t g y h u j k, octave viaz/x) with pitch, gate, and trigger outs. - cv - constant cv source (
-1to+1). - chord dice - generated 4-chord progression source with clock step input and root transposition input.
- adsr - attack/decay/sustain/release envelope with gate input.
- ar - attack/release envelope with
eoctrigger output at release end. - ad - attack/decay one-shot envelope with
eoctrigger output.
- vcf - multimode state-variable filter (lowpass, highpass, bandpass) with cv-modulated cutoff/resonance and envelope input.
- vca - cv-controlled amplifier for amplitude shaping (
gainsets base level;gaincv input adds modulation on top). - compressor - compressor with sidechain input, threshold/ratio/attack/release/makeup/knee/mix controls, gain-reduction cv output, and a scrolling input/threshold/gain-reduction level display.
- env flwr - envelope follower that converts audio level into cv with attack/release control.
- reverb - algorithmic reverb with
roomandplatemodes plus mix/decay/damping control. - granulator - live-input granular processor with
hybrid/ambient/glitchmodes, freeze gate, position/pitch cv, reverse/jitter/shape controls, tone+feedback shaping, crush texture, and dry/wet mix. - feedback delay - delay with cv time modulation, feedback, tone filtering, and wet/dry mix.
- tape delay - character delay with wow/flutter modulation, tone, drive, feedback, and mix.
- flanger - flanger/chorus module with rate, depth, feedback, and mix.
- wavefold - wavefolder with gain, symmetry, and fold cv input.
- ring mod - ring modulator with dry/wet mix.
- crush - bitcrusher with bit-depth and sample-rate reduction.
- dist - multi-mode distortion (
soft,hard,fuzz) with drive, tone, and output level.
- mixer - 4-channel mixer with per-channel level and mute, master level, master mute, and dual output metering.
- mult - 1-to-4 cv splitter.
- atten - attenuverter for cv scaling and inversion.
- s&h - sample-and-hold (sample cv on gate rising edge; front-panel hold button works when gate input is unpatched, and patched gate overrides the button).
- quant - cv quantizer for musical scales.
- octave - octave transposer for v/oct cv.
- chord - chord voice generator from one root cv input (four v/oct outputs).
- panner - constant-power mono-to-stereo panner with cv input.
- prob gate - probabilistic gate router with pass and skip outputs.
- comparator - compares two cv inputs and outputs
gt,lt,eqgates. - logic - gate logic (
and,or,xor,not). - slew - rise/fall slew limiter for cv smoothing and glide.
- delay - clean delay line with cv-modulated delay time (no feedback stage).
- mute - one-button audio mute utility.
- note - text note panel saved with the patch.
- output - final stereo output module (left/right in, meter, master level).
- scope - real-time waveform scope.
- freq spectrum - log-frequency spectrum analyzer.
- tuner - note + cents tuner display with stabilized pitch averaging.
- xy scope - x/y oscilloscope for lissajous-style signal visualization with
scaleandfadecontrols (fadecontrols trail persistence).
Subpatches let you group related modules into a reusable, named container. The container appears as a single panel on the rack with exposed ports and optional macro knobs.
Creating a subpatch
- Select two or more modules -> right-click empty rack space -> Group as subpatch (wraps the selection into a container, preserving internal cables)
- Open the command palette -> subpatch (creates an empty container you can drill into and build from scratch)
Editing a subpatch
- Double-click a container to drill into it. The breadcrumb at the top shows the current context; click any segment or press
escto exit. - Inside the subpatch, add modules normally with
spaceor/. - Exposing ports: place an in or out module inside the subpatch. Its ports appear on the container face. Click the label to rename; click the type badge to cycle audio -> cv -> gate -> trigger.
- Exposing macros: right-click any knob while inside a subpatch -> Expose as macro. A macro knob appears on the container face. Right-click again -> Remove macro to unexpose it.
Library + reuse
- Save subpatch to library: right-click a subpatch container -> Save to library
- Insert saved subpatch: click Presets in the top bar, search, then click or press
enterto insert - Delete saved preset: open Presets, then click the
✕next to an entry - Ungroup a container: right-click a subpatch container -> Ungroup
Linked instances
All instances of the same subpatch definition share the same internal structure. Editing the internals of one (while drilled in) updates all instances when you exit.
Naming
Double-click the name in the container header to rename it.
Click tutorials in the top bar to open guided lessons directly in the rack (shown at root level; hidden while drilled into a subpatch).
On first open (after pressing start), a welcome modal appears with a shortcut to open beginner tutorials immediately.
- Two modes
beginner: strict, step-by-step guidanceveteran: challenge goals with looser validation
- Built-in lesson pack (6 active)
- beginner:
first voice,envelope shaping,clock + sequencer,feedback safely,subpatch macros - veteran:
challenge: kick voice in 6 modules
- beginner:
- Step behavior
- each step asks for one action (add module, cable connection, param range, etc.)
- progress auto-validates from live store state
- each step includes contextual hints, show me guidance text, and try for me auto-perform
- Spotlight guidance
- active tutorial steps highlight relevant modules, ports, and controls in-place
Starting a lesson clears the current patch after confirmation. Lesson completion badges are saved in LocalStorage.
| Action | How |
|---|---|
| Add module | space or / on rack |
| Delete selected modules | delete or backspace |
| Select module | Click on it |
| Select multiple modules | Click-drag empty rack area |
| Select all visible modules | cmd/ctrl + a |
| Add to selection | Hold shift while marquee-selecting |
| Copy selected modules | cmd/ctrl + c |
| Paste modules | cmd/ctrl + v |
| Undo | cmd/ctrl + z or top bar ↩ |
| Redo | cmd/ctrl + shift + z or top bar ↪ |
| Move module(s) | Drag selected module header (free drag; snaps on release; viewport auto-pans near edges) |
| Drag a cable | Mousedown on any port |
| Disconnect a cable | Right-click the cable |
| Rename patch | Click the patch name in the top bar |
| New patch | Top bar -> New |
| Export patch | Top bar -> Export |
| Import patch | Top bar -> Import |
| Open subpatch presets | Top bar -> Presets |
| Settings | Gear icon in the top bar |
| Zoom in/out | Pinch trackpad or cmd/ctrl + scroll |
| Reset zoom | Click zoom percent in the top bar |
| Group modules as subpatch | Select >=2 modules -> right-click empty space |
| Ungroup subpatch | Right-click subpatch container -> Ungroup |
| Enter subpatch | Double-click container header |
| Exit subpatch | esc or click breadcrumb |
| Expose port in subpatch | Add in / out module while drilled in |
| Expose knob as macro | Right-click knob while drilled in -> Expose as macro |
| Save subpatch preset | Right-click subpatch container -> Save to library |
Module placement is clamped to the rack workspace bounds, snapped to the grid on placement, and overlap-validated (including add, drag, paste, and subpatch container placement).
- Cable tautness - controls how much cables sag between ports (
0= loose,1= taut) - Tooltips - toggle port tooltips on hover
- Theme - 11 themes total: base (
dark,light), dark variants (forest,abyss,volcanic), light variants (braun), stylized variants (synthwave,ice,arcade), and monochrome variants (slate,paper)
- React + TypeScript
- Vite
- Zustand (state management)
- Web Audio API / AudioWorklet (audio processing)
- SVG (cable rendering)