# Installation

Kookie Flow is a React component that draws a node graph with WebGL. You install it with
React Three Fiber and three.js, which do the drawing, and KookieUI v2, which supplies the
theme and the controls. It needs React 19 and a browser with WebGL 2.

## Choose the package

`@kushagradhawan/kookie-flow-react` is the normal React entry. The renderer lives in
`@kushagradhawan/kookie-flow-webgl`; graph logic lives in `@kushagradhawan/kookie-flow-core`.
The old `@kushagradhawan/kookie-flow` import forwards to the new packages.

These 0.2.0 candidates are not published. Build all sibling packages and pack them with pnpm:

```bash
pnpm install --frozen-lockfile
pnpm --filter @kushagradhawan/kookie-flow... run build
pnpm test:packages
pnpm --filter '@kushagradhawan/kookie-flow*' -r pack --pack-destination ./artifacts
```

Install all four archives in your app, together with
`vendor/kushagradhawan-kookie-ui-react-0.0.0-flow.2.tgz`. This UI archive preserves the tested Flow
appearance. Current UI v2 source is a separate upgrade and is not interchangeable with it.

## Install the renderer peers

| Package | Supported range |
| --- | --- |
| `react`, `react-dom` | ^19.2.8 |
| `three` | ~0.186.0 |
| `@react-three/fiber` | ^9.7.0 |
| `@react-three/drei` | ^10.7.8 |
| `@kushagradhawan/kookie-ui-react` | 0.0.0-flow.2 from the supplied archive |

The core alone needs no React, Three, KookieUI or browser globals. Node tooling and CJS require
Node 24+. Both module formats and their declarations are tested outside the monorepo.

`KookieFlow` uses hooks and WebGL. In Next.js App Router, import it from a `"use client"` file.
The canvas has no stylesheet of its own: its appearance comes from the KookieUI stylesheet.

## Add the theme

Import the stylesheet once and put a `Theme` at the root of your app. The canvas reads its
colours and corners from its own inherited `Theme` scope, so the graph follows the theme's
light or dark appearance and its radius. The [Theming](/styling/theming) chapter covers what
the canvas reads.

```tsx title="app/layout.tsx"
import "@kushagradhawan/kookie-ui-react/styles.css";
import { Theme } from "@kushagradhawan/kookie-ui-react";

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <Theme>{children}</Theme>
      </body>
    </html>
  );
}
```

## Give the canvas a height

The canvas fills its parent: its container is 100% wide and 100% tall. A parent with no
height of its own resolves that 100% to zero, and the graph draws into a box you can't see.
Give the parent a height, or place it in a layout that hands it one.

```tsx title="app/editor/page.tsx"
"use client";

import { KookieFlow, type Edge, type Entity } from "@kushagradhawan/kookie-flow-react";

const entities: Entity[] = [
  { id: "a", type: "note", position: { x: 0, y: 0 }, data: { label: "First node" } },
];
const edges: Edge[] = [];

export default function EditorPage() {
  return (
    <div style={{ display: "grid", gridTemplateRows: "auto 1fr", height: "100dvh" }}>
      <header>My editor</header>
      <KookieFlow entities={entities} edges={edges} />
    </div>
  );
}
```

The grid gives its second row whatever height the header leaves, and the canvas fills that
row. A fixed height such as `height: 480` on a wrapping `div` works too. The canvas watches
its box, so it redraws when the box changes size.

`entities` and `edges` sit at module scope here on purpose. The canvas rebuilds its copy of
the graph whenever it receives a new array, so an array written inline in JSX would rebuild
it on every render. [Controlled and uncontrolled state](/start/state) explains how the canvas
holds your graph.

## Import from the plugins subpath

Three hooks live in a second entry point, `@kushagradhawan/kookie-flow-react/plugins`:

- `useClipboard` copies, cuts and pastes the selection. See [Clipboard and cloning](/data/clipboard).
- `useKeyboardShortcuts` binds your own keys. See [Keyboard](/interaction/keyboard).
- `useContextMenu` holds the state of a right-click or long-press menu you draw yourself. See [Context menus](/interaction/context-menu).

`useClipboard` reads the canvas's internal store, so call it from a component you render as a
child of `KookieFlow`. Called anywhere else, it throws.

```tsx
import { KookieFlow, type Edge, type Entity } from "@kushagradhawan/kookie-flow-react";
import { useClipboard, useKeyboardShortcuts } from "@kushagradhawan/kookie-flow-react/plugins";

function ClipboardKeys() {
  const { copy, cut, paste } = useClipboard();
  useKeyboardShortcuts({
    bindings: { "mod+c": copy, "mod+x": cut, "mod+v": () => paste() },
  });
  return null;
}

export function Board({ entities, edges }: { entities: Entity[]; edges: Edge[] }) {
  return (
    <KookieFlow entities={entities} edges={edges}>
      <ClipboardKeys />
    </KookieFlow>
  );
}
```

These bindings listen on the whole page, so `mod+c` copies the graph's selection even while
someone copies text elsewhere on it. [Clipboard and cloning](/data/clipboard) shows how to limit
them to the canvas.

A paste adds nodes to the canvas without reporting them to `onEntitiesChange`. Read
[what is reported](/start/state#what-is-reported-and-what-is-not) before you pair the
clipboard with state you hold yourself.

## Use it with TypeScript

Both entry points ship their own type declarations. The declarations import types from
`three`, which ships none of its own, so add `@types/three` beside `@types/react`:

```bash
pnpm add -D @types/three
```

Import types with `import type`, so they leave no trace in your bundle:

```ts
import type { Edge, Entity, KookieFlowInstance } from "@kushagradhawan/kookie-flow-react";
import type { UseClipboardReturn } from "@kushagradhawan/kookie-flow-react/plugins";
```

Next, the [Quick start](/start/quick-start) builds a two-node graph you can wire up by
dragging.
