x-schema-designer

<x-schema-designer> is a one-line preset for typed-field schema graphs — ERDs, API payload shapes, GraphQL types, event schemas, or anything whose nodes are "things with labelled, typed fields". Under the hood it stamps an <x-flow> canvas plus three inspector mount points (node / row / edge) that the AlpineFlow Schema addon drives client-side.

Reach for <x-schema-designer> when you want the batteries-included schema surface. For generic flow canvases — workflow editors, DAG runners, mind maps — use <x-flow> directly.

Installation

The preset requires the JS addon to be registered on the Alpine side. Follow the optional addons steps, then add the schema import alongside the core bundle in resources/js/app.js:

// Core from WireFlow vendor bundle
import AlpineFlow from '../../vendor/getartisanflow/wireflow/dist/alpineflow.bundle.esm.js';
// Schema addon from npm
import AlpineFlowSchema from '@getartisanflow/alpineflow/schema';

document.addEventListener('alpine:init', () => {
    window.Alpine.plugin(AlpineFlow);
    window.Alpine.plugin(AlpineFlowSchema);
});

Rebuild after editing the import:

npm run build

Minimal example

<x-schema-designer :nodes="$tables" :edges="$relationships" />

The $tables array follows the x-flow-schema-node shape — one entry per node, each with data.label and data.fields:

$tables = [
    [
        'id' => 'user',
        'position' => ['x' => 0, 'y' => 0],
        'data' => [
            'label' => 'User',
            'fields' => [
                ['name' => 'id',    'type' => 'uuid', 'key' => 'primary'],
                ['name' => 'email', 'type' => 'text', 'required' => true],
            ],
        ],
    ],
];

$relationships = [];

That renders the canvas, wires the default node / row / edge inspectors, enables keyboard-to-connect, and uses the avoidant edge router — no further setup needed.

Props

Prop Type Default Description
nodes array [] Initial nodes. Same shape as <x-flow>.
edges array [] Initial edges. Each edge should carry sourceHandle / targetHandle to pin onto a specific field.
defaultEdgeType string 'avoidant' Default edge renderer. 'avoidant' is best for schema graphs because it routes around tables; switch to 'bezier' / 'smoothstep' / 'step' / 'straight' if you prefer.
keyboardConnect bool true Enable the addon's keyboard-to-connect flow (select a row, press a key, click another row).
collapseBidirectionalEdges bool false When true, edges between the same two nodes in opposite directions are visually merged into a single two-headed arrow.

The table above lists the schema-specific props; every other <x-flow> prop is forwarded to the underlying <x-flow> one-to-one (viewport, sync, listen, background, minimap, controls, pannable, zoomable, fitView, snap, edgesReconnectable, interactive, nodeTypes, config, minZoom/maxZoom, preventCycles, colorMode, selectionOnDrag, computeMode, fitViewOnInit, history, autoLayout, backgroundGap, wireIgnore, fullscreenTarget, containerHeight), so this preset is a true drop-in replacement for <x-flow> with the schema inspectors already wired. Drop down to a raw <x-flow> only if you want to place the three x-schema-*-inspector mount points by hand (see <x-schema-node-inspector>).

Slot overrides

Slot Purpose
Default slot Free-form children rendered inside <x-flow> — use this for toolbars, minimaps, context menus, extra panels.
<x-slot:node-inspector> Replaces the node inspector body. Receives the canvas Alpine scope — selectedNode and inspector are in scope.
<x-slot:row-inspector> Replaces the row inspector body. selectedRow and inspector are in scope.
<x-slot:edge-inspector> Replaces the edge inspector body. selectedEdge and inspector are in scope.

Each inspector slot is rendered inside the addon's directive wrapper, so the Alpine inspector scope (selectedNode, inspector.addField(...), etc.) is already in scope — your markup just needs to consume it.

Overriding the node inspector

<x-schema-designer :nodes="$tables" :edges="$relationships">
    <x-slot:node-inspector>
        <flux:card class="p-4">
            <flux:heading size="sm" x-text="selectedNode?.data?.label ?? 'No table selected'" />
            <template x-if="selectedNode">
                <flux:button
                    variant="ghost"
                    size="xs"
                    @click="inspector.addField({ name: 'created_at', type: 'timestamp' })"
                >
                    Add created_at
                </flux:button>
            </template>
        </flux:card>
    </x-slot:node-inspector>
</x-schema-designer>

Omitting a slot keeps the addon's default UI for that pane — mix and match as needed.

Adding canvas children

The default slot is a pass-through to <x-flow>, so you can layer any other WireFlow component inside:

<x-schema-designer :nodes="$tables" :edges="$relationships">
    <x-flow-panel position="top-right">
        <flux:button wire:click="inferReferences">Infer references</flux:button>
    </x-flow-panel>

    <x-flow-toolbar />
</x-schema-designer>

Server-side cascade

Pair the preset with the WithSchemaDesigner trait to mutate $this->nodes / $this->edges from the server with cascade semantics that match the client addon.

See also