Model or dataset
relation-graph/relation-graph avatar
relation-graph/relation-graph

relation-graph: A Slot-Based Graph Component for React, Vue 2, Vue 3, Svelte and Web Components

relation-graph is an relationship graph component for React/Vue/Svelte relationship data visualization/edit. Through its slot-based customization model, users can fully customize graph elements with plain React/Vue/Svelte/HTML components, relation-graph also uses an LLM-friendly architecture and provides knowledge content.

2,278 stars514 forksJavaScriptMIT

At a glance

What is it?
relation-graph renders relationship data as an interactive graph and lets you replace nodes and lines with your own framework components. It is a good fit when the graph is part of a larger app and you want to keep control of the markup; it is a poor fit if you need a database-backed graph platform or a server-side layout engine.
Who is it for?
Adopt relation-graph if your graph lives inside an existing React, Vue or Svelte application and you want nodes rendered as your own components rather than as library-controlled SVG. Do not adopt it if you need server-side rendering of the layout, a graph database, or a component that is still on the v2 line, because v3 moved to a multi-platform package split with separate installs per framework.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 118 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The problem relation-graph solves: graph rendering without surrendering your components

Most graph libraries own the markup of a node. You pass a label and a colour, and the library draws a circle with text. That is fine until a node needs a status badge, an avatar, a progress ring, or a click target that behaves like the rest of your application. relation-graph takes the opposite position. Its README describes the component as one that lets users "fully customize graphical elements using common HTML elements, Vue components, React components" through slots. The node is a slot. You decide what goes in it.

The second problem it addresses is the drawing board case. The README states that beyond typical relationship data display, relation-graph "supports being used as a drawing board", where you place arbitrary content and connect elements by setting an id on the elements you want to connect and defining element lines. That turns a graph component into a lightweight canvas for zooming, dragging and creating connections between things that are not necessarily data records.

The audience is therefore front-end engineers building an admin tool, a lineage viewer, an org chart or an internal diagramming surface inside a single-page application. It is not aimed at teams who want a hosted graph product or a query language.

How the slot model and the package split fit together

The architecture is a rendering component plus a layout engine, wrapped per framework. The React example imports RelationGraph, RGHooks, RGMiniView, RGSlotOnNode, RGNodeShape and RGSlotOnView from @relation-graph/react, and the application wraps the graph in an RGProvider. Data arrives as a single object with a rootId, a nodes array and a lines array. Each node carries id, text, optional width and height, and a free-form data object; each line carries from, to and text. In the README example the data object holds a myicon string, which the custom node component would read to pick an icon.

Rendering is driven by options rather than by markup. The example sets defaultLineShape, defaultNodeShape, defaultNodeWidth, defaultNodeHeight, defaultLineTextOnPath, defaultExpandHolderPosition and reLayoutWhenExpandedOrCollapsed, plus a layout block with layoutName set to 'center'. The graph instance is obtained through RGHooks.useGraphInstance(), and the data is loaded imperatively with await graphInstance.setJsonData(staticJsonData), followed by moveToCenter() and zoomToFit(). That imperative handle is the main control surface: it is how you pan, zoom and re-layout after the initial mount.

Events come back through props. onNodeClick receives a node and an RGUserEvent, onLineClick receives a line, a link and an event, and both return a boolean, which is the conventional way to signal whether default handling should continue. The v3 release notes describe a multi-platform architecture, so the same core is packaged separately as @relation-graph/react, @relation-graph/vue, @relation-graph/vue2 and @relation-graph/svelte, with Web Components consumed from a URL import rather than a package install.

Installing and wiring a first graph

Installation is one package per framework. The README gives npm install --save @relation-graph/react for React, @relation-graph/vue for Vue 3, @relation-graph/vue2 for Vue 2 and @relation-graph/svelte for Svelte. Web Components are not installed at all: the README shows importing from https://esm.sh/@relation-graph/web-components and using the custom element <relation-graph></relation-graph>.

The React path has a wrapper requirement that is easy to miss. The root component must be wrapped in RGProvider, and the graph itself is rendered inside it. The graph container needs an explicit height, which the README example supplies with style={{ height: 'calc(100vh - 0px)' }}. If that container has no height, there is nothing for the layout to occupy, and this is the most common way a first attempt appears to render nothing.

Configuration is the options object. The documented keys in the example are debug, defaultLineShape, defaultNodeShape, defaultNodeWidth, defaultNodeHeight, defaultLineTextOnPath, layout (with layoutName), defaultExpandHolderPosition and reLayoutWhenExpandedOrCollapsed. Data is not passed as a prop in this example; it is pushed in through the instance handle inside a useEffect. Slots such as RGSlotOnNode and RGSlotOnView are declared as children of the RelationGraph element, which is where your custom node component is mounted.

