Local Variables, Finally Done Right
Article
June 5, 2025
Kristian Hasselknippe

We added support for local variables in Midio a while ago, and while they immediately proved useful, they were… clunky. You had to create a separate node just to set them, another to get them, and they took up a disproportionate amount of space in the graph — especially when you only needed them for a quick expression or to pass something between a couple of nodes.

banner

As a result, even though variables had the potential to simplify things, they ended up adding friction. People avoided them unless absolutely necessary, which defeated the purpose.

A Cleaner Way to Set Variables

We wanted to fix this, and I’m really happy with the result.

Now, any node output can directly map to a local variable (by simply clicking the output property) — either one with the same name, or a different one if you prefer. This small change has a huge impact. It means that wherever you're already producing a value, you can also stash it for later use, without cluttering the node graph.

banner

Even better, since local variables can be referenced using @myVar in expressions, they’re just one click away. No more wiring up a separate Get node just to use a value you already produced earlier. It makes variables feel like a natural part of working with the graph — not an extra step you have to account for.

Preventing some classic footguns

With variables becoming easier to reach for, we wanted to make sure that users won’t accidentally shoot themselves in the foot. We added a couple of guard rails:

First, you'll now get a warning if you write to a variable without reading from it, or read from a variable that hasn't been written to — since neither scenario serves any purpose. This warning helps catch these issues early.

Second, we added a new mutation modifier for variables. It’s a way to be explicit about intent when a variable might be written to from multiple places. Without realizing it, you might reuse the same variable name in different places, so this feature makes you think carefully about when that happens.

banner

Conclusion

Taken together with the existing variable nodes (Set, Get, etc), I feel like we’ve finally landed on a variable system that works the way you want it to. They help reduce clutter rather than add to it, and make simple flows feel simple again.

There are still a couple of things I’d love to see down the line:

  • Global - process local - variables: for values that should persist across scopes.
  • Global - truly - variables: for values that should persist across processes
    • We do this now with the Ephemeral Store package, but it doesn’t have first class integration into the language, and the compiler can’t reason about these variables beyond them being accessible through function calls.
  • Direct mutation support: Right now, to add something to a list stored in a variable, you need to Get the value, update it, and then Set it again. It would be great to be able to do that directly — e.g. append to a list without the detour.