Nuxt Module
Wraps @macrulez/visual-linker-vue for Nuxt — auto-imports <VisualLinker> and useVisualLinker, registers the v-vl-block/v-vl-port directives, and makes the visualLinker key of nuxt.config.ts the shared configuration of every diagram in the project.
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@macrulez/visual-linker-nuxt'],
visualLinker: {
theme: { line: '#6366f1', lineHover: '#312e81' },
lines: { curve: 'smoothstep', jumps: true },
markers: { end: { shape: 'arrow', hover: { size: 10 } } },
blocks: { draggable: true, drag: { grid: 20 } },
},
})The options of the module are exactly the engine's configuration; to change them while the app runs, see Shared Configuration.
Configuration
The visualLinker key is a VisualLinkerConfig — the same object that createVisualLinker() and the config prop of <VisualLinker> take, so there is no separate list of module-only names to learn. Its groups:
theme— color tokens, written as CSS variables. See Themes.lines— curve, color, width, dashed, opacity, the visual states,bezier,smoothstep,routing,jumps,animated.markers—startandendmarkers, with their own states, and the per-shapesizes.ports— the built-in dot (show,radius,fill,stroke, the states), the defaultsideandoffset, andspread.labels— the look of library-drawn connection labels, with states.blocks—draggableanddrag: { grid, bounds }.interaction—hover,highlight,selectableandclipToScrollParents.
Every group and field is described in Configuration. Everything is optional, and the module hardcodes no default of its own: a field left out falls through to the engine's built-in value, so a future change to core's default is never silently shadowed by the Nuxt layer.
The options travel through runtimeConfig.public.visualLinker, so they must be plain JSON data: strings, numbers, booleans, objects and arrays. For blocks.drag.bounds that means 'container' or an inset object, not an HTMLElement — an element can still be given to one diagram through its own config or a block.
Example — every group at once:
// nuxt.config.ts
export default defineNuxtConfig({
modules: ['@macrulez/visual-linker-nuxt'],
visualLinker: {
theme: { line: '#6366f1', lineHover: '#312e81', portFill: '#ffffff' }, // colors in one place
lines: {
curve: 'smoothstep', // orthogonal routing for every connection
width: 2,
hover: { width: 3 }, // thicker under the pointer
smoothstep: { cornerRadius: 10 }, // rounder bends than the 8px default
routing: { avoidObstacles: true, padding: 12 }, // go around other blocks
jumps: { radius: 6 }, // hop over crossing lines
animated: { shape: 'dots', speed: 50 }, // a dotted pattern flows along every line
},
markers: {
end: { shape: 'arrow', hover: { size: 10 } }, // an arrowhead that grows on hover
sizes: { arrow: 8 }, // arrowheads a bit bigger than the other shapes
},
ports: { radius: 5, hover: { radius: 7 }, spread: { gap: 16, padding: 8 } }, // bigger dots, spread over a shared side
labels: { background: '#ffffff', fontSize: 12 }, // the pill behind label text
blocks: { draggable: true, drag: { grid: 20, bounds: 'container' } }, // every block can be dragged
interaction: { hover: true, highlight: true, selectable: true, clipToScrollParents: 'pin' }, // reacting, keyboard-operable lines
},
})Changing it at runtime
The module installs the configuration as the app-wide shared configuration, a reactive object, so any component can change it and every diagram follows — for example to switch themes:
import { darkTheme, useVisualLinkerConfig } from '@macrulez/visual-linker-vue'
const shared = useVisualLinkerConfig()
shared.theme = darkThemeA call site's own config still wins over it, field by field.
Registration
The module automatically:
- Registers
<VisualLinker>as a global component - Auto-imports
useVisualLinker - Registers the
v-vl-block/v-vl-portdirectives in a universal plugin — on the server too, so thedata-vl-*discovery attributes are already in the server-rendered HTML - Installs the
visualLinkerconfiguration in that same plugin as the shared configuration for every<VisualLinker>/useVisualLinker()call, which merge it under their ownconfig
<VisualLinker> and useVisualLinker are already SSR-safe on the server — the engine and its drawing layer only exist client-side, after mount. No <ClientOnly> wrapper is needed anywhere.