Skip to content

node types

■ Introduction

Vmblu is a graphical editor to build an application as a collection of connected nodes, the vmblu model. Nodes have input and ouput pins connected via routes. vmblu generates a runnable application directly from it.

The learning curve to work with the editor is not steep. If you have ever worked with node based systems, like most 3D packages have, you will be up and running in no time.

In and by itself vmblu is already a great way to build applications, but using it together with an LLM is where it really shines.

In vmblu you start with the design of the architecture of your application. You identify the functionality and subsystems, and allocate these to nodes. There could be a node to manage a database, a node that handles logins, a node for the layout of the page, nodes for user interface elements etc. vmblu gives the designer total freedom of how he wants to structure an application, what the nodes have to do and the data they exchange via their pins. Many alternative approaches are possible for a given problem, but there always a clear reference of the choices being made.

An excellent start is to prompt you favorite LLM to propose the architecture of your model. As the application grows the human and the LLM keep a common, concise reference to the architecture of the system.

Really big designs can be split over several files, and refactoring a design is easy using group nodes.

It is important to mention here that however layered the architecture is, it does not have an influence on the performance of the resulting system. In the end vmblu will identify which source node connects to which other source node node and have a direct connection between them.

By using a minimal set of tags vmblu is also excellent to navigate the entire source code of an application.

Like all programming, the whole process of working is iterative, but with the vmblu model you always have an explicit, executable and up-to-date architecture to the great advantage of both the LLMs and the humans in the loop.

■ Core Concepts

Nodes

There are three types of nodes in vmblu. They can be recognized by the leftmost icon in the header of the node.

  • Source node — implemented in code - factory icon
  • Group node — contains a sub-model, behaves as one node externally - group icon
  • Linked node — imported from a model file - link icon - or a bundle - padlock icon

node typesnode types

Click on the...

  • factory icon to see or set the location of the generator function for the node
  • group icon to open the view with the internal layout of the group node
  • link icon to see or set the location of the node linked to
  • padlock icon to see the location of the node linked to

Linked nodes can only be changed in the model they are defined in. The name of the node and the position of the pins, eg for better routing, can however be changed also in the importing model.

The three other icons in the node header are common for all nodes:

  • settings icon: the optional settings can contain a json structure that is passed to the node when it is instantiated and that contains initialisation data for the node. A linked node initially inherits the settings from the original node, but the values can be changed per node. Any changes made to the format of the settings in the original node are propagated to the linked nodes.
  • pulse icon: the pulse icon contains data in json format that is passed to the vmblu runtime but not to the node. It contains information about where to instantiate the node (eg a worker) or debugging requests. The format of the data is determined by the runtime.
  • text icon: the text icon allows to open a field to enter a longer format comment about the node - it can be used as the initial prompt for an LLM to write the code for the node.

Pins & Interfaces

A node has pins and these pins can be organised in interfaces.

  • Input - an input pin of a source node maps to a handler of the node: pin do this maps to onDoThis()
  • Output - a node can send a message over an output pin using the transmit function

By design pin names are case insensitive, ie messages Get File or get file or gET fiLe are considered the same.

js
tx.send("message", payload);
  • Request/Reply - output/input pair with back-channel. A node can do a simple reply over the back channel to the node that issued the request. Can be recognized by the small circle at the arrow's base.
  • Interfaces - named sections grouping pins. If a pin name has a prefix/suffix (. - _ +) then the interface name is added before/after the message name. Example: interface name file combines with messages .get, read- and +save as to file.get, read-file and file save as respectively.

pins and interfaces

Pins and interfaces can be moved left or right, up or down, to improve routing between nodes.

Pins of the same type can be combined in multipins to improve clarity of the circuit diagram. For example clock.[on, off] is a shorthand for two pins clock.on and clock.off. Multipins can be connected if there is a partial overlap: clock.[on, off] can be connected to start.on for example.

In javascript the request/reply mechanism uses promises syntax:

