Static Ads Lab
Concepts

JSON trees

The structured document model that represents every visual element in editable image ads and design templates.

A JSON tree is a Figma-like node hierarchy in JSON. It represents every element in an editable image ad or a design template — frames, text, rectangles, images, and effects.

Mental model

Think of a JSON tree as a small, structured document you can read and mutate. Editable image ads and design templates both produce trees. The fields and node types are the same; the difference is purpose: a design template is the layout blueprint, an editable image ad is the realized creative bound to a brand, product, and audience.

The shared schema lives in the workspace package @sal/json-tree. Public consumers don't need to install it — the API returns standard JSON.

Node types

TypeDescription
FRAMEContainer with layout properties (position, size, auto-layout)
TEXTText content with font, size, color, alignment
RECTANGLEShapes with fills (solid colors, images, gradients)
EFFECTDrop shadows, blur, and other visual effects on a node

Each node has a unique id (UUID). The tree's root is typically a FRAME containing all other nodes.

Common shapes

A text node

{
  "id": "2c210453-5a8f-4c41-bcae-604a7994e223",
  "type": "TEXT",
  "characters": "The GOAT of leggings",
  "fontSize": 48,
  "fontFamily": "Inter",
  "fills": [{ "type": "SOLID", "color": { "r": 0, "g": 0, "b": 0, "a": 1 } }]
}

An image rectangle

{
  "id": "ac39635c-cd64-42ec-a420-da71ee472cb5",
  "type": "RECTANGLE",
  "fills": [
    {
      "type": "IMAGE",
      "imageFillUrl": "https://cdn.example.com/lifestyle.jpg"
    }
  ]
}

Mutating a tree

Two paths:

  1. node_overrides at creation time — pass { [nodeId]: { characters | imageFillUrl } } in POST /v1/image-ads. Simpler. Use when you know what to override before generation.
  2. PATCH /v1/image-ads/:id with the full updated current_json_tree. Use after generation, especially when iterating in an editor.

Always send the entire tree on PATCH, not a diff.

Image rules

JSON trees never embed raw image bytes. Image fills carry a public URL (imageFillUrl). When you need to swap an image:

  • Upload the binary first via POST /v1/images (multipart) and use the returned src URL, OR
  • Provide your own publicly-accessible URL.

Base64 in JSON is rejected.

Endpoints

JSON trees are part of the Image ads and Design templates resources. There are no standalone JSON tree endpoints.

Pitfalls

  • The tree is large for typical ads (a few KB to ~100 KB). Don't log the full tree in production.
  • Node IDs are stable across versions of the same ad — use them to track "the headline node" reliably.
  • The shape evolves. Treat unknown fields as "preserve as-is" rather than failing on them.

Prompt for your agent

Read https://www.staticadslab.com/docs/resources/json-trees.mdx and write a helper findTextNodeByCharacters(tree, query) that returns the node whose characters include the query string.