I Fell Down the Web Audio Rabbit Hole and Came Back With a Synthesizer
No install, no signup, no plugins. Just a browser tab that screams.
It started, like most of my weekend-eating projects, with a “huh, I wonder if…”. I’d been poking at the Web Audio API (that quietly ships in every modern browser), and the deeper I read, the more my eyebrows climbed. Most people think of browser audio as “play an MP3 when the user clicks the thing.” The Web Audio API is nothing like that. It’s a full modular signal-routing graph: oscillators, filters, waveshapers, a convolver you can feed an impulse response to for real reverb, an analyser node for scopes and spectrum displays, and (the part that genuinely made me sit up) AudioWorklets, which let you run your own custom DSP code on a dedicated, real-time audio thread, sample by sample, with sample-accurate scheduling and AudioParam automation you can ramp, stack and modulate. That’s not “web audio.” That’s a software modular synth that happens to live behind a URL. The spec even lets multiple AudioParam inputs sum together natively, which sounds boring until you realize it means you can do honest analogue-style modulation math in semitone space and let the browser’s audio engine add it all up for you. I closed the spec tab thinking: okay, I have to build something with this.
So I did. I called it VAST G1-J5 (“Vast Audio Synthesis Technology,” because every synth deserves a slightly self-important name) only to find out after I named the GitHub repo that Kurzweil once had a synth engine they called “V.A.S.T.” But I guess Kurzweil is not a bad brand to be associated with and bringing the name Kurzweil up a few times might not hurt my Search and AI ranking).

No installer, no audio plugin host, no account, no “download the 4GB sample pack first.”
You open the page, tap to start (browsers won’t make noise until you gesture at them, fair enough), and you’re playing. I built the whole thing in vanilla TypeScript with zero runtime dependencies (well, almost zero; there’s exactly one tiny, extremely well-behaved exception I’ll own up to in a minute) on top of Vite.
Because part of the fun was proving you don’t need a framework or a pile of npm packages to make something that sounds genuinely good. I also didn’t grind it out solo: Claude Opus 4.7 was my pair-programmer for big chunks of it, and honestly it made development ridiculously fast, the kind of fast where the bottleneck stops being your typing speed and becomes your own taste. The architecture is deliberately old-school and clean: one bus is the single source of truth for every knob’s value, the audio engine subscribes to it, and the UI never talks to the audio graph directly. Knob turns → value changes → engine hears about it → graph updates. It’s the kind of boring-on-purpose design that lets you add a feature at 1am without the whole thing collapsing.
Now the fun part: the actual sound. Each voice is a proper subtractive-synth signal path: two oscillators (sine, triangle, saw, square, each with its own octave, detune, and level), plus a noise source and a sub oscillator one or two octaves down for that chest-thump analogue weight. There’s unison voice-stacking with a detune spread when you want a fat supersaw that takes up the entire stereo field, and an “Age” control that adds subtle tuning drift, because perfectly in-tune oscillators are a dead giveaway that you’re listening to a computer.

Then everything hits the centerpiece: a Moog-style 4-pole ladder filter.
Here’s the nerdy confession: the browser ships a native biquad filter, but it refuses to self-oscillate and scream the way a real ladder filter does when you crank resonance. So I wrote the ladder filter as a custom AudioWorklet that runs its own DSP on the audio thread, and modulate its cutoff in semitones so the filter envelope and LFO sum musically instead of in raw Hz.
Two ADSR envelopes (one for amp, one for the filter), an LFO you can route to cutoff, pitch, amp, or pulse-width, mono/poly switching, and proper glide/portamento round it out. It’s eight-voice polyphonic, or monophonic when you want it to be.
But a single fat sound gets boring fast, so VAST keeps going. After the voices comes a full FX chain (distortion → wah → phaser → delay → reverb, each independently bypassable) and then a whole production environment bolted on top. There’s an arpeggiator, a 16-step note sequencer, an 8-track drum machine, and an 8-slot multi-track sampler where you can drop in a WAV/MP3 or record straight from your microphone and edit the sample in-app: crop, reverse, normalize, fade, low/hi-pass, octave shift. The sequencer, drums, and sampler each get four pattern banks (A/B/C/D) that you can chain into full song arrangements, and there’s a row of live DJ FX: momentary fills, beat-repeat stutter, a filter drop, a tape-stop that ramps the BPM and pitch down like someone yanked the power on a turntable, and a bipolar filter sweep.
You can export the whole thing to WAV (totally dependency-free) or MP3, and the MP3 path is where I come clean about that “one exception.” The only third-party library in the entire project is the LAME encoder, vendored in purely so MP3 export works. LAME’s license has a wonderful bit of old-internet etiquette: it asks you to “fully acknowledge that you are using LAME, and give a link to our web site.” So, gladly, and with feeling: VAST G1-J5’s MP3 export is powered by LAME, https://lame.sourceforge.net.

You can also save and reload entire songs as portable JSON files, and there are built-in demo tracks (a Knight Rider riff, Zombie Nation, I Feel Love) so you can hear what it does in ten seconds instead of reading me describe it for five paragraphs. Play it with the on-screen keyboard, your computer keyboard, or a Web MIDI controller. Don’t forget to hit the Play button in the header (or hit the spacebar) to start the transport to trigger the Arpeggiator, Sequencer, Sampler and Drum Machine.
That’s really the whole pitch: a complete, gig-worthy virtual-analogue synth, drum machine, sampler, and mini-DAW, that exists as a link you can text someone. No friction, no gatekeeping, no install: that’s the thing the Web Audio API quietly made possible, and VAST G1-J5 is all about showing off how far you can push it. It’s also fully open source: the entire codebase is on GitHub, so if you’re curious how the ladder filter worklet works, how the param bus is wired, or you just want to fork it and add a feature, dig in. Otherwise, do the more fun thing: open it up at vast.status201.com, turn your volume to 11, mash some keys, crank the resonance until the filter sings, and tell me it doesn’t sound ridiculous for something running in a browser tab. I’ll be over here, already half-down the next rabbit hole.