js
tx.request("message name", requestPayload, optionalTimeout)
  .then((replyPayload) => {})
  .catch((error) => {
    /* errors:
            - message: 'Reply timeout' options: {sender, msec}
            - message: 'No channel'
        */
  });

Routes

Routes connect pins.

  • Orthogonal routing for clarity.
  • Any output can connect to any input (names don’t need to match).
  • Multi-message pins connect if there is a partial overlap - routes between multipins are wider.

routes

Impossible connections (input to input etc.) are not allowed in vmblu. Requests are normally connected to replies, but can be connected to regular inputs, eg for tracking purposes.

Left click on a pin to start a route, shift left click anywhere on a route to undo the route up to that point. The nearest pin will be disconnected.

Routes can be reshaped by clicking on and moving segments.

Clicking on pins and interfaces highlights all the connections for that pin or interface. Also all the connections for a single node can be highlighted (ctrl h)

Buses

To simplify routing between pins, buses can be used. There are two types of buses:

  • Busbar — broadcast - connects all outputs to all inputs.
  • Cable — connects inputs to outputs of the same name - ideal for interface symmetry.

Create a busbar or cable via the context menu or use ctrl b or ctrl k. For clarity, buses can be given a name.

When a route can terminate on a bus, the bus will light up when passing over it while drawing the route. When releasing the left mouse button, the route will be connected to the bus via a bus tack.

By design, inputs/outputs of the same node cannot be connected via a bus.

buses

Optionally a filter function can be associated with a bus. The filter function allows to select between the possible destinations of a connection to the bus, eg to do a round-robin message distribution or to select one or more destinations based on message content.

Pads

Pads are used inside a group node and expose the pins of the group node. There are two ways to add a pad, either by adding a pin to the group node or by extruding a pin inside the group node view. To extrude a pin, shift-ctrl + left click on the pin and move the cursor.

pads

Multiple inputs/outputs can be connected to a pad. Pads can also be connected to buses.

■ Working with LLMs

The vmblu editor can be used without LLM assistance to build systems with clarity and maintainability. The use of an LLMs can greatly speed up the development of the system without sacrificing the clarity and trustworthiness of the system.

In order to make working with LLMs efficient, a number of documents have to be included in the project. These documents explain to an LLM the formats used by vmblu and the rules to follow when editing these documents.

Documents used

While working on a project myProject the LLM uses the following documents:

  • vmblu.schema.json The format of a vmblu file - part of the distro.
  • vmblu.annex.md Semantic clarifictions about the schema for an LLM - part of the distro
  • myProject.vmblu The actual model of the system
  • myProject.doc.json The parameter signatures of message handlers and messages sent - generated by vmblu
  • manifest.json Overview of the authoritive reference files of the system
  • seed.md Starting point for an LLM
  • time.session.json The prompts used over the sessions for the model (to be implemented)

The command vmblu init creates the directory structure for a project and copies/generates the required files as follows:

project dir/
  myProject.vmblu
  myProject.doc.json
  package.json
  llm/
    manifest.json
    vmblu.schema.json
    vmblu.annex.md
    seed.md
    session/
  nodes/

The source for the project can be organized as wanted: for complex nodes it can be helpful to have a model file for the node close to the actual source of the node and link to that node in the main model file, or to have a library of nodes, for example for the ui of the project, etc.

Collaboration loop

  • Iterative. As for the development of source code, working with an LLM to build a model is an iterative process. The vmblu.schema defines the areas that an LLM can change and the areas that are exclusively for the use of the graphical editor. An LLM can typically define nodes, pins, interfaces and connections but the exact placement and routing is done by the editor.

  • Clean up graphics When an LLM proposes an architecture for a system, the vmblu editor will place the nodes and route the connections automatically, but normally human interaction will be required to make the graphics clearer by moving the nodes and the routes - most of the time fairly straightforward. As LLMs will become better at these tasks, less will have to be done to make the diagrams clearer. LLMs will not interfere with positions / routes that have been fixed by the user.

  • Incremental It is always a good idea to spend some time first on the architecture to get the fundamentals right, but not everything has to be in place to start writing the code for the system. In a node based architecture it is a lot easier to add features and functions incrementally.

