Structure of a programlink

A Membrane program consists of:

  • Code: TypeScript/JavaScript handlers for fields, actions and events.
  • Schema: nodes exposed in the graph. The program's own API.
  • Dependencies: nodes used by the program.
  • An HTTP endpoint: receive request on the program's own URL.

Graph and Schemalink

Programs that expose data and functionality do so by exposing a graph of nodes.

To expose a graph, programs declare a schema that determines the shape of its nodes and how they related to each other.

A schema is composed of types, and each type is composed of fields, actions and events (collectively refered to as members).

  • fields: queriable nodes and values.
  • actions: invocable functions on a node.
  • events: subscribable notifications.

A program's schema must always define a type named Root which serves as the entry point into the rest of its graph.


Programs must have an index.ts or index.js exporting resolver functions.


Programs declare ahead of time the nodes needed from the graph.

These handles are then available as variables in the nodes object from the membrane module.

State objectlink

Programs have a state object that can be used to persist state between updates. This object can be accessed from the membrane module.

Technically, since the entire JS heap is continually persisted, you could just use module-level variables to store state. But since each update creates a new ES Module, prior values are not accessible from newer modules, hence the need for state to share state across different version of the program's code (i.e. different ESM modules).


Each Membrane program has its own publicly available domain name which they can use to respond to HTTP requests.


Programs can declare that they recognize certain text expressions and are able to turn them into corresponding node handles.

This is what allows the browser plugin to scan a web page and find the corresponding handles.