More MinimalSynth

experiments, minimalcomps

You’d be forgiven if you came to the conclusion that I had any idea of what was going on here, especially with the filter node. I’m half decent at coding to an API, but I don’t really have much of a clue about music and sound.

Did a few more hours of work on top of yesterday’s demo. Started on a whole visual sound class library. It’s worth looking at the source. Not counting the library code, this whole demo was created in under 40 lines of code. Each node is a self contained UI. The toughest part was maintaining the connections. Especially with the oscillator node, which gets destroyed and recreated every time you stop and start it. This means you have to keep track of what is supposed to be connected to it – in both directions – and re-establish those connections as needed. After lots of overly complex solutions, I think I came up with a pretty clean way of managing it.

I’ll be continuing to work on this, adding more nodes, adding some more visualizations. There’s many areas of this web audio API that I haven’t even looked at.


Controls: MinimalComps2

Graphics: BLJS

Support this work

MinimalComps2 v1.5.0


I know, I know, too many releases in too short a time. But I think this is the last minor release for a while. Pretty sure I’ve done most of what I really want to do with these for a v1. And I have no idea what v2 will look like. So from here on out it should be mostly patches with bug fixes and minor tweaks.

What’s in it?

HSlider label positions

Up to now you could only change the position of the text label on an HSlider. Now you can put the value slider just about wherever you want it as well. Both can be placed top, left, right or bottom. There’s some logic in there to make sure they don’t overlap. A change on this one is that previously the value label would be to the right of the slider. Like this:

Old HSlider with value on right.

Now it defaults to on top. Like this:

New HSlider with value on top.

I think this looks a lot better, but it might mess things up for you. You can easily manually change it back to the right side.

ColorPicker with sliders

New color choosing sliders.

When you tab or click into the color picker’s input field, the panel will drop down, giving you RGB sliders to adjust your color. I like this SO much better. My favorite update for this release! You can make it drop up if you want, or turn this feature off altogether to just use the text field.

Dropdown drop up

You can now make the Dropdown component drop up if you don’t have room for it to drop down. This is not automatic. It’s a setting. Hey, these are minimal components.

VSlider swap labels

You can swap the position of the text and value labels on the VSlider, like you can on the Knob. Not a big deal, but someone might use it.

PlayButton component

Yup, a new component.


Functionally, this is the same as a Checkbox or Toggle. You click it to toggle it back and forth between two states (checked / not checked, toggled / not toggled, playing / not playing). But who wants to use a checkbox to start and stop an animation or audio?


That’s all folks. Like I said, I don’t anticipate a v1.6 for a while. But probably some v1.5.x patches here and there to fix bugs and give minor tweaks. Mostly I’m just going to be using them as much as I can in various experiments.

MinimalComps2 v1.4.0


I gotta admin, I’m not crazy about how the 2 in MinimalComps2 works with the semantic versioning. Version 1.4 of version 2? Whatever.

Anyway… VERSION 1.4.0!!!

No new components this time, but some super useful features, as well as a bunch of bug fixes.


There are some new defaults in the Defaults object. These are mostly useful if you are creating a bunch of components that need some specific property that is not settable in the constructor. Like HSlider’s text position. Rather than doing something like:

const hs1 = new HSlider(panel, x, y, "one", 0, 0, 100);
hs1.textPosition = "left";
const hs2 = new HSlider(panel, x, y, "two", 0, 0, 100);
hs2.textPosition = "left";
const hs3 = new HSlider(panel, x, y, "three", 0, 0, 100);
hs3.textPosition = "left";

You can do:

Defaults.hslider.textPosition = "left";
const hs1 = new HSlider(panel, x, y, "one", 0, 0, 100);
const hs2 = new HSlider(panel, x, y, "two", 0, 0, 100);
const hs3 = new HSlider(panel, x, y, "three", 0, 0, 100);

You can see all the properties that use this technique here.

Chainable setters