The vmblu.annex file contains general rules for the LLM to follow when working on a project. A designer can of course always add rules to this file as he sees fit.

MCP interface to the app

An LLM can also interface with the running application that was built with vmblu, by giving it access to the interfaces of the nodes. This allows the user to interface with a system in natural language at the node-level.

The way this works is that vmblu can build an MCP tool file. The tool file contains the details, in a standardised format, of the nodes that offer a service and the parameters for that service. An MCP Client, typically an LLM, can request that file and use this to interface with the system.

As vmblu applications are message based, interfacing with the app to obtain a service, is uncomplicated. There is a separate chapter on how to implement MCP in a vmblu application.

■ Using the Editor

main menu

  • accept changes : when a linked node is modified in its original file, the model that imports the node will show what has changed - added, changed or deleted pins and interfaces. Click on this icon - after verification - to accept these changes.

  • sync model : when a node linked to, is modified, this will reflect immediately in the importing file. If the node linked to is in the same file, it can be necessary to do a 'sync' to force an immediate update of the model.

  • set save point / back to save point: before a big modefication of a model it might be worth considering to set a save point, which saves the current status of the file. If the modefication did not turn out as expected, back to save point will reset the model to what was saved. The initial save point is set when the model is read from file.

  • make lib: outputs a file 'my-model-lib.js' that is the main file for building a bundle with the nodes of the model. Also the model is part of the bundle. Typically used to build a library of standard nodes.

  • make app: outputs the main file of the vmblu-based application. To be included in a browser page, run at the server etc. The file consists of a list of nodes and filters that are created by the runtime.

  • settings: the settings for the model.

Selections

The editor often works on selections: a node, a pin, a group of nodes etc.

Selecting in the editor is done by clicking on the node or pin to be selected. To select multiple nodes or pins in a rectangular area use [shift] + [left mouse button] + drag. A selection is shown in orange or with an orange box around it.

To reposition a pin in a node use [ctrl]+[left mouse button]+drag. You can also drag a group of selected pins like that. To drag all the pins of an interface, simply [ctrl]+[left mouse click]+drag the interface name.

selection

Context Menus

The actions that are available for an item of the model can be selected from a context menu, that pops up when clicking the [right mouse button] on the item. For many of the actions listed in the menu there is akos a key combination available. The editor has the following context menus:

Background Menu

background menu

Node Menu

node menu

  • source to slipboard: Puts an outline of the source code for this node on the clipboard. The outline contains the headers for the handlesr of the input pins of the node.
  • make a test node: creates a node that is a mirror image of this node: for every input pin of the node the mirror node has an output pin, and for evey output pin the mirror node has an input pin. The mirror node is typically used to make a test node for the original node.
  • update profiles: re-scan the source of the node to update what parameters are required by a message handler and where output messages are sent.

Pin Area Menu

pin area menu

  • add channel: makes a request pin from an output pin and a reply pin from an input pin.
  • profile: shows the profile of the pin. For an input or reply pin this shows the parameter signature of the handler for the message and the file where the handler can be found. When clicking on the file the file is opened at the position of the handler. For an output or request message this shows the location(s) in the source where the message is sent. Clicking on these opens the file at the location where the message is sent.

Input pin profile example: input pin profile

Output pin profile example: output pin profile

Bus Menu

selection

Selection Menu

selection

  • group: allows to make a single group node from the selected nodes. External connections will stay intact. If needed buses will be duplicated inside the group node. External pins will be given corresponding pads inside the group node.

■ Source Integration

With every source node corresponds an implementation in code. In that code handlers correspond with input/reply messages and output/request messages are sent via the runtime.

Source nodes are instantiated at runtime by calling the factory function for that node. The factory function can either be a normal function that returns the node, or it can be a class name, in which case the runtime will instantiate with new mySourceNode.

When the factory function is called, two parameters are passed to it, tx and sx, and the function should return, explicitely or implicitely, a reference to an object that allows the runtime to parse for the message handlers. In most cases that object is simply the instance of the node, but it does not have to be.

