---
name: giraffe-sdk-developer
description: Use when building or debugging a custom app that runs embedded in Giraffe — anything importing @gi-nx/iframe-sdk, or using giraffeState, useGiraffeState or rpc.invoke, or working with RawSections, StackedSections, usages, flows, the project boundary, or Giraffe's geographic vs projected coordinate systems.
---

# Context

Giraffe is a geospatial mapping platform. Custom apps run in iframes and communicate with the parent Giraffe window via the `@gi-nx/iframe-sdk` package.

# Instructions

- Initially, only read the following pages.
- Read the SDK documentation main page at <https://gi-docs-beta.web.app/md/index.md>
- Read what the available types of state are at <https://gi-docs-beta.web.app/md/state.md>
- Read what the available commands are at <https://gi-docs-beta.web.app/md/functions.md>
- When developing an app using specific instructions, use the links in the above pages to discover more about the SDK API.
- Always verify the method and its associated arguments.
- If the user asks to add a particular usage, flow or block that is not in the active project, you can suggest searching the content library for it using `fetchContentPacks`.
- Never search the web for Giraffe related information. Always rely on the provided documentation links.

# Guidelines

- Use `useGiraffeState` hook for React apps
- Use `giraffeState.addListener` for vanilla JS
- Use `rpc.invoke(functionName, args)` for commands

# Key Concepts

## Giraffe Features

Giraffe has its own feature system that is separate from the underlying Mapbox GL map.

- **Giraffe RawSections** are the editable GeoJSON features that Giraffe manages (points, lines, polygons). They are stored per-project, have properties like `color`, `usage`, `levels`, `flow`, etc., and are persisted to the Giraffe backend. Use `getRawSections`, `createRawSection`, `updateRawSection`, and `deleteRawSection` to work with them. Raw Sections are not directly visible on the map until they are processed by the Giraffe engine into StackedSections. Read the standard properties of RawSections at <https://gi-docs.web.app/md/interfaces/RawPolygon.md>
- **Giraffe StackedSections** are the processed output of the Giraffe engine. Each RawSection is evaluated and can produce one or many StackedSections (e.g. a building with multiple levels). They carry computed properties like `_height`, `_baseHeight`, `area`, `grossArea`, `netArea`, etc. StackedSections are read-only — to make changes, modify the source RawSection and the engine will re-evaluate. Stacked Sections are rendered on the map. Read the computed properties at <https://gi-docs.web.app/md/interfaces/StackedSection.md>
- sometimes they are referred to as 'evaluated' or 'baked' sections
- **Mapbox layers/features** are the vector tiles, GeoJSON sources, and style layers rendered by the Mapbox GL map underneath. These are read-only context layers (e.g. satellite imagery, cadastral boundaries, terrain). Use `queryRenderedFeatures` to read them, and `setFeatureState`/`getFeatureState` to set transient visual state on them.

Modifying a Giraffe feature uses `updateRawSection`, not `setFeatureState`. The `setFeatureState`/`removeFeatureState`/`getFeatureState` functions only apply to Mapbox source features.

## Project Boundary

GeoJSON feature that defines the boundary of the project site.

## Usages

Usages assign shared properties to lots of sections. For example, a "Residential" usage might set `color`, `levels` properties on all sections that have that usage. This way, you can change the appearance and behavior of many sections by updating a single usage.

## Flows

- Flows are reusable functions attached to features.
- Flows are made up of nodes and edges. The entry to a flow is a `read feature` node and the ouputs are `write feature` nodes.
- Nodes have a unique instance ID and a type (also an ID that references the node definition). Edges connect an output of one node to an input of another.
- Find the available flow nodes at <https://gi-docs-beta.web.app/md/nodes.md>. This is where you can find the ID for the definitions, and dig deeper to find the inputs and outputs. Do not make assumptions about flow structure.
- A collection of useful flows is available at <https://storage.googleapis.com/feaso-prod/FlowPreview/flowExamples-v4.json>

## Coordinate Systems

Giraffe uses two coordinate systems:

- **Geographic coordinates (`GeoCoordinate` = `[longitude, latitude]`)** — All RawSection and StackedSection `geometry.coordinates` are in WGS84 geographic coordinates. This is the only format accepted by `createRawSection` and `updateRawSection`. You must always pass geographic coordinates when writing features.
- **Projected coordinates (`CalcProjectedCoordinate` = `[x, y]` metres)** — A local metric coordinate system relative to the project origin. The Giraffe engine uses this internally to compute accurate areas, lengths, and heights. It is **never** used as input — it is computed by the engine.

**Important:** `_projected` is a **read-only computed property** on StackedSections. It is the engine's internal metric representation of the geometry. Do NOT set or pass `_projected` when creating or updating RawSections — it will be ignored. Always use `geometry.coordinates` with geographic coordinates.

`getProjector()` is provided as a utility for app-side geometry calculations (e.g. constructing shapes in metres, then converting to `[lng, lat]` before passing to `createRawSection`):

```ts
import { getProjector } from '@gi-nx/iframe-sdk';

const proj = getProjector();
if (proj) {
  // Do geometry work in metres, then convert back to lng/lat for the RawSection
  const origin = [151.2093, -33.8688] as [number, number];
  const [x, y] = proj.forward(origin);
  const offsetGeo = proj.inverse([x + 50, y + 50]); // 50m NE
  await rpc.invoke('createRawSection', [
    { type: 'Feature', geometry: { type: 'Point', coordinates: offsetGeo }, properties: {} }
  ]);
}
```
