Skip to main content

Bubble to NodeGX dictionary

A Bubble app is stored as JSON: a tree of elements, each with a type and its properties, and workflows made of actions. A NodeGX app is JSON too: components made of nodes, each with a type and its parameters, joined by connections. This page puts the two side by side, one Bubble element at a time.

The examples are real. The Bubble side is cut from the export of a Bubble landing page; the only edits are a placeholder image URL, and a scroll target moved to an element that is kept. The NodeGX side is what the rules below make from it, regenerated with the page whenever the rules change.

For Bubble's operators one by one (:count, :formatted as, :filtered), see Coming from Bubble. This page covers everything around them: elements, layout, styles, workflows and data.

Elements, one example each​

Each example shows the element as it appears in the Bubble export, then the NodeGX nodes it becomes. The NodeGX node keeps the Bubble id: cmMfz becomes el_cmMfz. Canvas positions are left out.

Page​

One Bubble page becomes two nodes. The Page holds the title and the URL (the index page gets ""). The Group under it lays the page out: the page's container_layout, minimum height and background colour.

Bubble

{
"id": "bTIWz",
"name": "index",
"type": "Page",
"properties": {
"title": {
"entries": {
"0": "Page Title"
},
"type": "TextExpression"
},
"new_responsive": true,
"container_layout": "column",
"min_height_px": 400,
"backdrop_bgcolor": "rgba(255, 255, 255, 1)",
"width": 1200,
"height": 4166,
"preset_width": "full_width",
"default_width": 1200,
"responsive_version": 1,
"element_version": 5
},
"elements": "(the elements below)",
"workflows": "(the workflows below)"
}

NodeGX: Page, Group

[
{
"id": "page_bTIWz",
"type": "Page",
"label": "index",
"parameters": {
"title": "Page Title",
"urlPath": ""
},
"children": [
"root_bTIWz"
]
},
{
"id": "root_bTIWz",
"type": "Group",
"label": "Page index",
"parent": "page_bTIWz",
"parameters": {
"flexDirection": "column",
"width": {
"value": 100,
"unit": "%"
},
"sizeMode": "contentHeight",
"minHeight": {
"value": 400,
"unit": "px"
},
"backgroundColor": "rgba(255, 255, 255, 1)"
},
"children": [
"el_cmMsV",
"el_cmMfz",
"el_cmMfn",
"el_cmMwK",
"el_cmMpD",
"el_cmMwz"
]
}
]

Group​

A row. container_layout: "row" becomes flexDirection: "row", fit_height becomes sizeMode: "contentHeight", and the margins carry over in px. Its two children are the next two examples.

Bubble

{
"properties": {
"height": 250,
"left": 24,
"top": 0,
"width": 400,
"zindex": 2,
"background_style": "none",
"order": 1,
"fit_height": true,
"margin_top": 32,
"margin_left": 24,
"margin_right": 24,
"single_width": false,
"min_width_css": "20px",
"single_height": false,
"min_height_css": "20px",
"horiz_alignment": "center",
"container_layout": "row",
"container_horiz_alignment": "flex-start"
},
"type": "Group",
"id": "cmMsV",
"default_name": "Group BZ",
"elements": {
"cmMsa": "(MaterialIcon E, below)",
"cmMsd": "(Text U, below)"
},
"order": 1
}

NodeGX: Group

{
"id": "el_cmMsV",
"type": "Group",
"label": "Group BZ",
"parent": "root_bTIWz",
"parameters": {
"flexDirection": "row",
"justifyContent": "flex-start",
"width": {
"value": 100,
"unit": "%"
},
"minWidth": {
"value": 20,
"unit": "px"
},
"minHeight": {
"value": 20,
"unit": "px"
},
"sizeMode": "contentHeight",
"alignX": "center",
"backgroundColor": "transparent",
"marginTop": {
"value": 32,
"unit": "px"
},
"marginLeft": {
"value": 24,
"unit": "px"
},
"marginRight": {
"value": 24,
"unit": "px"
}
},
"children": [
"el_cmMsY",
"el_cmMsb"
]
}

