# Node Types

The scene graph supports 28 node types from Figma's Kiwi schema. Each node is identified by a GUID (`sessionID:localID`) and has a parent reference via `parentIndex`. The OpenPencil engine's `NodeType` union currently uses 17 of these types.

## Type Table

28 Figma schema types + 1 synthetic engine type. Types marked ✅ are in the engine's `NodeType` union (17 total).

| Type | ID | Description | Engine |
|------|----|-------------|--------|
| `DOCUMENT` | 1 | Root node, one per file | — |
| `CANVAS` | 2 | Page | ✅ |
| `GROUP` | 3 | Group container | ✅ |
| `FRAME` | 4 | Primary container (artboard), supports auto-layout | ✅ |
| `BOOLEAN_OPERATION` | 5 | Union/subtract/intersect/exclude result | |
| `VECTOR` | 6 | Freeform vector path | ✅ |
| `STAR` | 7 | Star shape | ✅ |
| `LINE` | 8 | Line | ✅ |
| `ELLIPSE` | 9 | Ellipse/circle, supports arc data | ✅ |
| `RECTANGLE` | 10 | Rectangle | ✅ |
| `REGULAR_POLYGON` | 11 | Regular polygon (3–12 sides, engine uses `POLYGON`) | ✅ |
| `ROUNDED_RECTANGLE` | 12 | Rectangle with smooth corners | ✅ |
| `TEXT` | 13 | Text with rich formatting | ✅ |
| `SLICE` | 14 | Export region | |
| `SYMBOL` | 15 | Component (main, engine uses `COMPONENT`) | ✅ |
| `INSTANCE` | 16 | Component instance | ✅ |
| `STICKY` | 17 | FigJam sticky note | |
| `SHAPE_WITH_TEXT` | 18 | FigJam shape | ✅ |
| `CONNECTOR` | 19 | Connector line between nodes | ✅ |
| `CODE_BLOCK` | 20 | FigJam code block | |
| `WIDGET` | 21 | Plugin widget | |
| `STAMP` | 22 | FigJam stamp | |
| `MEDIA` | 23 | Video/GIF | |
| `HIGHLIGHT` | 24 | FigJam highlight | |
| `SECTION` | 25 | Canvas section (organizational, top-level only) | ✅ |
| `SECTION_OVERLAY` | 26 | Section overlay | |
| `WASHI_TAPE` | 27 | FigJam washi tape | |
| `VARIABLE` | 28 | Variable definition node | |
| `COMPONENT_SET` | — | Variant group container (synthetic, mapped from `SYMBOL`) | ✅ |

### Engine NodeType Union (17 types)

The engine's `NodeType` uses simplified names. Some differ from the Kiwi schema:
- `COMPONENT` → Kiwi `SYMBOL` (ID 15)
- `COMPONENT_SET` → variant group container (no dedicated Kiwi ID, mapped from `SYMBOL` with variants)
- `POLYGON` → Kiwi `REGULAR_POLYGON` (ID 11)

```typescript
type NodeType =
  | 'CANVAS' | 'FRAME' | 'RECTANGLE' | 'ROUNDED_RECTANGLE'
  | 'ELLIPSE' | 'TEXT' | 'LINE' | 'STAR' | 'POLYGON'
  | 'VECTOR' | 'GROUP' | 'SECTION'
  | 'COMPONENT' | 'COMPONENT_SET' | 'INSTANCE'
  | 'CONNECTOR' | 'SHAPE_WITH_TEXT'
```

## Node Hierarchy

```
Document
├── Canvas (Page 1)
│   ├── Section (top-level only, title pill, auto-adopts siblings)
│   │   ├── Frame
│   │   │   └── ...children
│   │   └── Rectangle
│   ├── Frame
│   │   ├── Rectangle
│   │   ├── Text
│   │   └── Frame (nested)
│   │       ├── Ellipse
│   │       └── Instance (→ references Component)
│   ├── Component
│   │   └── ...children
│   ├── Group
│   │   └── ...children
│   └── BooleanOperation
│       └── ...operand shapes
└── Canvas (Page 2)
    └── ...
```