Factory functions

Below are a few examples of factory functions:

A simple function that returns the node:

js
function mySourceNodeFactory(tx, sx) {
  // create the node here
  const mySourceNode = ...

  // explicitely return
  return mySourceNode;
}

A constructor function:

js
//Constructor for planet
export function CelestialOrb(tx, sx) {
  // save the tx and the sx
  this.tx = tx;
  this.sx = sx;

  // the planet specs
  this.ephemeris = null;

  // etc...

  // return is implicit
}
CelestialOrb.prototype = {
  // The message handlers - and other methods
  onSomeMessage(payload) {},

  onSomeOtherMessage(payload) {},
};

A class:

js
// Declaration
class DatabaseAccess {
  constructor(tx, sx) {
    // Save the transmitter
    this.tx = tx;

    // save the settings
    this.sx = sx;
  }
  // The message handlers - and other methods
  onSomeMessage(payload) {}

  onSomeOtherMessage(payload) {}
}

All nodes are created by the runtime before it starts to switch messages between them. This means that a node can already send messages as soon as it is created, the messages will be placed on the message queue, and do not have to worry about nodes not yet being created.

The sx parameter are the settings for the node as set via the settings icon of the node. The txparameter - the transmitter - is an object that gives the node access to the functions of the runtime library.

Below we have a look at how messages are mapped to handlers and to the tx interface.

Messages and handlers

When a node is instantiated, the runtime will scan the returned object for handlers that correspond to the input pins of the object.

A handler function is a normal function that is called by the runtime with the message payload as the only parameter and this set to the node for which the handler is called.

The correspondence is straightforward: with a message some message corresponds a handler with the name onSomeMessage, ie the message name is preceeded by 'on' and camel-cased.

Message names are allowed to contain special characters and spaces, but these special characters are stripped from the handler name. The editor signals when the handler name for two messages are the same, eg some message and some.message.

The tx interface

The transmitter txthat is passed as a parameter to the node exposes the interface with the runtime. It has the following members:

  • tx.send(pinName, payload) This function sends a message over pin pinName with one parameter, the payload. The payload can be anything, but will be an object in most of the cases. The function returns the number of messages that have been send, so if the pin is not connected it will return 0 (zero).
  • tx.request(pinName, payload, { timeout? }) This function also sends a payload over a pin pinName but has an additional, optional, timeout parameter. The request function returns a promise that resolves when the reply from the connected node(s) comes in. If a request is connected to three pins that can give a reply then three promises will be created. The promise is rejected immediately if no reply pins are connected to the request pin, and also when the timeout is triggered. The default value for the timeout is a setting for the runtime, but typically a few seconds.
  • tx.reply(payload) A node can issue a reply on a reply pin, whereby the payload is returned over the same pin and resolves the outstanding promise at the requesting node.
  • tx.next(partial) In stead of a reply, a node can also answer with next. This will return the payload to the requesting node but create a promise again to wait for the answer on this reply. In this way two nodes can have a conversation by using next in turns until it is terminated by the final reply
  • tx.reschedule() It some cases it can be that a node cannot handle a message because certain conditions have not yet been met. This situation can be solved in several ways, but for convenience a simple function has been added to the tx interface that simply puts the message on the message queue again so that it will be presented again at the next iteration.
  • tx.pin this property is the name of the pin from which the message originated that the handler is treating.
  • tx.wireless(nodeName).send and tx.wireless(nodeName).request(...) The purpose of a vmblu model is to make every connection between nodes explicit, and the node does not have to know anything about the architecture of the total system to send and receive messages. There are however situations where it is on the contrary essential for a node to know the architecture of the system, for example when using an MCP (Model Context Protocol) node in a system. An MCP node allows an LLM to send a message to a node that has published its interface. In that case, instead of having to route a connection from the MCP node to every node that has a published interface, the MCP node can use wireless transmission. The wireless function takes the name of the node as a parameter and returns a specific transmitter that allows to send/request a message to that node.

