Cloud|

@k2b/cloud

Cloud dashboard widgets

The Cloud endpoint contract that feeds portable widget presentation components.

Widget@k2b/uiWidgetStat@k2b/uiWidgetList@k2b/uiWidgetPills@k2b/uiWidgetStatus@k2b/uiWidgetHero@k2b/ui

The Notebooks widget uses its source app's yellow accent for its header chip. Status icons keep their own colors; endpoint discovery remains a server concern.

Account requests
Open7
Needs review
New3Waiting4
Recent notes
Release planPlatform
2m
Incident reviewOperations
1h
Service health
All systems operational8 services report healthy.
No active incidents

TSX

Copy
import { appAccentStyle } from "@k2b/cloud/ssr/app-appearance.ts";
<Widget title="Account requests" icon="ti ti-users" size="compact">
<WidgetStat value={7} label="Open" sub="Needs review" accent={{ tone: "amber", icon: "ti ti-clock" }} />
<WidgetPills pills={[{ label: "New", value: 3, tone: "blue" }, { label: "Waiting", value: 4, tone: "amber" }]} />
</Widget>
<div class="app-accent-scope" style={appAccentStyle("#eab308")}>
<Widget title="Recent notes" icon="ti ti-notebook" size="compact">
<WidgetList grow items={recentNotes} />
</Widget>
</div>
<Widget title="Service health" icon="ti ti-heartbeat" size="compact">
<WidgetStatus tone="success" title="All systems operational" message="8 services report healthy." />
<WidgetHero title="No active incidents" icon="ti ti-circle-check" tone="emerald" />
</Widget>

Cloud applications can expose bounded WidgetResponse JSON endpoints to the shared dashboard. The endpoint, session, permissions, route, and response contract are Cloud-specific; the rendered widget components also exist portably in @k2b/ui.

Use Cloud dashboard widgets

Register an endpoint when users need a compact cross-application summary or a direct route into a common task. Do not reproduce an entire application screen.

Use the portable widget components directly when the host already owns its data and layout and does not need Cloud endpoint discovery.

The widget's header icon sits in a soft chip of its source app's color, from that app's declared appearance.accent, in loading, error, locked, empty, and loaded states. A widget whose app declares no accent uses the dashboard's color. In a small dashboard tile, a failure message with Try again shows no status icon, so the message and the button fit the tile on a 320px phone.

Import

ts
import type { WidgetResponse } from "@k2b/cloud/contracts";

Endpoint contract

Cloud invokes the widget on behalf of the signed-in user using a target-bound credential, not the user's session cookie. The handler applies every required permission, keeps its query bounded, and returns:

  • 200 with WidgetResponse;
  • 204 when there is no relevant content;
  • 403 when the user lacks access;
  • another error only for a real failure.

One slow or failed endpoint must not block the dashboard.

Accessibility

Every stat needs a label and context. Widget and row links need destination-specific text. Status blocks must state their result in text instead of relying on tone or icons.

Runtime

The dashboard is one board of widgets in three fixed sizes, small, medium, and large, on four columns or two on phones. The page renders every widget's @k2b/ui frame at its final size with a loading state. The browser then reads all widgets from Core in one stream (POST /api/widgets/v1), with entry ids, sizes, and settings; each fills its frame as soon as its app answers, within its own 8-second budget. A slow widget says so after three seconds; a widget that fails or times out shows a calm inline state with Try again, which asks only that widget again. A locked or empty widget keeps its frame. Endpoint responses are JSON; applications never return Solid elements through this contract. A handler reads the requested size and settings with getWidgetRequest(c) and returns content that fits them.

Edit mode offers Move forward and Move back alongside dragging and keyboard movement. Customize opens declared settings in a dialog, or a bottom sheet on phones, and reloads that entry quietly after Apply. Done saves settings; Cancel restores them. Widgets with settings can appear several times with independent entry ids and values. Widgets without settings appear once. Framework validation runs on every call; handlers authorize each chosen resource.

Example

ts
const body: WidgetResponse = {
  title: "Recent notes",
  icon: "ti ti-notebook",
  href: "/app/notebooks",
  blocks: [
    {
      kind: "list",
      grow: true,
      items: notes.map((note) => ({
        label: note.title,
        sub: note.notebookName,
        href: `/app/notebooks/${note.notebookId}/notes/${note.id}`,
      })),
    },
  ],
};

return c.json(body);

Connect a coding agent

The Cloud skill provides compact working instructions. MCP supplies exact current documentation when details matter.

CLI command
bunx skills add https://docs.example.com

This command installs the working instructions published by this website in the selected coding agent.

For exact, current details, also connect the MCP server through one of the agent tabs.

Installation uses the open-source Vercel Skills CLI.

The skill and MCP complement each other: the skill describes workflows, while MCP supplies current documentation.