Each kind of node is basically a class, and is distinguished by its color and interfaces - input nodes are blue with a button that triggers an action and one output, debug nodes are green with one input and a switch to toggle if output is being logged, function nodes are tan and have one input and three outputs (iirc, "normal" output - more on this later - stderr and return value).
Nodes are linked up output to input - no limit on the number of links a given interface can have - and transfer information as json objects. Often nodes expect a top level key named "payload" by default, though most node behavior can be customised.
So a hello world program would be something like: blue kickoff node with a button --> tan function node inside which you define a js function that takes an object named msg as an argument and sets msg.payload to "hello world!" --> green debug node set to log msg.payload and switched on. You click the button and "hello world!" appears in the log (and reappears as many times as you click).
The nice thing is that there are a lot of kinds of nodes that abstract away common tasks - very much like what ansible does with modules. One read/writes files, one executes shell commands, one listens/broadcasts to mqtt channels, one queries sql databases, etc. When the correct node is used for a task vs wrapping all the desired logic in a single function node (which you could do), the resulting graph or flow is very easy to understand or reason about.
What I had in mind was staying in the procedural/oop paradigm of e.g. Java, but without the requirement of a fixed syntax, way more flexible rendering options, and the possibily of more diverse input schemes than typing one character at a time.