## Core Properties

Every node carries these fields (subset of `NodeChange`):

### Identity & Tree

- `guid` — unique identifier (`sessionID:localID`)
- `type` — node type enum
- `name` — display name
- `phase` — `CREATED` or `REMOVED`
- `parentIndex` — parent GUID + position string for z-ordering

### Transform

- `size` — width/height vector
- `transform` — 2×3 affine matrix
- `rotation` — degrees

### Appearance

- `fillPaints[]` — fill colors/gradients/images
- `strokePaints[]` — stroke colors
- `effects[]` — shadows, blurs
- `opacity` — 0–1
- `blendMode` — `NORMAL`, `MULTIPLY`, `SCREEN`, etc.

### Stroke

- `strokeWeight` — stroke thickness
- `strokeAlign` — `INSIDE` / `CENTER` / `OUTSIDE`
- `strokeCap` — `NONE` / `ROUND` / `SQUARE` / `ARROW_LINES` / `ARROW_EQUILATERAL`
- `strokeJoin` — `MITER` / `BEVEL` / `ROUND`
- `dashPattern[]` — dash/gap lengths

### Corners

- `cornerRadius` — uniform radius
- `cornerSmoothing` — squircle amount (0–1)
- Per-corner radii when `rectangleCornerRadiiIndependent` is true

### Visibility

- `visible` — show/hide
- `locked` — prevent editing

## Type-Specific Properties

### Text

`fontSize`, `fontName`, `lineHeight`, `letterSpacing`, `textAlignHorizontal`, `textAlignVertical`, `textAutoResize`, `textData` (characters, style overrides, baselines, glyphs)

### Vector

`vectorData` (vectorNetworkBlob, normalizedSize), `fillGeometry[]`, `strokeGeometry[]`, `handleMirroring`, `arcData`

### Layout (Frame)

`stackMode`, `stackSpacing`, `stackPadding`, `stackJustify`, `stackCounterAlign`, `stackPrimarySizing`, `stackCounterSizing`, `stackChildPrimaryGrow`, `stackChildAlignSelf`

### Component

`symbolData`, `componentKey`, `componentPropDefs[]`, `symbolDescription`

### Instance

`overriddenSymbolID`, `symbolData.symbolOverrides[]`, `componentPropRefs[]`, `componentPropAssignments[]`

## Paint

```typescript
interface Fill {
  type: 'SOLID' | 'GRADIENT_LINEAR' | 'GRADIENT_RADIAL' |
        'GRADIENT_ANGULAR' | 'GRADIENT_DIAMOND' | 'IMAGE'
  color: Color              // {r, g, b, a} 0–1 floats
  opacity: number           // 0–1
  visible: boolean
  blendMode?: BlendMode
  gradientStops?: GradientStop[]     // for gradients
  gradientTransform?: GradientTransform  // 2×3 matrix
  imageHash?: string        // for image fills
  imageScaleMode?: 'FILL' | 'FIT' | 'CROP' | 'TILE'
  imageTransform?: GradientTransform
}
```

## Effect

```typescript
interface Effect {
  type: 'DROP_SHADOW' | 'INNER_SHADOW' | 'LAYER_BLUR' |
        'BACKGROUND_BLUR' | 'FOREGROUND_BLUR'
  color: Color
  offset: { x: number; y: number }
  radius: number
  spread: number
  visible: boolean
}
```

## Stroke

```typescript
interface Stroke {
  color: Color
  weight: number
  opacity: number
  visible: boolean
  align: 'INSIDE' | 'CENTER' | 'OUTSIDE'
  cap?: 'NONE' | 'ROUND' | 'SQUARE' | 'ARROW_LINES' | 'ARROW_EQUILATERAL'
  join?: 'MITER' | 'BEVEL' | 'ROUND'
  dashPattern?: number[]
}
```
