Nodes API

The sdk.nodes namespace gives you full access to the design tree. You can read, create, update, delete, clone, and rearrange any node in the current design.

Reading nodes

getAll()

Returns every node in the design as an array.

const allNodes = sdk.nodes.getAll();
console.log(`Total nodes: ${allNodes.length}`);

getById(id)

Returns a single node by its ID, or undefined if not found.

const node = sdk.nodes.getById('abc123');
if (node) {
  console.log(node.type, node.styles.backgroundColor);
}

getByType(type)

Returns all nodes of a specific type. Use frame for containers/sections and text for text elements.

const frames = sdk.nodes.getByType('frame');
const textNodes = sdk.nodes.getByType('text');

getSelected()

Returns the nodes currently selected by the user. This is typically your starting point.

const selected = sdk.nodes.getSelected();
if (selected.length === 0) return; // Nothing selected

getChildren(parentId)

Returns the direct children of a node.

const children = sdk.nodes.getChildren(parentId);

getDescendants(parentId)

Returns all descendants recursively (children, grandchildren, etc.).

const all = sdk.nodes.getDescendants(sectionId);

getParent(nodeId)

Returns the parent node, or undefined for root nodes.

const parent = sdk.nodes.getParent(nodeId);

Modifying nodes

update(nodeId, changes)

Merges changes into a node. Pass any combination of top-level fields and styles.

// Change background color
sdk.nodes.update(nodeId, {
  styles: { backgroundColor: '#ff0000' },
});
 
// Rename a node
sdk.nodes.update(nodeId, {
  name: 'Hero Section',
});
 
// Set multiple styles at once
sdk.nodes.update(nodeId, {
  styles: {
    width: '100%',
    padding: '24px',
    borderRadius: '8px',
    display: 'flex',
    flexDirection: 'column',
    gap: '16px',
  },
});

updateMany(nodeIds, changes)

Applies the same changes to multiple nodes in a single batch. More efficient than calling update in a loop.

const children = sdk.nodes.getChildren(parentId);
const ids = children.map((n) => n.id);
 
sdk.nodes.updateMany(ids, {
  styles: { opacity: '0.5' },
});

create(type, parentId, attrs?)

Creates a new node inside the given parent. Returns the created node.

// Create a text element
const textNode = sdk.nodes.create('text', parentId, {
  styles: {
    textContent: 'Hello World',
    fontSize: '24px',
    color: '#000000',
  },
});
 
// Create a frame with layout
const container = sdk.nodes.create('frame', parentId, {
  name: 'Card',
  styles: {
    width: '300px',
    height: 'auto',
    padding: '16px',
    display: 'flex',
    flexDirection: 'column',
    gap: '8px',
    backgroundColor: '#ffffff',
    borderRadius: '12px',
  },
});

delete(nodeId)

Deletes a node and all its children.

sdk.nodes.delete(nodeId);

clone(nodeId)

Creates a deep copy of a node in the same parent. Returns the new node.

const copy = sdk.nodes.clone(nodeId);
if (copy) {
  sdk.nodes.update(copy.id, {
    styles: { left: '200px' },
  });
}

reparent(nodeId, newParentId, index?)

Moves a node to a different parent. Optionally specify the insertion index.

// Move to end of new parent
sdk.nodes.reparent(nodeId, newParentId);
 
// Move to specific position
sdk.nodes.reparent(nodeId, newParentId, 0); // First child

reorder(parentId, childId, newIndex)

Changes the position of a child within its current parent.

// Move to first position
sdk.nodes.reorder(parentId, childId, 0);

Node data shape

Every node has these fields:

  • idstring — Unique identifier
  • typestring — Element type (frame or text)
  • parentIdstring | null — Parent node ID
  • childrenstring[] — Child node IDs in order
  • variantIdstring | null — Variant this node belongs to
  • ordernumber — Sort order within parent
  • stylesRecord<string, any> — All CSS and custom styles
  • namestring — Display name in layers panel
  • lockedboolean — Whether the node is locked

Example: Auto-layout generator

A plugin that converts a flat list of children into a grid layout:

export default definePlugin({
  name: 'Auto Grid',
  description: 'Arrange children in a CSS grid',
  controls: {
    columns: { type: 'number', label: 'Columns', default: 3, min: 1, max: 12 },
    gap: { type: 'number', label: 'Gap (px)', default: 16, min: 0, max: 64 },
  },
  run(values, sdk) {
    const selected = sdk.nodes.getSelected()[0];
    if (!selected) return;
 
    sdk.nodes.update(selected.id, {
      styles: {
        display: 'grid',
        gridTemplateColumns: `repeat(${values.columns}, 1fr)`,
        gap: `${values.gap}px`,
      },
    });
  },
});