Key concepts
Three ideas unlock the whole app: what flows on the wires, how nodes connect, and how one value can mean something different for every element.
If you only learn three things before building, learn these. Everything else in DNA is a variation on them.
1. Collections — the things on the wire
Almost everything that travels between nodes is a collection: a spreadsheet of things. Each row is one item, and each column is an attribute those items carry.
| @P (position) | @Cd (colour) | @pscale (size) |
|---|---|---|
| 0, 0, 0 | red | 1.0 |
| 1, 0, 0 | green | 0.5 |
Points, mesh vertices, shape outlines, even plain rows of numbers — they all share this row-and-column shape. Once you see a collection as a table, every node becomes "a thing that adds rows, removes rows, or edits a column". Open the spreadsheet view on any node to see exactly what's flowing through.
Attribute names use an @ prefix when you reference them — @P is position, @Cd is colour, @id is each row's unique number. You'll see these everywhere.
Read more in Collections.
2. Connections — wiring nodes together
You build by dragging a wire from one node's output into another node's input. The downstream node reads the collection coming in, does its thing, and passes a new one out:
A scatter node takes geometry in and sends points out.
A colour node reads the rows, writes the
@Cdcolumn, and passes the same rows along.A merge node stacks the rows of two collections into one.
Because every collection is the same underlying table, you can mix steps freely — scatter points on a shape, colour them from a table, then turn them into curves. When a node needs a particular kind of input, DNA converts what you give it automatically where it makes sense.
If a node misbehaves, check the kind of its input — points, geometry, curves, a table. The spreadsheet and the node's badges tell you what you're feeding it.
3. Context — one rule, many answers
Here's the idea that makes node graphs click. A single node doesn't hold just one value. When it feeds many elements — many points, many copies, many loop passes — a value can resolve differently for each one.
The classic example: scatter 200 points, then add an The Expression language node and write one rule:
@Cd = @id / @total
Each point reads its own @id (0 through 199), divides by the total, and gets a brightness from 0 to 1 — a smooth ramp across all 200 points, from a single line. You never wrote a loop. You described what happens to one element, and the app applied it across the whole bag.
The same idea powers copies and loops: the utility.iterator hands each copy its own @index, and a loop.for_start hands each pass its own pass number. You author the relationship once; every element, copy, or pass fills in its own number.
A value only varies per element if it actually is a per-element attribute. A plain number typed into a parameter is one value shared by everything. To get variety, read an attribute (@id, @index, @path_t) or feed a list instead of a single value.
Read more in Context: per-element values.