Another ease of use improvement. Basically, all settable properties now have a setter method that returns the current instance of the component. This lets you set a bunch of properties in a row and assign the result back to a variable that holds the instance. Especially useful for those properties that aren’t in the constructor, but some people don’t like the long constructors either. Along with this work, I made sure that just about all the constructor parameters are optional and have sensible defaults.

So now, if you want, you can do stuff like this:

const velSlider = new HSlider(panel)
  .move(x, y)
  .setSize(200, 30)

Maybe a little overboard with that example, but you get the idea.


Binding is one of my favorite features. It turns this:

new HSlider(panel, 20, 20, "velocity", 0, 0, 100, event => model.velocity =;

to this:

new HSlider(panel, 20, 20, "velocity", 0, 0, 100)
  .bind(model, "velocity");

I wrote about this in a lot more detail here: . So I’ll leave you with that.

Other stuff

I also upgraded the API docs a bit, both in style and content.

A bunch of bug fixes, more demos

Also, check my last few posts here for some more examples of the components in action.

I hope to get a showcase up eventually, linking to other real world uses of the library beyond my own. So if you do something with these, let me know!

Attraction and Repulsion


A particle wanders through a grid of cells, leaving a trail of points behind it. When in a cell, it is attracted to the center of that cell. It is also repelled by its previous trail of points.

Although the center attraction is stronger than the point repulsion, eventually the cell fills up with so many trail points that the particle is pushed into another cell.

Behavior emerges. Hilarity ensues. A good time was had by all.

Reminds me of a bee visiting flowers in a field.

Occasionally Eventually the particle either gets stuck or disappears. Shrug. Probably shouldn’t leave this running unattended for long periods of time.

Source (Warning – very unpolished code. Programmer discretion is advised.)

Controls: MinimalComps2

Graphics: BLJS

Support this work

MinimalComps2 v1.3.0


I’m super excited to announce the latest official build of MinimalComps2. I’ve put a lot of work into these. Been seriously obsessed over them to be honest.

That’s a live demo, not a screenshot, so have a play around. The source for that demo is here. It includes instances of all 22 components in the set.

As you can see there have been several new components added since last week. I’m quite happy with all of them but I won’t go into detail about them here. Better to check the demos and docs, API documentation and source code.

For each new component I’ve made recently, I’ve made sure that:

  1. They are fully documented. I’m using jsdoc for this at the moment. I’ll probably do a bit of work on the documentation theme, but overall, I’m happy with it. In fact, ALL components are fully documented now, not just the new ones.
  2. They are fully unit tested. I actually wrote my own unit test framework. Silly I know, but I wanted it to work the way I wanted it to work. Other testing frameworks I was trying were too bloated and complex. I had a lot of fun writing this one. It’s a minimal unit testing framework, which is appropriate. Unit test frameworks are actually super simple. I think people tend to overengineer them and make them do too much. They start to morph more into integration test frameworks than purely unit testing. All the new components are fully tested. In all, nine out of the twenty two components are tested, so there’s more to do there. But that’s close to 300 individual assertions. Doing this has uncovered a lot of little bugs, so it’s been 110% worth it.
  3. Each new component has a live demo on the main site showing how it is used.

There is more work to be done on these, but I think I’m done with creating new components. Everything I added in this release was on the early list of components I wanted to create. That list is now officially empty. I’m sure I’ll have an idea or two later on, but I’m satisfied that the library fulfills its needs at this point.

The work going forward is mostly on wrapping up the unit testing, improving some standards and best practices throughout the code. I don’t feel like the code is too horrible, but there are places where I do one thing one way and a similar thing in a different way somewhere else. So getting some more consistency in there would be good. Raking the documentation over the coals too. Some of that was copied and pasted and I’m sure there are some minor errors here and there. And finally, doing more demos as examples of how to use different components.

I really hope people find these useful and hope to see some examples in the wild. If you use them, shoot me a link and I’ll share it around.

If you do find them useful and want to support the work in some way… buy me a beer/coffee/new car.