The README also points to a visual configuration tool on relation-graph.com, which is the sensible place to work out layout and shape options before writing them into code.

Where relation-graph stops being the right tool

The layout runs in the browser. Nothing in the supplied material describes a server-side layout service or a way to compute positions without a DOM. If you need to render a graph to an image on a build server, or to produce a static layout for a PDF, this component does not appear to cover that case, and you would need to compute coordinates yourself and feed them in.

The slot model has a cost that the README does not discuss. Every node is a real component instance in your framework. A graph with thousands of visible nodes is thousands of mounted components, and the library's own drawing work sits underneath that. The documentation gives no guidance on a practical node ceiling, so the number has to be established on your own data. Treat any figure you have not measured as unknown.

The drawing board mode is the other place to be careful. Connecting arbitrary elements by id assumes those ids are stable and that you control the DOM. If your board content is produced by a third party or re-rendered by another framework, the id contract becomes fragile, and the README does not describe what happens when a referenced id disappears.

Finally, the version split matters. v3 packages are separate per framework, so a project still importing from the v2 line is not on the same API surface as the examples above. The v2.2.11 and v2.1.42 releases are older than v3.0.13, and the README's React example is written against v3 imports.

How it differs from Cytoscape.js and D3

Cytoscape.js is the closest comparison for graph rendering in a web app, and the difference is who owns the node. Cytoscape.js renders to a canvas and gives you styling through selectors and its own style model; you can put HTML overlays on top, but the node body itself is drawn by the library. relation-graph inverts that: the node body is your component, and the library handles positioning, lines, zooming and dragging around it. If your nodes need to be interactive in ways that only your framework can express, that inversion is the reason to pick relation-graph. If you need canvas-level performance on large graphs, Cytoscape.js's approach is the one designed for it.

D3 is a different kind of comparison because it is not a graph component. It gives you scales, forces and selections, and you assemble the graph yourself. D3's force simulation gives you control over every parameter and no component boundaries; relation-graph gives you a component with an options object and slots, which is faster to stand up and narrower in what you can change. Choosing between them is choosing between writing the layout loop and configuring one.

The drawing board mode has no direct equivalent in either. It is closer to a diagramming canvas than to a graph library, and the README treats it as a second use case of the same component rather than a separate product.

Maintenance, upgrades and the MIT licence

The repository is MIT licensed, which means you can use, modify and redistribute it, including in commercial and closed-source products, provided the copyright notice and permission notice are preserved. That is the standard reading of MIT and not legal advice; if licence obligations matter to your organisation, have counsel confirm how you handle third-party notices.

The release cadence visible in the supplied material is uneven. v3.0.13 landed on 2026-05-08, roughly thirteen months after v2.2.11 in March 2025, which itself came about eleven months after v2.1.42 in April 2024. That is a slow, occasional release rhythm rather than a continuous one, and the last push to the repository is dated 2026-05-20, shortly after the v3.0.13 release. The practical consequence is that you should expect to pin a version and carry it for a while rather than track a fast-moving main branch.

The upgrade cost between major lines is real. v3 is described as a rewrite that supports more platforms while keeping the code cleaner, and the packaging changed to one package per framework. Moving a v2 application to v3 is not a version bump; it is a change of import paths and, in the React case, the RGProvider wrapper and the hook-based instance access. Budget for that as a migration rather than a dependency update.

The knowledge-for-ai directory in the source tree is worth noting as a maintenance aid. Because the architecture is described as naturally LLM-friendly with knowledge files under <source-code-root>/knowledge-for-ai, you can point an assistant at the version you have checked out rather than relying on a general model's memory of the API. That is only useful if the directory is present and current at your pinned tag, which is something to confirm rather than assume.

Editorial conclusion

Adopt relation-graph if your graph lives inside an existing React, Vue or Svelte application and you want nodes rendered as your own components rather than as library-controlled SVG. Do not adopt it if you need server-side rendering of the layout, a graph database, or a component that is still on the v2 line, because v3 moved to a multi-platform package split with separate installs per framework. Before committing, verify three things against the version you install: that the RGProvider wrapper is required in your framework's binding, that the layout names you need exist in the version you pin, and that the knowledge-for-ai directory in the source tree matches the release tag you are on. The MIT licence removes the licensing question, so the real decision is whether slot-based rendering is the control you want.

Official sources

  1. License: MIT
  2. Project website
  3. README
  4. relation-graph/relation-graph on GitHub
  5. Releases
Community notes

Community notes