Material icon (plugin element)​

A Group sized like the Bubble element, holding the icon itself. The icon names Material Icons' check glyph, and the project links the Material Icons font for it.

Bubble

{
"properties": {
"height": 24,
"left": 0,
"top": 0,
"width": 24,
"icon": "check",
"icon_color": "rgba(11, 159, 111, 1)",
"order": 1,
"fixed_width": true,
"vert_alignment": "center"
},
"type": "materialicons-Materialicon",
"id": "cmMsY",
"default_name": "MaterialIcon E",
"order": 1
}

NodeGX: Group, Icon

[
{
"id": "el_cmMsY",
"type": "Group",
"label": "MaterialIcon E",
"parent": "el_cmMsV",
"parameters": {
"alignY": "center",
"width": {
"value": 24,
"unit": "px"
},
"height": {
"value": 24,
"unit": "px"
},
"sizeMode": "explicit"
},
"children": [
"icon_cmMsY"
]
},
{
"id": "icon_cmMsY",
"type": "net.noodl.visual.icon",
"label": "MaterialIcon E glyph",
"parent": "el_cmMsY",
"parameters": {
"iconIconSource": {
"class": "material-icons",
"code": "check",
"codeAsClass": false
},
"iconSize": {
"value": 24,
"unit": "px"
},
"iconColor": "rgba(11, 159, 111, 1)"
}
}
]

Text​

The text comes out of its TextExpression. font_face: "Inter:::regular" becomes fontFamily and fontWeight, and the project links Inter from Google Fonts.

Bubble

{
"properties": {
"text": {
"entries": {
"0": "Feature numero uno"
},
"type": "TextExpression"
},
"bold": false,
"font_face": "Inter:::regular",
"height": 22,
"left": 0,
"top": 0,
"width": 228,
"font_color": "rgba(107, 114, 128, 1)",
"font_size": 16,
"line_height": 1.2,
"order": 2,
"fit_width": true,
"fixed_width": false,
"font_family": "Inter",
"font_weight": "400",
"margin_left": 8,
"padding_top": 0,
"padding_left": 0,
"padding_right": 0,
"padding_bottom": 0,
"vert_alignment": "center"
},
"type": "Text",
"id": "cmMsb",
"default_name": "Text U",
"order": 1
}

NodeGX: Text

{
"id": "el_cmMsb",
"type": "Text",
"label": "Text U",
"parent": "el_cmMsV",
"parameters": {
"alignY": "center",
"sizeMode": "contentSize",
"color": "rgba(107, 114, 128, 1)",
"fontSize": {
"value": 16,
"unit": "px"
},
"fontWeight": "400",
"fontFamily": "Inter",
"lineHeight": 1.2,
"marginLeft": {
"value": 8,
"unit": "px"
},
"text": "Feature numero uno"
}
}

Fonts and icon fonts​

NodeGX does not load a web font by itself, and Bubble does. So the project's head code gets one Google Fonts link carrying every family and weight the page uses, and Material Icons when an icon needs it. This is the project setting made for this sample.

NodeGX (nodegx.project.json)

{
"settings": {
"headCode": "<link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n<link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n<link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;600&family=Material+Icons&display=swap\" rel=\"stylesheet\">"
}
}

Button​

The This element is hovered condition becomes the button's hover state. Bubble's 200 ms fade on that change is the element's own transitions, which are not carried yet.

Bubble

