Skip to content

Real-Time Dashboard

Use the React SDK’s WebSocket integration to build live-updating dashboards. Events from user interactions stream in real-time.

import { useState } from "react";
import { GguiProvider, GguiSession, StackItemRenderer } from "@ggui-ai/react";
import type { ActionEnvelope, StackItem } from "@ggui-ai/react";
function App() {
return (
<GguiProvider appId="app_..." wsEndpoint="wss://ws.guuey.com">
<LiveDashboard sessionId="session_..." />
</GguiProvider>
);
}
function LiveDashboard({ sessionId }: { sessionId: string }) {
const [events, setEvents] = useState<ActionEnvelope[]>([]);
const [currentStack, setCurrentStack] = useState<StackItem[]>([]);
return (
<GguiSession
sessionId={sessionId}
onInteraction={(event) => {
setEvents((prev) => [...prev.slice(-50), event]);
}}
onStackPush={(stackItem) => {
setCurrentStack((prev) => [...prev, stackItem as StackItem]);
}}
onStackPop={() => {
setCurrentStack((prev) => prev.slice(0, -1));
}}
onError={(error) => console.error("Session error:", error)}
>
{({ connectionStatus }) => (
<div style={{ display: "flex", gap: "1rem" }}>
<div style={{ flex: 1 }}>
<ConnectionBadge status={connectionStatus} />
{currentStack.length > 0 && (
<StackItemRenderer stackItem={currentStack[currentStack.length - 1]} />
)}
</div>
<aside style={{ width: 300 }}>
<h3>Live Events ({events.length})</h3>
<EventFeed events={events} />
</aside>
</div>
)}
</GguiSession>
);
}
function ConnectionBadge({ status }: { status: string }) {
const colors: Record<string, string> = {
connected: "#22c55e",
connecting: "#eab308",
reconnecting: "#f97316",
disconnected: "#ef4444",
};
return (
<div style={{ display: "flex", alignItems: "center", gap: 8, marginBottom: 16 }}>
<span
style={{
width: 8,
height: 8,
borderRadius: "50%",
backgroundColor: colors[status] || "#9ca3af",
}}
/>
{status}
</div>
);
}
function EventFeed({ events }: { events: ActionEnvelope[] }) {
return (
<div style={{ maxHeight: 400, overflow: "auto" }}>
{events
.slice()
.reverse()
.map((event, i) => (
<div
key={i}
style={{
padding: "0.5rem",
borderBottom: "1px solid #e5e7eb",
fontSize: "0.875rem",
}}
>
<strong>{event.type}</strong>
{event.payload !== undefined && (
<pre style={{ margin: "4px 0 0", fontSize: "0.75rem" }}>
{JSON.stringify(event.payload, null, 2)}
</pre>
)}
</div>
))}
</div>
);
}

For custom real-time scenarios without GguiSession:

import { useWebSocket, useGguiContext } from "@ggui-ai/react";
function CustomLiveView({ sessionId }: { sessionId: string }) {
const { appId, wsEndpoint } = useGguiContext();
const { status, sendAction } = useWebSocket({
url: wsEndpoint || "",
sessionId,
appId,
onMessage: (message) => console.log("Received:", message),
});
// sendAction takes a canonical ActionEnvelope — see the React SDK docs.
return <p>Connection: {status}</p>;
}