Figma Adapter

Figma Variables exports include tool-specific metadata and reference syntax. This adapter normalizes Figma exports into Variable Design Standard (VDS) format.

Supported export formats

This adapter handles two export formats:

  1. Plugin export format: Generated by Figma plugins (available on all plans). Uses @ collection prefixes, $ group prefixes, and $variable_metadata.
  2. REST API format: From the Local Variables endpoint (Enterprise plan only). Uses valuesByMode with internal IDs.

The normalization steps below focus on the plugin export format, which is more commonly used.

Plugin export input format

Plugin exports include:

  • $collection_metadata at collection level
  • $variable_metadata on each variable
  • Reference syntax: {@collection.token} (with @ prefix)
  • Mode values in $variable_metadata.modes

Example Figma export:

{
  "@primitives": {
    "$collection_metadata": {
      "name": "Primitives",
      "figmaId": "VariableCollectionId:502:189",
      "modes": [
        { "key": "light", "name": "Light" },
        { "key": "dark", "name": "Dark" }
      ]
    },
    "$color": {
      "primary": {
        "$type": "color",
        "$value": "#0066cc",
        "$variable_metadata": {
          "name": "color/primary",
          "figmaId": "VariableID:502:227",
          "modes": {
            "light": "#0066cc",
            "dark": "#004499"
          }
        }
      }
    }
  }
}
                    

Normalization steps

Step 1: Extract collection metadata

Move $collection_metadata to $extensions on the collection group.

Before:

{
  "@primitives": {
    "$collection_metadata": {
      "name": "Primitives",
      "figmaId": "VariableCollectionId:502:189"
    }
  }
}
                    

After:

{
  "primitives": {
    "$extensions": {
      "figma": {
        "collectionId": "VariableCollectionId:502:189",
        "name": "Primitives"
      }
    }
  }
}
                    

Step 2: Normalize collection names

Remove @ prefix from collection names. The @ prefix is added by the export plugin to distinguish collections from groups. In Figma UI, you name the collection “Primitives” (without @).

Before: "@primitives" (from export)

After: "primitives" (normalized)

Similarly, group names have $ prefixes in exports (e.g., $color, $green). These are added by the plugin because Figma uses / as path separators in variable names (e.g., color/green/200), and the export converts these to nested JSON objects with $ prefixes to avoid conflicts with DTCG reserved properties like $type and $value.

Step 3: Extract variable metadata

Move $variable_metadata to $extensions on each variable.

Before:

{
  "color": {
    "primary": {
      "$type": "color",
      "$value": "#0066cc",
      "$variable_metadata": {
        "name": "color/primary",
        "figmaId": "VariableID:502:227"
      }
    }
  }
}
                    

After:

{
  "color": {
    "primary": {
      "$type": "color",
      "$value": "#0066cc",
      "$extensions": {
        "figma": {
          "variableId": "VariableID:502:227",
          "name": "color/primary"
        }
      }
    }
  }
}
                    

Step 4: Normalize reference syntax

Convert Figma reference syntax to canonical format.

Figma uses: {@collection.token}

Variable Design Standard (VDS) uses: {collection.token}

Before:

{
  "color": {
    "text": {
      "primary": {
        "$type": "color",
        "$value": "{@primitives.$color.primary}"
      }
    }
  }
}
                    

After:

{
  "color": {
    "text": {
      "primary": {
        "$type": "color",
        "$value": "{primitives.color.primary}"
      }
    }
  }
}
                    

Step 5: Handle modes

If $variable_metadata.modes exists, move mode values to $value object.

Before:

{
  "color": {
    "surface": {
      "$type": "color",
      "$value": "#ffffff",
      "$variable_metadata": {
        "modes": {
          "light": "#ffffff",
          "dark": "#000000"
        }
      }
    }
  }
}
                    

After:

{
  "color": {
    "surface": {
      "$type": "color",
      "$value": {
        "light": "#ffffff",
        "dark": "#000000"
      },
      "$extensions": {
        "figma": {
          "variableId": "VariableID:502:227"
        }
      }
    }
  }
}
                    

Step 6: Validate naming

Check that normalized names follow Variable Design Standard (VDS) naming convention (see Naming).

  • Names MUST use dot-separated paths
  • Names MUST be lowercase
  • Names MUST NOT include platform prefixes

Complete conversion example

Figma export:

