{ "$schema": "homarr-widget-package-v3", "manifest": { "id": "homarr.reference.rack", "version": "1.0.0", "sdkVersion": "1", "name": "Interactive server rack", "description": "A keyboard-accessible SVG rack backed by real Beszel inventory, with selectable systems and host-native detail views.", "entrypoints": { "tile": "widget.tsx", "advanced": "widget.tsx", "server": "server.ts" }, "handlers": { "systems": { "kind": "query", "permission": "view" } } }, "files": { "server.ts": "import type { NativeResult, SystemRow } from \"./beszel-types\";\nimport { callWidgetIntegration, defineWidgetServer } from \"@homarr/widget-sdk/server\";\nexport default defineWidgetServer({ systems: (_input, context) => callWidgetIntegration>(context, {connection:\"beszel\",capability:\"beszel.systems\"}) });", "widget.tsx": "import type { SystemRow, NativeResult } from \"./beszel-types\";\nimport { Alert, Button, Group, Stack, Text } from \"@mantine/core\";\nimport { useWidgetHost, useWidgetQuery, useWidgetServices, useWidgetState } from \"@homarr/widget-sdk\";\nimport \"./rack.css\";\nexport default function Rack() {\n const host = useWidgetHost();\n const services = useWidgetServices();\n const query = useWidgetQuery>(\"systems\", {}, {refetchInterval: 15000});\n const [selected, setSelected] = useWidgetState(\"selected\", \"\");\n const systems = query.data?.data ?? [];\n const rows = host.displayMode === \"advanced\" ? systems : systems.slice(0, 8);\n const inspect = (system:SystemRow) => { setSelected(system.id); services.openDetail({title: system.name, content: {system.hostname} \u00b7 {system.osName}CPU: {system.cpu.toFixed(1)}% \u00b7 Memory: {system.memory.toFixed(1)}% \u00b7 Disk: {system.disk.toFixed(1)}%{system.cpuModel} \u00b7 {system.cores} coresUptime: {Math.floor(system.uptime / 3600)} hours}); };\n return \n Server rack{systems.length} systems\n {query.error && {query.error.message}}\n \n \n {rows.map((system, index) => inspect(system)} onKeyDown={(event) => { if (event.key === \"Enter\" || event.key === \" \") { event.preventDefault(); inspect(system); } }} className=\"reference-rack__unit\">\n \n \n {system.name.slice(0, 35)}\n CPU {system.cpu.toFixed(1)}% \u00b7 RAM {system.memory.toFixed(1)}% \u00b7 {system.status}\n \n {[0,1,2,3].map((slot) => )}\n )}\n \n {!query.isPending && !query.error && !systems.length && No Beszel systems are available.}\n ;\n}", "beszel-types.ts": "// Public result fields used from the Homarr Beszel capability adapter.\nexport interface SystemRow {\n id:string; name:string; status:\"up\"|\"down\"|\"paused\"|\"pending\";\n cpu:number; memory:number; disk:number; gpu:number; netBytes:number; uptime:number;\n hostname:string; cpuModel:string; cores:number; osName:string; agentVersion:string;\n}\nexport interface AttributedSystem extends SystemRow {connection:string;rowKey:string}\nexport interface NativeResult {data:T;timestamp?:string}\nexport interface SystemStats {cpu:number;mu:number;mb:number;du:number;dio?:[number,number];dr?:number;dw?:number;b?:[number,number];ns?:number;nr?:number}\nexport interface ContainerStats {n:string;c:number;m:number;b?:[number,number];ns?:number;nr?:number}\nexport interface StatsRecord {id:string;created:string;stats:T}\nexport type SystemRecord = StatsRecord;\nexport type ContainerRecord = StatsRecord;\nexport interface StatsResult {systemStats:SystemRecord[];containerStats:ContainerRecord[]}\nexport type LiveStatsEvent = {type:\"system_stats\";record:SystemRecord}|{type:\"container_stats\";record:ContainerRecord};\nexport interface StatsInput {connection?:string;systemId:string;timePeriod?:string;includeDocker?:boolean}\n", "rack.css": ".reference-rack__unit { cursor: pointer; outline: none; }\n.reference-rack__unit:focus-visible > rect:first-child { stroke: var(--mantine-color-blue-6); stroke-width: 3; }\n.reference-rack__unit:hover > rect:first-child { stroke: var(--mantine-color-blue-5); }\n" }, "dependencies": {}, "connections": { "beszel": { "kind": "integration", "label": "Beszel integration" } }, "options": {} }