Filter

The filter for a bus is an object that has the method filter defined on it, like in this simplified example:

js
// The filter object 
export function MyFilterObject() {}
MyFilterObject.prototype = {

  // the filter function can return an array of names or a single name
  filter(nodeNames, pinName, messagePayload) {

    // do some selection based on your criteria..
    const selectedNodes = ...

    // In this case the name of the destination 
    return selectedNodes;
  },
};

When a message is sent over a bus, all the possible recipients of that message on the bus are identified. In a second step the filter function is called with three parameters: the array of recipients (strings), the name of the pin that put the message on the bus and the payload of the message.

The filter function can then select one or more names from the nodes in the nodeNames and return the single string or an array of strings. The message will be sent to these filtered destinations.

JSDoc tags

JSDoc tags are used in the source code to make the pin profile information work. Under the hood vmblu uses ts-morph to scan the source files for parameter info. The parameter info can be taken from typescript type info or, for javascript, from the @param JSDoc tag.

vmblu uses three specific tags to locate information:

  • @node <node name> this tag indicates that the methods/functions in a file are for the node of that name, so that the handlers and the tx.send can be linked to that node. Placing it once at the start of a file is sufficient and it stays valid until the next @node tag in the file.
  • @prompt <text> LLM-friendly description of a handler.
  • @mcp if you put the @mcp tage before a handler, then the handler will be included in the mcp tool description file for the app.

Example of a decorated handler function:

js
/**
 * @prompt Notification that a document was renamed.
 * @node document manager
 * @mcp
 * @param {Object} info
 * @param {string} info.oldName - Previous document name
 * @param {string} info.newName - New document name
 */
onDocRenamed({ oldName, newName }) { /* ... */ }

Making the app

In the main menu select the rocket icon to generate the javascript code for the app. The code generated contains four parts:

  • Import section: here all the files with the factory functions and filter functions are imported. Example:
js
// ------------------------------------------------------------------
// Model: 
// Path: solar-system-app.js
// Creation date 9/22/2025, 8:57:19 AM
// ------------------------------------------------------------------

// import the runtime library
import * as VMBLU from "@vizualmodel/vmblu";

//Imports
import { ScreenLayout,
		 HelpersSettings,
		 SolarSystemSettings,
		 SimulationSettings,
		 CamerasSettings,
		 IconMenuHorizontal,
		 LLMChatWindow } from './ui/index.js'
// etc...
import { PlanetaryDistance } from './chart/index.js'
import { McpClientOpenAI } from '../../../core/ai/mcp-client-in-browser.js'
import { McpServerInBrowser } from './mcp-server.js'
  • Nodes section: An array of source nodes and the connections to other source nodes. Example:
js
//The runtime nodes
const nodeList = [
	//_______________________________________________SCREEN LAYOUT
	{
	name: "screen layout", 
	uid: "PzOB", 
	factory: ScreenLayout,
	inputs: [
		"-> menu",
		"-> timeline",

    //etc...

		"-> right side toggle",
		"-> right side add div"
		],
	outputs: [
		"visible start -> update start @ renderer (imdr)",
		"visible stop -> update stop @ renderer (imdr)",
		"canvas -> canvas add @ camera manager (LDdW)"
		]
	},
	//________________________________________________HELPER TOOLS
	{
	name: "helper tools", 
	uid: "whha", 
	factory: HelperTools,
	inputs: [
		"-> grid change",
		"-> axes change"
		],
	outputs: [
		"grid show -> grid set @ helper settings (zBFx)",
		"axes show -> axes set @ helper settings (zBFx)",
		"scene add -> scene add @ scene manager (tKKg)",
		"scene remove -> scene remove @ scene manager (tKKg)",
		"scene dispose -> scene dispose @ scene manager (tKKg)"
		],
	sx:	{
		    "grid": {
          "on": false,
          "color": "0x773333"
		    },
		    "axes": {
		        "on": false,
		        "size": "50"
		    }
		}
	},

Also the optional sx, the parameters for the node, and dx, the parameters for the runtime, are included for each node.

  • Filter section: The filter nodes for a bus and the fanout of the bus for each input to the bus. Example:
js
//The filters
const filterList = [
	//________________________________________PLANET ROUTER FILTER
	{
	name: "planet router", 
	uid: "KAbB", 
	filter: PlanetRouter,
	table: [
		`place local camera : [
			"place local camera @ earth (hEXZ)",
      ...
			"place local camera @ venus (oeFm)" ]`,

    // etc...

		`simulation user change : [
			"simulation user change @ uranus (IKeo)",
      ...
			"simulation user change @ jupiter (Wzci)" ]`,]
	},
]
  • Runtime section: Here the function scaffold is called. scaffold instantiates all the nodes and returns a reference to the runtime. Finally the runtime is started.
js
// prepare the runtime
const runtime = VMBLU.scaffold(nodeList, filterList)

// and start the app
runtime.start()

Running an app

A vmblu app can be run like any other js or ts app, for example run inside a browser

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vmblu Browser Version</title>
    <link rel="stylesheet" href="index.css">
  </head>
  <body>
    <script type="module" src="vmblu.js"></script>
  </body>
</html>

Or run as a node.js app

bash
node myVmbluApp.js

Console warnings

The scaffold function can issue the following warnings:

  • ** NO HANDLERS ** The node has input pins but the factory returned no handlers.
  • ** NO HANDLER ** The node has an input pin for which there is no handler.
  • ** NO OUTPUT PIN ** tx.send() is used but there is no corresponding output pin.

The app does continue, it could simply be that some functionality has not yet been implemented.

■ Using MCP

Introduction

MCP is a standardised protocol that exposes 'tools' offered by an application to an LLM. The way this works is that

  • for the application you create an MCP server, an interface that tells what tools the application has to offer in a standard format.
  • for each LLM you wish the application to interface with you create an MCP client that interfaces with the LLM following the specific requirements of the LLM.

The reason why MCP is such an improvement over previous approaches is that you only have to write the MCP Server once for your application, and the MCP client once for each LLM you wish to use your applications with.

Setting up MCP for use in a vmblu application is, because of the use of nodes and message passing, straightforward.

MCP in vmblu

It is clear that the for the client and server to work properly they have to exchange some information. In vmblu this is easy to set up by using a group node as follows:

MCp group node

The three source nodes are:

  • LLM Chat Window: a user interface window that connects to the LLM. In that window the user can type prompts and will see the replies from the LLM. The look, feel and handling of that window depend on your application. As API keys are best not stored in the app code, this window will generally also offer an interface to set and revoke an API key.
  • MCP Client: This node sets up the connection to the LLM used. It also takes in the prompt from the user and returns the replies from the LLM. In addition it has a connection to the MCP Server node for the application.
  • MCP Server: This node reads the mcp tool file - generated by vmblu as we have seen above - and makes it available for the client.

The way this works is that the MCP client issues a request for a manifest for every MCP Server connected to it. The manifest contains some general information about the version used etc.. Following an acceptable reply, the MCP client sends a request to the MCP Server to obtain the list of tools supplied by this application. The MCP client converts the tool list to the format specific for the LLM, and includes the tool list in the prompt records it sends to the LLM.

When the user types a new prompt, for example change camera settings to ..., the client forwards this to the LLM and if the LLM sees that there is a tool available for the request, it will add a tool call record to its reply to the MCP Client. The MCP client then sensd a tool call message to the MCP server.

The MCP server knows how to execute that tool call. In many cases this will simply be sending a message to a node to get something done, but it can be a more complicated action requiring several messages for example. In any case the architetcure of a vmblu application is very well suited for this type of interaction. When the tool call has been executed, the MCP Server will send the result back to the client to inform the user and LLM as required.

The MCP Server node is also one of the type of nodes where the use of wireless communication with the nodes via tx.wireless(nodeName).send() is natural as The MCP Server is supposed to know the architecture of the application. The alternative would be to add a pin to the MCP server for every tool used and route it to the node that delivers the service. Doable, but maybe not the most elegant solution, depending on the application.

The vmblu distro contains a an example of an MCP Client node and MCP Server node.

Example of an MCP tool file generated by vmblu:

js
// ------------------------------------------------------------------
// MCP tool file for model: SolarSystem
// Creation date 6/27/2025, 4:40:26 PM
// ------------------------------------------------------------------

export const mcpTools = [
    {
        name: 'camera manager_camera add',
        description: 'Trigger camera add on camera manager',
        parameters: [
            {
                name: 'name',
                type: 'string',
                description: '- the name of the camera.'
            },
            {
                name: 'type',
                type: 'CameraType',
                description: '- perspective or orthographic'
            },
  ...
            {
                name: 'lookAt',
                type: 'import(three).Vector3',
                description: '- point that the camera looks at'
            }
        ],
        returns: '',
        node: 'camera manager',
        pin: 'camera add',
        handler: 'onCameraAdd',
        file: 'C:/dev/vm/app/solar/src/3d/camera-manager.js',
        line: 156
    },
    {
        name: 'camera manager_camera update',
        description: 'Trigger camera update on camera manager',
        parameters: [
            {
                name: 'near',
                type: 'number',
                description: '- New near clipping plane distance.'
            },
...
            {
                name: 'aspect',
                type: 'number',
                description: '- New aspect ratio.'
            }
        ],
        returns: '',
        node: 'camera manager',
        pin: 'camera update',
        handler: 'onCameraUpdate',
        file: 'C:/dev/vm/app/solar/src/3d/camera-manager.js',
        line: 192
    },

■ FAQ

  • Does vmblu use standard -closed- nodes ? No in vmblu the function of a node - the source code of the node - is provided by the developer of the system and there are no 'closed' nodes in vmblu, there is no lock-in. Obviously vmblu is ideal to design a library of standard nodes for all kinds of tasks that can then easily be used across multiple project, but that is entirely up to the dev team.
  • Can the vmblu runtime be modified ? Yes, the runtime is part of the vmblu distro and is also open source. It is short and sweet and if for some reason you want to modify it, you can.
  • TS or JS? Both. TS types are read; in JS, add JSDoc for types.
  • Is vmblu available for other languages For the moment vmblu is only available for TS/JS. In principle there is no limitation with respect to the languages the vmblu model can be applied to. As demand grows, runtimes for other languages will be added.
  • Type safety between pins? vmblu doesn’t enforce types across nodes; enforce in code and via Profiles.
  • When to use request/reply? In most cases request/reply will be used sparingly between nodes. If you see that you have to use it a lot , there is probably a better split possible of functionalities between nodes.
  • Busbar vs Cable? Busbar = broadcast, ideal for one to many or many to one situations. Cable = same-name pins only, ideal for interface type of connections between nodes.
  • Can I reuse nodes? Yes: make a linked node or bundle; accept changes to stay in sync.

■ Glossary

  • Node — source, group, or linked component.
  • Pin — input/output connection point.
  • Interface — group of pins with shared prefix/suffix.
  • Route — connection between pins.
  • Busbar — broadcast bus.
  • Cable — name-matched bus.
  • Router — selective filter on a cable.
  • Pad — group node IO exposed internally.
  • Profile — pin metadata linking to source code sites.
  • sx/dx — node vs runtime settings.
  • MCP — Model Context Protocol for tool integration.

■ Appendices

Keyboard Shortcuts

ActionShortcut
Create busbarCtrl + B
Create cableCtrl + K
Multi-selectShift + drag
Move pin/interfaceCtrl + drag
UndoCtrl + Z
RedoCtrl + Shift + Z

JSDoc Cheat Sheet

js
/**
 * @prompt Notification that a document was renamed.
 * @node document manager
 * @mcp
 * @param {Object} info
 * @param {string} info.oldName - Previous document name
 * @param {string} info.newName - New document name
 */
onDocRenamed({ oldName, newName }) { /* ... */ }