{
"properties": {
"text": {
"entries": {
"0": "Benefit"
},
"type": "TextExpression"
},
"bold": false,
"font_face": "Inter:::600",
"height": 40,
"left": 0,
"top": 0,
"width": 60,
"font_alignment": "center",
"font_color": "rgba(107, 114, 128, 1)",
"font_size": 16,
"line_height": 1.4,
"background_style": "none",
"border_style": "none",
"order": 2,
"fixed_width": true,
"font_family": "Inter",
"font_weight": "600",
"max_width_css": "90px",
"min_width_css": "60px",
"min_height_css": "40px",
"vert_alignment": "center",
"responsive_alignment": "left"
},
"states": {
"bTGVB": {
"condition": {
"next": {
"type": "Message",
"name": "is_hovered"
},
"properties": {
"element_id": "bTGMw"
},
"type": "ThisElement"
},
"properties": {
"font_color": "rgba(22, 30, 46, 1)"
},
"type": "State"
}
},
"type": "Button",
"id": "cmMfz",
"default_name": "Button B",
"order": 2,
"transitions": {
"font_color": {
"fn": "ease-in-out",
"duration": 200
}
}
}

NodeGX: Button

{
"id": "el_cmMfz",
"type": "net.noodl.controls.button",
"label": "Button B",
"parent": "root_bTIWz",
"parameters": {
"alignY": "center",
"width": {
"value": 100,
"unit": "%"
},
"minWidth": {
"value": 60,
"unit": "px"
},
"maxWidth": {
"value": 90,
"unit": "px"
},
"minHeight": {
"value": 40,
"unit": "px"
},
"sizeMode": "contentHeight",
"backgroundColor": "transparent",
"color": "rgba(107, 114, 128, 1)",
"fontSize": {
"value": 16,
"unit": "px"
},
"fontWeight": "600",
"fontFamily": "Inter",
"lineHeight": 1.4,
"textAlignX": "center",
"label": "Benefit",
"useLabel": true
},
"stateParameters": {
"hover": {
"color": "rgba(22, 30, 46, 1)"
}
}
}

Image​

The protocol-relative src gains https:. The fixed width (50) and the 10:11 aspect ratio give the height (55). The element wears the style it wore in Bubble, as a variant.

Bubble

{
"properties": {
"height": 55,
"left": 0,
"top": 0,
"width": 50,
"zindex": 2,
"src": {
"entries": {
"0": "//example.com/logo.png"
},
"type": "TextExpression"
},
"order": 3,
"fit_height": false,
"margin_left": 0,
"single_width": true,
"min_width_css": "50px",
"single_height": true,
"min_height_css": "55px",
"vert_alignment": "center",
"use_aspect_ratio": true,
"aspect_ratio_width": 10,
"aspect_ratio_height": 11
},
"type": "Image",
"id": "cmMfn",
"default_name": "Image A",
"style": "Image_simple_image_",
"order": 3
}

NodeGX: Image

{
"id": "el_cmMfn",
"type": "Image",
"label": "Image A",
"parent": "root_bTIWz",
"variant": "Image_simple_image_",
"parameters": {
"alignY": "center",
"width": {
"value": 50,
"unit": "px"
},
"minWidth": {
"value": 50,
"unit": "px"
},
"height": {
"value": 55,
"unit": "px"
},
"sizeMode": "explicit",
"marginLeft": {
"value": 0,
"unit": "px"
},
"src": "https://example.com/logo.png",
"objectFit": "contain"
}
}

The style Image_simple_image_, as a variant in nodegx.styles.json:

{
"name": "Image_simple_image_",
"typename": "Image",
"parameters": {},
"stateParameters": {},
"stateTransitions": {}
}

A Text with the link's words and its hover colour. This Link goes to a URL, which is not wired yet; a Link to a page also gets a Router Navigate on its click.

Bubble

