# Qwik quick start

Mount a 400-pixel-high diagram with two connected nodes, keep edits in serializable signals, and use the live instance from a Fit view button.

Framework bindings are thin skins over one headless model: specs describe your intent, live models hold the data, and the engine owns behavior.

## Prerequisites

Use an existing Qwik 1.x application with `@builder.io/qwik` satisfying `^1.5.0` and `@grafloria/element` satisfying `^0.5.0`; see the [JavaScript quick start](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/javascript-quick-start) for the shared engine and renderer prerequisites.

Keep your application's Qwik Vite configuration: no Grafloria-specific Vite plugin is required. This example runs in a server-rendered Qwik City application; the binding creates its live diagram in a browser-only task at document ready.

## 1. Install the binding and its peers

Run this in your application directory:

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

The Qwik package re-exports the shared spec types, so the component and its data types use one import site.

## 2. Mount a controlled canvas

Bind Qwik signals to [`GrafloriaFlow`](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/grafloria-qwik#grafloriaflow) rather than React state; see the [React quick start](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/react-quick-start) for the shared [`NodeSpec`](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/grafloria-renderer-instance-nodespec#nodespec) and [`EdgeSpec`](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/grafloria-renderer-instance-edgespec#edgespec) canvas setup.

The signals contain only plain data. Both change callbacks are QRLs created with Qwik's `$()`: they return the edited specs to the signals bound to `nodes` and `edges`.

`onInit$` gives you the mounted [`DiagramInstance`](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/grafloria-renderer-instance-diagraminstance#diagraminstance). Keep it in a signal marked with `noSerialize()` rather than asking Qwik to serialize a live renderer. The button uses that instance's `fitView()` to frame the content.

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

export default component$(() => {
  const nodes = useSignal<NodeSpec[]>([
    {
      id: 'extract',
      position: { x: 80, y: 120 },
      size: { width: 180, height: 72 },
      label: 'Extract',
    },
    {
      id: 'load',
      position: { x: 380, y: 120 },
      size: { width: 180, height: 72 },
      label: 'Load',
    },
  ]);
  const edges = useSignal<EdgeSpec[]>([
    {
      id: 'extract-load',
      source: 'extract',
      target: 'load',
      sourceHandle: 'right',
      targetHandle: 'left',
    },
  ]);
  const instance = useSignal<NoSerialize<DiagramInstance>>();

  return (
    <section>
      <button
        type="button"
        disabled={!instance.value}
        onClick$={() => instance.value?.fitView(40)}
      >
        Fit view
      </button>
      <GrafloriaFlow
        nodes={nodes.value}
        edges={edges.value}
        fitView
        onNodesChange$={$((next: NodeSpec[]) => {
          nodes.value = next;
        })}
        onEdgesChange$={$((next: EdgeSpec[]) => {
          edges.value = next;
        })}
        onInit$={$((diagram: DiagramInstance) => {
          instance.value = noSerialize(diagram);
        })}
        style={{ height: '400px' }}
      />
    </section>
  );
});
```

The canvas draws Extract and Load side by side, with an edge from Extract's right port to Load's left port. `fitView` frames the initial content. The Fit view button stays disabled until `onInit$` supplies the instance.

![Extract and Load appear side by side with a right-pointing connecting arrow. The Fit view button sits above the canvas.](https://atloriaassets.blob.core.windows.net/assets/a438221c-c1af-407c-b9e6-a56c986db846/716c8c7fa06f395860eebb304430000e.png)

## 3. Run and edit the diagram

Start your Qwik application's development server:

```bash
npm run dev
```

Open the address printed by your application. Drag either node and use Fit view to frame the diagram again. The binding projects node and edge change events into specs for your callbacks; changes to the controlled arrays feed back into the mounted instance through `setNodes()` and `setEdges()`.

You now have a sized, editable canvas, controlled node and edge state, and instance access for your own controls. The binding disposes its diagram and removes its event subscriptions on unmount; do not dispose it in `onInit$`.

## Choose the state owner

Keep `nodes`, `edges`, and their change callbacks when your application owns the specs. For an uncontrolled canvas, use `defaultNodes` and `defaultEdges` instead: they seed the diagram at mount, rather than supplying ongoing controlled updates.

For more on serializable state and live objects, see [Qwik: state and resumption](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/qwik-state-and-resumption). For canvas sizing, see [Theme a canvas](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/theme-a-canvas).

## Where next

- Try the [live Qwik demos](https://grafloria.com/demos-qwik/) and inspect their source.
- Read [State and event flow](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/state-and-event-flow) for controlled editing.
- Use [Instance and lifecycle](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/instance-and-lifecycle) for instance access and teardown.
- Continue to [Qwik: custom content and kits](https://bench-grafloria-61d.atloria.app/p/bench-grafloria-61d-mQCmWpDrxv/developer/qwik-custom-content-and-kits) for custom node components.
