Skip to content
D
Documentation

JavaScript quick start

tutorial
2 min readUpdated

JavaScript in 10 minutes

Mount a live diagram with render, then use the returned DiagramInstance to fit, observe, save, and restore it.

Grafloria has one headless model underneath its JavaScript and framework bindings. The renderer connects that model to the canvas; the instance is the live handle you keep for later operations.

Prerequisites

  • A modern browser with ES modules.
  • Node.js and npm for installing the packages and running an ESM development server.
  • No framework. The packages are ESM; the starter below uses Vite.

1. Install the packages

bash
npm install @grafloria/element @grafloria/renderer @grafloria/engine
npm install --save-dev vite

@grafloria/element provides the JavaScript render() entry point. The renderer and engine satisfy its peer dependencies.

Add these scripts to package.json:

json
{
  "type": "module",
  "scripts": {
    "dev": "vite",
    "build": "vite build"
  }
}

2. Give the diagram a sized target

Create index.html with a container that has a real height. A diagram in a zero-height element has no area in which to draw.

html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Grafloria JavaScript quick start</title>
    <style>
      html, body, #canvas { margin: 0; height: 100%; }
      #canvas { width: 100%; height: 400px; }
      #actions { position: fixed; z-index: 1; top: 1rem; left: 1rem; }
    </style>
  </head>
  <body>
    <div id="actions">
      <button id="save" type="button">Save</button>
      <button id="load" type="button">Load</button>
    </div>
    <div id="canvas" style="width: 100%; height: 400px;"></div>
    <script type="module" src="/src/main.js"></script>
  </body>
</html>

3. Render real nodes and an edge

Create src/main.js. Pass a data spec first and the target element second. The call returns the live instance, and fitView: true frames the initial content.

js
import { render } from '@grafloria/element';

const canvas = document.getElementById('canvas');
const saveButton = document.getElementById('save');
const loadButton = document.getElementById('load');

if (!canvas || !saveButton || !loadButton) {
  throw new Error('The diagram controls are missing');
}

canvas.style.width = '100%';
canvas.style.height = '400px';

const api = render({
  nodes: [
    {
      id: 'a',
      position: { x: 60, y: 80 },
      size: { width: 180, height: 80 },
      data: { label: 'Ingest' },
    },
    {
      id: 'b',
      position: { x: 380, y: 80 },
      size: { width: 180, height: 80 },
      data: { label: 'Publish' },
    },
  ],
  edges: [{ id: 'e1', source: 'a', target: 'b' }],
}, canvas, { fitView: true });

api.on('node:doubleclick', () => {
  console.log('A node was double-clicked');
});

saveButton.addEventListener('click', () => {
  localStorage.setItem('diagram-text', api.exportText());
});

loadButton.addEventListener('click', () => {
  const saved = localStorage.getItem('diagram-text');
  if (saved !== null) {
    api.loadText(saved);
    api.fitView();
    api.renderNow();
  }
});
Two labelled nodes connected by an edge in the rendered canvas.

Run the page with:

bash
npm run dev

The browser shows two labelled nodes connected by an edge. You can drag nodes, draw connections, pan, and zoom. Double-clicking a node logs a message. render() accepts a data object, not Mermaid text; use loadText() when the input is Mermaid-compatible text.

4. Save and restore the document

The Save button stores the string returned by exportText(). The export is Mermaid-compatible and includes Grafloria's lossless sidecar by default, so positions and styling can round-trip. Load passes that string to loadText(), which reconciles it into the mounted diagram, then fitView() and renderNow() frame and repaint the restored content.

For JSON document persistence, use api.getModel() with the engine's serializer; the text round-trip above keeps this first example at the instance front door.

What you have at the end

You have a mounted, interactive diagram and one instance that lets your application:

  • subscribe to diagram events with on();
  • frame content with fitView();
  • export and restore Mermaid-compatible text with exportText() and loadText();
  • force an immediate repaint with renderNow().

When the page tears down, call api.dispose() from your application’s unmount or close handler. Do not dispose it immediately after rendering: disposal removes the live diagram.

Where next

Was this page helpful?