{
"properties": {
"text": {
"entries": {
"0": "FAQ"
},
"type": "TextExpression"
},
"bold": false,
"font_face": "Inter:::regular",
"height": 45,
"left": 0,
"top": 0,
"width": 200,
"font_color": "rgba(107, 114, 128, 1)",
"font_size": 16,
"line_height": 1.2,
"vertical_centering": true,
"order": 4,
"fit_width": true,
"fit_height": true,
"font_family": "Inter",
"font_weight": "400",
"padding_top": 0,
"padding_left": 0,
"single_width": false,
"min_width_css": "0px",
"padding_right": 0,
"single_height": false,
"min_height_css": "40px",
"padding_bottom": 0,
"horiz_alignment": "flex-start"
},
"states": {
"0": {
"condition": {
"next": {
"type": "Message",
"name": "is_hovered"
},
"properties": {
"element_id": "bTGMw"
},
"type": "ThisElement"
},
"properties": {
"font_color": "rgba(22, 30, 46, 1)"
},
"type": "State"
}
},
"type": "Link",
"id": "cmMwK",
"default_name": "Link E",
"order": 4,
"transitions": {
"font_color": {
"fn": "ease",
"duration": 200
}
}
}

NodeGX: Text

{
"id": "el_cmMwK",
"type": "Text",
"label": "Link E",
"parent": "root_bTIWz",
"parameters": {
"minHeight": {
"value": 40,
"unit": "px"
},
"sizeMode": "contentSize",
"alignX": "left",
"color": "rgba(107, 114, 128, 1)",
"fontSize": {
"value": 16,
"unit": "px"
},
"fontWeight": "400",
"fontFamily": "Inter",
"lineHeight": 1.2,
"text": "FAQ"
},
"stateParameters": {
"hover": {
"color": "rgba(22, 30, 46, 1)"
}
}
}

Shape​

A Group with the shape's colour, size and rounded corners.

Bubble

{
"properties": {
"height": 80,
"left": 0,
"top": 0,
"width": 160,
"zindex": 2,
"border_roundness": 5,
"bgcolor": "rgba(60, 13, 153, 1)",
"order": 5,
"fit_height": false,
"margin_left": 41,
"single_width": true,
"min_width_css": "160px",
"single_height": true,
"min_height_css": "80px",
"nonant_alignment": "aa"
},
"type": "Shape",
"id": "cmMpD",
"default_name": "Shape A",
"order": 5
}

NodeGX: Group

{
"id": "el_cmMpD",
"type": "Group",
"label": "Shape A",
"parent": "root_bTIWz",
"parameters": {
"width": {
"value": 160,
"unit": "px"
},
"minWidth": {
"value": 160,
"unit": "px"
},
"height": {
"value": 80,
"unit": "px"
},
"sizeMode": "explicit",
"backgroundColor": "rgba(60, 13, 153, 1)",
"borderRadius": {
"value": 5,
"unit": "px"
},
"marginLeft": {
"value": 41,
"unit": "px"
}
}
}

Floating group​

A Group with the same shadow and corners, unmounted (mounted: false) because it starts hidden. It does not float yet: Bubble pins a Floating Group to the window, and this Group scrolls with the page. Its children are left out of this sample.

Bubble

{
"properties": {
"height": 287,
"left": 0,
"top": 0,
"width": 1190,
"zindex": 2,
"boxshadow_horizontal": 0,
"border_roundness": 5,
"boxshadow_style": "outset",
"is_visible": false,
"background_style": "bgcolor",
"bgcolor": "rgba(255, 255, 255, 1)",
"background_image": {
"entries": {
"0": ""
},
"type": "TextExpression"
},
"boxshadow_color": "rgba(170,170,170,0.5)",
"boxshadow_spread": 1,
"fit_height": false,
"single_width": false,
"min_width_css": "98%",
"single_height": false,
"use_max_width": true,
"min_height_css": "100%",
"horiz_alignment": "flex-start",
"container_layout": "column",
"background_size_cover": true,
"background_color_if_empty_image": "rgba(255,255,255,1)",
"order": 6
},
"type": "FloatingGroup",
"id": "cmMwz",
"default_name": "FloatingGroup A",
"name": "Floating Mobile Nav Menu",
"order": 6
}

NodeGX: Group

