Vibes DIY
Vibes DIY / Blog
From the build log

You can just make music

The browser you're reading this in contains a full drum machine. Not "could download an app" — it's one line of code away, and by the end of this post you'll have pressed play on four of them without installing anything.

This is a tutorial about Strudel, a wonderful live-coding music engine — you type little patterns, it makes beats. Every example below is a real app running live in this page. Press play. Then remix one and make it yours.

The one line that does all the work

Normally, using a music engine in your app means a project setup: package managers, import statements, build tools, and a folder of other people's code that becomes part of your app. If you've never done that, good news — you're not going to start today.

Here's the entire trick, and the only "advanced" code in this post:

jsconst web = await import("https://esm.sh/@strudel/[email protected]");

Read it like a sentence: when someone presses play, go fetch the Strudel engine from that address and hand it to me. The engine lives on a public shelf on the internet (a CDN), and the visitor's browser picks it up at that moment — exactly the way it picks up a webpage. It is not copied into your app. Your app is just your fifty lines; the instrument is borrowed at showtime, not photocopied into your sheet music.

That distinction is more than tidy — it's respectful. Strudel is licensed under the AGPL, a strong share-alike license: build Strudel's code into your program, and your program is expected to adopt the same license. That's a great deal for a music tool, but it's a decision you shouldn't have to make to play a kick drum. Loading the engine at runtime keeps the two programs separate: Strudel stays whole, credited, and under its own license at its own address, and your fifty lines stay yours. (Usual caveat: we're enthusiasts, not lawyers — and either way, credit the Strudel project visibly. They made the magic.)

On Vibes you don't even have to remember the line — every example below is a public vibe you can open and remix, loader included. Let's play.

Step 1 — press play

One button. When you press it, the engine arrives (first press takes a few seconds — it's fetching real drum sounds), and then this plays:

jss("bd*4, ~ cp ~ cp, hh*8")
strudel-hello-beat — open the live vibe

That string is a whole song, or at least a whole groove: bd*4 is four bass drums per bar, ~ cp ~ cp is a clap on the off-beats, hh*8 is eight hi-hats, and the commas mean play all of these at once.

Get posts like this in your inbox

One email field. Real updates. No algorithm required.

Step 2 — the pattern language

Those little strings are called mini-notation, and they're the whole game. Words are drum sounds. Spaces divide the bar. A few symbols do the rest:

writemeaning
bd sdkick, then snare
~silence
bd*2twice as many
[sd sd]squeeze two into one slot
<sd cp>snare this bar, clap the next
bd sd, hh*8both lines at once

Type anything into this one — it's a text box wired straight to the engine. The chips load examples of each symbol:

strudel-notation — open the live vibe

Step 3 — you don't have to show anyone the code

Here's the part that turns a toy into an app: your interface can write the pattern for you. This is a classic step sequencer — three rows of buttons, and every toggle rebuilds the mini-notation string and hands it to the engine, live, while it plays:

strudel-layers — open the live vibe

The translation from buttons to music is one honest function — a lit button becomes its drum sound, an unlit one becomes ~:

jsfunction toCode(grid) {
  const lines = ROWS.map(([sound]) =>
    `  s("${grid[sound].map((on) => (on ? sound : "~")).join(" ")}")`
  );
  return `stack(\n${lines.join(",\n")}\n).cpm(110/8)`;
}

stack(...) is "play these together," and cpm() sets the tempo — one small gotcha worth knowing: it counts whole loops per minute, not beats, so you divide your BPM by how many beats one loop holds (our eight steps span two bars, hence the 8). When in doubt, divide until it grooves.

Step 4 — knobs

Patterns take effects by chaining them on the end: .lpf(1200) is a filter that muffles the highs, .room(0.3) adds space, .cpm() sets how fast the loop spins. Which means sliders are just numbers dropped into the same string:

strudel-effects — open the live vibe

Drag while it plays. There's a bassline hiding under that filter.

Where this goes

Each demo above is a public vibe: open it, hit remix, and the loader line comes with it — you start at "making music" instead of "configuring a project." That's the actual point of the runtime-import trick. It's not a license workaround, it's a division of labor: the Strudel folks maintain a brilliant instrument at a public address, and you write the fifty lines that are actually yours — the interface, the idea, the song.

If you want to see how far the same trick stretches, jchris/strudel is the full live-coding version: an editor, saved patterns, and an AI prompt box that rewrites your groove when you ask it to "make it darker."

Make a noise machine of your own

Remix any demo in this post, or describe the instrument you wish existed.

Start building →

Enjoyed this? Get the next post by email

One email field. Real updates. No algorithm required.

Prefer a feed? RSS · Atom