{
  "@primitives": {
    "$collection_metadata": {
      "name": "Primitives",
      "figmaId": "VariableCollectionId:502:189"
    },
    "$color": {
      "primary": {
        "$type": "color",
        "$value": "#0066cc",
        "$variable_metadata": {
          "name": "color/primary",
          "figmaId": "VariableID:502:227",
          "modes": {
            "light": "#0066cc",
            "dark": "#004499"
          }
        }
      }
    }
  },
  "@tokens": {
    "$color": {
      "text": {
        "primary": {
          "$type": "color",
          "$value": "{@primitives.$color.primary}",
          "$variable_metadata": {
            "name": "color/text/primary",
            "figmaId": "VariableID:502:228"
          }
        }
      }
    }
  }
}
                    

Normalized Variable Design Standard (VDS):

{
  "primitives": {
    "$extensions": {
      "figma": {
        "collectionId": "VariableCollectionId:502:189",
        "name": "Primitives"
      }
    },
    "color": {
      "primary": {
        "$type": "color",
        "$value": {
          "light": "#0066cc",
          "dark": "#004499"
        },
        "$extensions": {
          "figma": {
            "variableId": "VariableID:502:227",
            "name": "color/primary"
          }
        }
      }
    }
  },
  "tokens": {
    "color": {
      "text": {
        "primary": {
          "$type": "color",
          "$value": {
            "light": "{primitives.color.primary}",
            "dark": "{primitives.color.primary}"
          },
          "$extensions": {
            "figma": {
              "variableId": "VariableID:502:228",
              "name": "color/text/primary"
            }
          }
        }
      }
    }
  }
}
                    

Round-trip considerations

If you need to sync changes back to Figma:

  • Preserve Figma IDs in $extensions.figma.variableId and $extensions.figma.collectionId
  • Keep mode keys the same as the Figma mode keys
  • Maintain reference paths that Figma can resolve

Failure modes

If normalization fails:

  • Missing $variable_metadata breaks Figma ID preservation
  • Invalid reference syntax causes resolution failures
  • Mode mismatches break mode-based workflows
  • Naming violations cause validation failures

Validation checklist

After normalization, verify:

  • All $collection_metadata moved to $extensions
  • All $variable_metadata moved to $extensions
  • All @ prefixes removed from collection names
  • All references use canonical format ({path})
  • Mode values moved to $value object
  • Names follow Variable Design Standard (VDS) naming convention

Workflow

Designers author variables in Figma. Changes flow through export, normalization, review, and release.

Who does what

  • Designer: authors variables in Figma, exports JSON
  • Design Engineer: runs adapter, opens PR, reviews changes
  • CI: validates normalized JSON

Workflow steps

  1. Designer exports variables from Figma (Dev Mode plugin or REST API).
  2. Design Engineer runs Figma adapter to normalize export JSON.
  3. Design Engineer commits normalized JSON to version control.
  4. Design Engineer opens PR for review.
  5. Reviewers check naming, types, references (see Change Control).
  6. After merge, CI generates build outputs.

What gets reviewed

  • Variable names follow naming convention (Naming)
  • References resolve correctly
  • Modes are limited (light, dark)
  • No duplicate values when base tokens exist
  • Breaking changes are documented

Authoring checklist

Before exporting from Figma:

  • Use semantic alias tokens for UI intent, not raw palette values
  • Keep modes limited (example: light, dark)
  • Follow naming convention (dot-separated paths, lowercase)
  • Use references instead of duplicating values

Artifacts that change

  • Figma export JSON (input, not committed)
  • Normalized Variable Design Standard (VDS) JSON (committed, reviewed)
  • Generated CSS/TypeScript files (output, not committed)

REST API format handling

For Enterprise plan users with REST API access, the input format differs:

{
  "variables": {
    "VariableID:502:227": {
      "id": "VariableID:502:227",
      "name": "color/green/200",
      "resolvedType": "COLOR",
      "valuesByMode": {
        "502:0": {
          "r": 0.216,
          "g": 1,
          "b": 0.341,
          "a": 1
        }
      },
      "variableCollectionId": "VariableCollectionId:502:189"
    }
  },
  "variableCollections": {
    "VariableCollectionId:502:189": {
      "id": "VariableCollectionId:502:189",
      "name": "Primitives",
      "modes": [{ "modeId": "502:0", "name": "Light" }]
    }
  }
}
                    

REST API normalization requires:

  1. Convert valuesByMode to $value object with mode names
  2. Convert RGBA objects to color format (hex or colorSpace object)
  3. Build variable hierarchy from /-separated names
  4. Resolve variable aliases (which use VariableAlias type)
  5. Map collection/mode IDs to names

Out of scope

  • Real-time sync with Figma (handle via version control)
  • Conflict resolution (handle via PR review)
  • Figma plugin development (see Plugin API)