{
"id": "el_cmMwz",
"type": "Group",
"label": "Floating Mobile Nav Menu",
"parent": "root_bTIWz",
"parameters": {
"flexDirection": "column",
"width": {
"value": 100,
"unit": "%"
},
"minWidth": {
"value": 98,
"unit": "%"
},
"mounted": false,
"minHeight": {
"value": 100,
"unit": "%"
},
"sizeMode": "contentHeight",
"alignX": "left",
"backgroundColor": "rgba(255, 255, 255, 1)",
"borderRadius": {
"value": 5,
"unit": "px"
},
"boxShadowEnabled": true,
"boxShadowOffsetX": {
"value": 0,
"unit": "px"
},
"boxShadowOffsetY": {
"value": 0,
"unit": "px"
},
"boxShadowBlurRadius": {
"value": 0,
"unit": "px"
},
"boxShadowSpreadRadius": {
"value": 1,
"unit": "px"
},
"boxShadowColor": "rgba(170,170,170,0.5)"
}
}

A workflow​

Two Bubble workflows from the same page. Clicking Button B triggers the custom event Scroll To with the text "benefit"; the event scrolls to Group BZ only when its text is "benefit".

Bubble

[
{
"properties": {
"element_id": "cmMfz"
},
"type": "ButtonClicked",
"id": "cmMwl",
"actions": {
"0": {
"properties": {
"arguments": {
"0": {
"param_id": "_LEGACY_",
"arg_value": "benefit"
}
},
"custom_event": "cmMvZ"
},
"type": "TriggerCustomEvent",
"id": "cmMwo"
}
}
},
{
"properties": {
"event_name": "Scroll To",
"parameters": {
"0": {
"btype_id": "text",
"param_id": "_LEGACY_",
"param_name": "Workflow's text"
}
},
"event_color": "orange"
},
"type": "CustomEvent",
"id": "cmMvZ",
"actions": {
"0": {
"properties": {
"condition": {
"next": {
"args": "benefit",
"type": "Message",
"name": "equals"
},
"type": "CurrentWorkflowItem"
},
"element_id": "cmMsV",
"offset": -80
},
"type": "ScrollToElement",
"id": "cmMvf"
}
}
}
]

NodeGX: Send Event, Receive Event, Condition, Expression

[
{
"id": "act_cmMwo",
"type": "Event Sender",
"label": "Trigger cmMvZ",
"parameters": {
"channelName": "cmMvZ",
"propagation": "global"
}
},
{
"id": "ev_cmMvZ",
"type": "Event Receiver",
"label": "Custom event Scroll To",
"parameters": {
"channelName": "Scroll To"
}
},
{
"id": "ac_1",
"type": "Condition",
"label": "Only when CurrentWorkflowItem's equals \"benefit\"",
"parameters": {}
},
{
"id": "ex_2",
"type": "Expression",
"label": "Only when CurrentWorkflowItem's equals \"benefit\"",
"parameters": {
"expression": "(param_payload == \"benefit\")",
"evaluateAtLoad": true
}
},
{
"id": "act_cmMvf",
"type": "Expression",
"label": "ScrollToElement Group BZ (small action)",
"parameters": {
"expression": "/* ScrollToElement Group BZ */ true"
}
}
]

And the connections that make it run, in order:

