Build dashboards you can actually look at and press

Widgets bind to a message name and read it live off the socket the editor
already had — lifted out of the flow editor so a dashboard route gets the
same values, which also gives the home page live data for free.

The input widgets close the loop the other way: a slider publishes into
the graph and whatever consumes that message runs. Verified end to end in
the running app — moving a slider set a flow input, and the stat bound to
what the flow computed from it followed.

View mode is plain CSS grid. A wall panel that only displays should not
download the code that lets someone drag things around, and it now does
not. Editing is a widget picker, a per-widget width control and a
settings card fed by the message catalog.

No new dependencies: the slider is a range input, the gauge is an arc,
and the markdown is a five-line subset. Charts are the one widget still
missing — they need a charting library and the chart tokens the design
guidelines reserved — so they are stored and validated but not offered.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011LF61rxW1FG5YCD2J9YqjY
This commit is contained in:
2026-08-16 09:33:02 +02:00
co-authored by Claude Fable 5
parent 895bd89b2b
commit be6d4fc13c
15 changed files with 1388 additions and 7 deletions
+11 -2
View File
@@ -1,4 +1,11 @@
import { Home, LogOut, Settings, Users, Workflow } from "lucide-react"
import {
Home,
LayoutDashboard,
LogOut,
Settings,
Users,
Workflow,
} from "lucide-react"
import { Logo } from "@/components/Common/Logo"
import {
@@ -12,8 +19,10 @@ import useAuth from "@/hooks/useAuth"
import { type Item, Main } from "./Main"
const baseItems: Item[] = [
{ icon: Home, title: "Dashboard", path: "/" },
// "Home" rather than "Dashboard": dashboards are their own thing now.
{ icon: Home, title: "Home", path: "/" },
{ icon: Workflow, title: "Flows", path: "/flows" },
{ icon: LayoutDashboard, title: "Dashboards", path: "/dashboards" },
]
export function AppSidebar() {