Draw every flow as one graph, merged on what it talks to

A node type can now say which outside thing its parameters point at, and
nodes sharing one — a broker topic, a URL, a bucket — are drawn as a single
neuron on a new /brain canvas. That makes the wiring which runs between
flows through a broker visible for the first time; no single flow's canvas
can show it. The key is read off stored parameters, so a credential
reference never reaches an id.

Layout is a d3 force simulation settled once and then frozen, lit by the
socket the editor already listens to: a neuron pulses when any node behind
it publishes, and its connections light as values pass.

Fixes the message pulse while here: interpolating the stroke against the
edge's `color-mix()` resting colour went through oklab and left the gamut,
which turned every pulse on both canvases fluorescent yellow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017MeiWk3Yq12n2pTvnQWYvt
This commit is contained in:
2026-08-16 22:59:31 +02:00
co-authored by Claude Fable 5
parent af3ba51571
commit 4bcd38354b
25 changed files with 790 additions and 4 deletions
+21
View File
@@ -24,6 +24,7 @@ import { Route as LayoutModulesRouteImport } from './routes/_layout/modules'
import { Route as LayoutHealthRouteImport } from './routes/_layout/health'
import { Route as LayoutAlertsRouteImport } from './routes/_layout/alerts'
import { Route as LayoutAdminRouteImport } from './routes/_layout/admin'
import { Route as CanvasBrainRouteImport } from './routes/_canvas/brain'
import { Route as LayoutFlowsIndexRouteImport } from './routes/_layout/flows/index'
import { Route as LayoutDashboardsIndexRouteImport } from './routes/_layout/dashboards/index'
import { Route as CanvasFlowsFlowNameRouteImport } from './routes/_canvas/flows/$flowName'
@@ -102,6 +103,11 @@ const LayoutAdminRoute = LayoutAdminRouteImport.update({
path: '/admin',
getParentRoute: () => LayoutRoute,
} as any)
const CanvasBrainRoute = CanvasBrainRouteImport.update({
id: '/brain',
path: '/brain',
getParentRoute: () => CanvasRoute,
} as any)
const LayoutFlowsIndexRoute = LayoutFlowsIndexRouteImport.update({
id: '/flows/',
path: '/flows/',
@@ -129,6 +135,7 @@ export interface FileRoutesByFullPath {
'/recover-password': typeof RecoverPasswordRoute
'/reset-password': typeof ResetPasswordRoute
'/signup': typeof SignupRoute
'/brain': typeof CanvasBrainRoute
'/admin': typeof LayoutAdminRoute
'/alerts': typeof LayoutAlertsRoute
'/health': typeof LayoutHealthRoute
@@ -148,6 +155,7 @@ export interface FileRoutesByTo {
'/recover-password': typeof RecoverPasswordRoute
'/reset-password': typeof ResetPasswordRoute
'/signup': typeof SignupRoute
'/brain': typeof CanvasBrainRoute
'/admin': typeof LayoutAdminRoute
'/alerts': typeof LayoutAlertsRoute
'/health': typeof LayoutHealthRoute
@@ -169,6 +177,7 @@ export interface FileRoutesById {
'/recover-password': typeof RecoverPasswordRoute
'/reset-password': typeof ResetPasswordRoute
'/signup': typeof SignupRoute
'/_canvas/brain': typeof CanvasBrainRoute
'/_layout/admin': typeof LayoutAdminRoute
'/_layout/alerts': typeof LayoutAlertsRoute
'/_layout/health': typeof LayoutHealthRoute
@@ -191,6 +200,7 @@ export interface FileRouteTypes {
| '/recover-password'
| '/reset-password'
| '/signup'
| '/brain'
| '/admin'
| '/alerts'
| '/health'
@@ -210,6 +220,7 @@ export interface FileRouteTypes {
| '/recover-password'
| '/reset-password'
| '/signup'
| '/brain'
| '/admin'
| '/alerts'
| '/health'
@@ -230,6 +241,7 @@ export interface FileRouteTypes {
| '/recover-password'
| '/reset-password'
| '/signup'
| '/_canvas/brain'
| '/_layout/admin'
| '/_layout/alerts'
| '/_layout/health'
@@ -363,6 +375,13 @@ declare module '@tanstack/react-router' {
preLoaderRoute: typeof LayoutAdminRouteImport
parentRoute: typeof LayoutRoute
}
'/_canvas/brain': {
id: '/_canvas/brain'
path: '/brain'
fullPath: '/brain'
preLoaderRoute: typeof CanvasBrainRouteImport
parentRoute: typeof CanvasRoute
}
'/_layout/flows/': {
id: '/_layout/flows/'
path: '/flows'
@@ -395,11 +414,13 @@ declare module '@tanstack/react-router' {
}
interface CanvasRouteChildren {
CanvasBrainRoute: typeof CanvasBrainRoute
CanvasDashboardsNameRoute: typeof CanvasDashboardsNameRoute
CanvasFlowsFlowNameRoute: typeof CanvasFlowsFlowNameRoute
}
const CanvasRouteChildren: CanvasRouteChildren = {
CanvasBrainRoute: CanvasBrainRoute,
CanvasDashboardsNameRoute: CanvasDashboardsNameRoute,
CanvasFlowsFlowNameRoute: CanvasFlowsFlowNameRoute,
}