FromOutputToInput
el_cmMfz (Button B)onClickact_cmMwo (Trigger cmMvZ)sendEvent
act_cmMvf (ScrollToElement Group BZ (small action))doneel_cmMsV (Group BZ)scrollIntoView
ev_cmMvZ (Custom event Scroll To)payloadex_2 (Only when CurrentWorkflowItem's equals "benefit")param_payload
ex_2 (Only when CurrentWorkflowItem's equals "benefit")resultac_1 (Only when CurrentWorkflowItem's equals "benefit")condition
ev_cmMvZ (Custom event Scroll To)eventReceivedac_1 (Only when CurrentWorkflowItem's equals "benefit")eval
ac_1 (Only when CurrentWorkflowItem's equals "benefit")ontrueact_cmMvf (ScrollToElement Group BZ (small action))run

The rules​

Everything the dictionary knows, including what the example page does not use. A row marked not in the dictionary yet is a Bubble feature with no NodeGX answer so far. It is listed so you know.

Elements​

BubbleNodeGXNotes
a page (type: "Page")a /Pages/<name> component: a Page (title, urlPath; the index page gets "") over a root GroupThe page's own layout, gaps, padding and background go on the root Group.
Group, Shape, Popup, FloatingGroup, GroupFocus, AlertGroupA Popup or GroupFocus starts with mounted: false. A Floating Group does not float yet: it scrolls with the page. A Shape keeps its box, but its shape type (ellipse, triangle) is not read yet.
TextTextBBCode such as [b] and [sup] is stripped. A Text with a background or a border becomes a Group carrying the box around a Text, because a NodeGX Text has no box.
LinkText, plus a Navigate wired from its onClick when it links to a pageA Link to an external URL is not wired yet. An icon-only Link gets text: "".
ButtonButtontext becomes label, with useLabel: true.
Input, MultiLineInputText Inputplaceholder carries over. content_format password, email, number, phone or url sets type. A MultiLineInput gets type: "textArea".
CheckboxCheckboxtext becomes label.
Dropdown, RadioButtons, AutocompleteDropdownDropdownThe data source becomes an Expression wired to items.
ImageImagesrc gains https: when Bubble wrote it protocol-relative (//s3…). objectFit is contain, which is how Bubble shows an image. A fixed-width image with an aspect ratio takes its height from the ratio.
Icon, and the Material Icons plugin elementa Group holding an IconA Material icon becomes iconIconSource: { class: "material-icons", code: "<name>" }, and the project links the Material Icons font in its head code.
RepeatingGroupa Group holding a Repeater whose template is a row component /Rows/<page> <name>The cell's elements go into the row component. A Component Inputs node gets one port per field the cell reads, and the data source becomes an Expression wired to items.
a reusable elementa /Reusable/<name> component, placed where the element was usedThe instance keeps only its position and size.
a custom statea Variable named <element>.<state>Its default value carries over.
HTML, Video, GoogleMap, SliderInput, DateInput, FileInput, PictureInput, any other plugin elementa labelled Group placeholderNot in the dictionary yet. The page still opens, and the placeholder says what stood there.

Layout​

Bubble's responsive engine is flexbox underneath, so most of it maps one property to one parameter.

BubbleNodeGXNotes
container_layout row or column, row_gap / column_gap, container_horiz_alignment / container_vert_alignmentflexDirection, rowGap / columnGap, alignItems / justifyContent
single_width / single_height (fixed), fit_width / fit_height, min_width_css / max_width_css, horiz_alignmentwidth / height in px, sizeMode, minWidth / maxWidth, alignXStretch becomes width: 100%. fixed_width is ignored on a new-engine page, where single_width is the flag.
vert_alignment of a child in a rowalignY
container_layout: "relative" (Align to parent) with nonant_alignmentthe biggest child stays in flow and gives the container its height; the others are position: absolute with alignX / alignY from the nonantThe nonant's letter order is a guess: every example so far reads the same either way.
a fixed container, or a page with no container_layout (the pre-2021 engine)children position: absolute, placed by marginLeft / marginTop from left / top, inside a position: relative parentIt renders the same and edits badly. Re-flowing it into rows and columns is a judgement for a person or an AI.
rotation_angletransformRotation
how a row shares its width among children that are not fixedequal sharesNot in the dictionary yet: Bubble's rule is not known, so columns with different minimum widths come out a different size.

Style​

BubbleNodeGXNotes
bgcolor, background_style (gradient or none), border_*, border_roundness, boxshadow_*, opacitybackgroundColor, backgroundGradient, borderStyle / borderWidth / borderColor, borderRadius, boxShadow*, opacity
font_color, font_size, font_family / font_face: "Inter:::600", line_height, letter_spacing, font_alignmentcolor, fontSize, fontFamily + fontWeight, lineHeight, letterSpacing, textAlignXEvery family that is not built into the browser is added to one Google Fonts link in the project's head code, with the weights the page uses.
padding_*, margin_*padding*, margin*
settings.client_safe.color_tokens / font_tokenscustom design tokens with Bubble's own names (--color_primary_default), plus an _rgb triple for each colourBubble's rgba(var(--color_primary_default_rgb), 0.8) keeps working unchanged.
a style (styles.<id>)a variant { name, typename, parameters, stateParameters } in nodegx.styles.json, which the element wears as variantThe element drops every parameter the variant already sets.
a condition This element is hovered / focused / pressedstateParameters.hover / focused / pressedA style's transitions become the variant's stateTransitions. An element's own transitions are not carried yet, so its hover change is instant.
any other conditionone Expression per changed property: (<condition>) ? <state value> : <base value>is_visible drives mounted, or visible when the element keeps its space while hidden. This input is (not) valid has no NodeGX state yet.

Workflows​

BubbleNodeGXNotes
ButtonClicked, ElementClickedthe element's onClick
PageLoadedthe Page's didMount
InputValueChangedthe input's onTextChanged
CustomEventReceive Event on a channel named after the event
the action chainone node per action: the event triggers the first, and each action's done triggers the nextAn action's Only when becomes a Condition between them, fed by an Expression.
TriggerCustomEventSend Event
NewThing, MakeChanges, DeleteThingCreate Record, Update Record, Delete RecordEach value becomes a prop-<field> input: a direct wire when it is one input's value, an Expression otherwise.
ChangePageNavigate to /Pages/<name>Page parameters are not carried yet.
GoPreviousPop Component Stack
OpenURLExternal Link
LogIn, SignUp, LogOut, ResetPasswordLog In, Sign Up, Log Out, Reset PasswordReset Password takes its token from the URL.
SetCustomState, DisplayGroupDataSet Variable
ShowElement, HideElementa Set Variable on <element>.mounted, which the element's mounted reads
ScrollToElement, SetFocusToElementan Expression that passes the signal on to the element's scrollIntoView or focusOther one-signal actions (ResetInputs, AnimateElement, …) keep their place in the chain with nothing on the end yet.
ScheduleAPIWorkflow, SendEmail, plugin actions, any other actionan Expression placeholder carrying the action's settings in a commentNot in the dictionary yet. The chain stays whole, so the workflow still runs past it.

Dynamic expressions​

A Bubble expression (Input A's value :count > 3) becomes one Expression node. Each value it reads is an input wired from the node that holds it; each operator is a line of JavaScript. For the operators one by one, see Coming from Bubble.

BubbleNodeGXNotes
Input A's value, Checkbox B's valuea wire from that element's value output
Current User, Current User is logged ina User node's id, email or authenticated
Get data from page URLPage Inputs, one pm-<name> output per parameter
Current page width / heightScreen Resolution
Get data from an external API (API Connector)one HTTP Request node per call, fetched when the page mountsThe call's parsed types give the field paths. Auth headers and keys are not carried.
Parent group's thing inside a repeating groupthe row component's Component Inputs
an operator not in the table__bubble("<name>", …) in the ExpressionNot in the dictionary yet. The page opens and the expression says what it was.

Data​

BubbleNodeGXNotes
user_types (data types)backend collections in the project (metadata.dbCollections)text, number, yes/no, date, list and another type become String, Number, Boolean, Date, Array and Pointer.
option setsan /Option sets/<name> component whose items output lists the optionsOne option in an expression becomes { value, display }.
privacy rulesnot converted yetThey use the same expression language, so they will be a table row. Until then a person writes the NodeGX security rules.