# Build a Qwik diagram

Render a resumable diagram with [`GrafloriaFlow`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-qwik#grafloriaflow) and keep its callbacks in QRLs.

## The first idea

Qwik is a thin binding over Grafloria's shared headless engine: you provide node and edge data to the component, and the engine renders and manages the diagram.

## Prerequisites

Use Qwik 1.x (`@builder.io/qwik` 1.5 or later) with a Qwik SSR application. The Qwik package is version 0.10.6 and requires `@grafloria/engine` 0.3.x, `@grafloria/renderer` 0.4.x, and `@grafloria/element` 0.4.x.

Install the binding and its peer packages:

```bash
npm install @grafloria/qwik @grafloria/engine @grafloria/renderer @builder.io/qwik @grafloria/element
```

## Render the flow

Create a route component such as `src/routes/index.tsx`. Type the data with `NodeSpec` and [`EdgeSpec`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-renderer-instance-edgespec#edgespec), then bind the signal values to the flow. The [`DiagramInstance`](https://atloria.dev/p/grafloria-h7YM7amryF/developer/grafloria-renderer-instance-diagraminstance#diagraminstance) passed to `onInit$` gives you the mounted diagram handle.

```tsx title="src/routes/index.tsx"
import { component$, $, useSignal } from '@builder.io/qwik';
import {
  GrafloriaFlow,
  type DiagramInstance,
  type EdgeSpec,
  type NodeSpec,
} from '@grafloria/qwik';

export default component$(() => {
  const nodes = useSignal<NodeSpec[]>([
    { id: 'start', position: { x: 80, y: 120 }, label: 'Start' },
    { id: 'finish', position: { x: 360, y: 120 }, label: 'Finish' },
  ]);
  const edges = useSignal<EdgeSpec[]>([
    { id: 'start-finish', source: 'start', target: 'finish' },
  ]);

  const handleInit = $((instance: DiagramInstance) => {
    instance.fitView();
  });
  const handleNodesChange = $((next: NodeSpec[]) => {
    nodes.value = next;
  });

  return (
    <GrafloriaFlow
      nodes={nodes.value}
      edges={edges.value}
      onInit$={handleInit}
      onNodesChange$={handleNodesChange}
      style={{ width: '800px', height: '400px' }}
    />
  );
});
```

![The mounted Qwik flow displays the Start and Finish boxes connected by an edge.](https://atloriaassets.blob.core.windows.net/assets/a438221c-c1af-407c-b9e6-a56c986db846/ec9e48d8d2bc2c832b15457a85b8ba0e.png)

The mounted component renders two labelled boxes joined by a link. `fitView()` frames the content when the instance is ready, and `onNodesChange$` writes edited nodes back to the signal. The `$` suffix keeps both callbacks in QRLs that Qwik can load lazily.

1. Start the Qwik SSR dev server. In the Grafloria Qwik demo repository, use the SSR mode explicitly:

```bash
npx vite --config apps/demos-qwik/vite.config.ts --mode ssr
```

Open `http://localhost:4290/` in that repository, or start your own Qwik application with its normal SSR command. The server-rendered page contains the diagram host; Qwik resumes the component in the browser rather than walking the component tree through a hydration pass.

## What you have at the end

## Where to go next

- [How Grafloria works](https://atloria.dev/p/grafloria-h7YM7amryF/developer/how-grafloria-works) explains the shared engine, model, and instance.
- [Auto-layout a diagram](https://atloria.dev/p/grafloria-h7YM7amryF/developer/auto-layout-a-diagram) adds declarative layout.
- [Create custom nodes](https://atloria.dev/p/grafloria-h7YM7amryF/developer/create-custom-nodes) maps node types to Qwik components.
- Try the [Qwik demos](https://grafloria.com/demos-qwik/) to see the binding running.
