Building a pedal in an afternoon
Apr 9, 2026
The pitch on the /build page is that you can make a working pedal in an afternoon if you know some JavaScript. That is the kind of claim that deserves a stopwatch rather than an adjective, so here is one afternoon, timed, with the mistakes left in.
The target: a bitcrusher. Sample-rate reduction and bit-depth quantization, two knobs, a dry/wet. Small enough to finish, real enough to use.
00:00 — scaffold
The CLI writes a folder with a kernel, a parameter schema, a minimal UI, and a plugin.config.json. Nothing in there is clever. The kernel it generates is a gain stage, which compiles and runs, and that matters more than being interesting — you want a working baseline before you start breaking things.
First thing I did was run the generated tool in the browser dev server and play the guitar take through it. Twenty seconds in, audio. That is the loop you stay in for the rest of the afternoon.
00:25 — the kernel
The bitcrusher itself is about fifteen lines of restricted TypeScript. Hold a sample, count down a phase accumulator, and only update the held value when the counter wraps — that is the rate reduction. Quantization is a multiply, a round, and a divide by the step count.
The two knobs go in the parameter schema, and this is the part I did not expect to like: the schema derives the TypeScript type of the parameter object your process() function receives. I typo'd bitDepth as bitdepth and got a compile error rather than a knob that silently did nothing, which is the failure mode I have personally shipped more than once.
00:40 — first failure: I allocated
The compiler rejected my first real attempt. I had written a small helper that returned an object, which meant an allocation, which is not allowed on the audio thread. The error pointed at the exact line and said so in those words.
This is annoying for about four minutes and then it stops being annoying, because the restriction is the entire reason the same source can become native code with predictable timing. Rewriting the helper to take the values as arguments took two lines. The rule is that the audio thread does no work that could pause it, and the compiler is unusually willing to explain what counts.
01:10 — the UI
The UI is a web app. I used React because that is what the FX Mini example uses; the SDK does not care, and OSC Mini's UI is Vue for exactly that reason. You get parameter bindings and a value stream out; laying out two knobs is regular front-end work at that point.
I spent longer than I should have picking a font.
02:15 — second failure: the export ran, the DAW disagreed
The VST3 export succeeded. Loading it in the DAW did not — the plugin scanned, appeared, and then produced silence. The cause was mine: my parameter defaults were fine in the browser because the UI had already pushed values on mount, and in the plugin nothing had, so the sample-rate divisor defaulted to zero and every output sample was the same held silence.
Worth saying plainly, because it is the one real gotcha for a web developer here. The browser path has a UI that mounts and initializes; the plugin path may run with no window open at all. Defaults in the schema are not decoration. Once they were sensible, it made noise on the first note.
02:40 — parity check
Before calling it done I ran the render comparison: the same input through the WASM build and the native build, hashes compared. They matched, which they should, but I did not want to write this post without having actually looked.
03:05 — done
Three hours and change, including the two failures and the font. The result is a pedal that runs in a browser tab at full quality and loads in a DAW as a VST3, from one source file, made by someone who is a web developer rather than a DSP engineer.
That is the whole promise, and it is worth being clear about the boundary: this makes building accessible, not designing good DSP. A bitcrusher is forgiving. A convincing compressor is still hard, and no compiler will make it easy. But the distance between "I have an idea for a pedal" and "the idea is in my DAW" is now an afternoon, and it used to be a career change.