Source profileQuality 90/100Review permissions

superplanehq/superplane/.cursor/skills/superplane-dashboard-and-widgets/SKILL.md

superplane-dashboard-and-widgets

Implements and configures SuperPlane canvas consoles (markdown, node, table, board, chart, number, scorecard panels), widget data sources, CEL/templates, table row trigger actions, and console YAML. Use when editing console UI, panelTypes, useWidgetData, WidgetTable, WidgetBoard, canvas_console_yml, Get/UpdateCanvasConsole, or docs/prd/console-and-widgets.md.

Source repository stars
5,518
Declared platforms
0
Static risk flags
1
Last source update
2026-08-26
Source checked
2026-08-26

Decision brief

What it does: where it fits

Use this skill when working on per-canvas consoles: the console mode overlay, typed panels, widget renderers, YAML import/export, or backend validation.

Best for

  • Use when editing console UI, panelTypes, useWidgetData, WidgetTable, WidgetBoard, canvas_console_yml, Get/UpdateCanvasConsole, or docs/prd/console-and-widgets.

Not for

  • Tasks that require unconfirmed production actions or broad system permissions.
  • Environments where the pinned source and install steps cannot be inspected.

Compatibility matrix

Platform support, with evidence labels

PlatformStatusEvidenceWhat to check
CodexNot declaredNo explicit evidencePortability before use
Claude CodeNot declaredNo explicit evidencePortability before use
CursorNot declaredNo explicit evidencePortability before use
Gemini CLINot declaredNo explicit evidencePortability before use
Open the compatibility checker

Installation

Inspect first. Install second.

The source command is displayed only when detected. A safe inspection prompt is always available so your agent can explain every action before execution.

Source-detected install commandSource
npx skills add https://github.com/superplanehq/superplane --skill ".cursor/skills/superplane-dashboard-and-widgets"
Safe inspection promptEditorial

Inspect the Agent Skill "superplane-dashboard-and-widgets" from https://github.com/superplanehq/superplane/blob/5a7aaa87db636301923c4595e31325ebc1df7bd6/.cursor/skills/superplane-dashboard-and-widgets/SKILL.md at commit 5a7aaa87db636301923c4595e31325ebc1df7bd6. List every install step, command, network request, credential, file read/write, external action, and rollback step. Explain whether it fits my task. Do not install or execute anything until I approve.

Workflow

What the source asks the agent to do

  1. 01

    Verification

    Review the “Verification” section in the pinned source before continuing.

    Review and apply the “Verification” source section.
  2. 02

    Product rules (do not break)

    One console per canvas (not templates). Stored as versioned JSON panels + layout on the canvas version.

    One console per canvas (not templates). Stored as versioned JSON panels + layout on the canvas version.Console mode hides the graph; 12-column react-grid-layout (ConsoleView).Edit (panels, layout, YAML import): canvases:update, not template, canvas not deleted.
  3. 03

    Layer map

    Invariant: panelTypes.ts validators (plus satellite modules like boardPanelContent.ts and nodesPanelContent.ts), pkg/yaml/console.go, and widget types.ts must agree. Frontend fast-fails; backend is authoritative on import.

    Invariant: panelTypes.ts validators (plus satellite modules like boardPanelContent.ts and nodesPanelContent.ts), pkg/yaml/console.go, and widget types.ts must agree. Frontend fast-fails; backend is authoritative on impo…Node references: always accept id or name via resolveConsoleNode in ConsoleContext.tsx.
  4. 04

    Panel types

    New panels: templateForPanelType in panelTypes.ts. Draft states (e.g. empty memory namespace) should stay valid where possible.

    New panels: templateForPanelType in panelTypes.ts. Draft states (e.g. empty memory namespace) should stay valid where possible.
  5. 05

    Data sources (useWidgetData)

    Execution rows get status, nodeName, durationMs. Status vocabulary: passed, failed, running, pending, cancelled, unknown.

    Execution rows get status, nodeName, durationMs. Status vocabulary: passed, failed, running, pending, cancelled, unknown.

Permission review

Static risk signals and limitations

Runs scripts

medium · line 206

The documentation asks the agent to run terminal commands or scripts.

make format.js

Runs scripts

medium · line 207

The documentation asks the agent to run terminal commands or scripts.

make check.lint.ui

Evidence record

Why each signal appears

EvidenceSourceComputedTestedEditorial
SignalValueEvidence typeMeaning
Quality score90/100ComputedDocumentation, specificity, maintenance, and trust rules
Repository stars5,518SourceRepository attention, not individual Skill quality
Compatibility0 platformsSourceDeclared in the catalog source record
Usage guideautomated source guideEditorialGenerated or reviewed according to the visible evidence level

Pinned source

Provenance and original SKILL.md

Repository
superplanehq/superplane
Skill path
.cursor/skills/superplane-dashboard-and-widgets/SKILL.md
Commit
5a7aaa87db636301923c4595e31325ebc1df7bd6
License
Apache-2.0
Collected
2026-08-26
Default branch
main
View the original SKILL.md

SuperPlane console and widgets

Use this skill when working on per-canvas consoles: the console mode overlay, typed panels, widget renderers, YAML import/export, or backend validation.

Canonical reference: docs/prd/console-and-widgets.md — read it for full schemas, examples, and maintenance notes. This skill is the operational subset for agents.


Product rules (do not break)

  • One console per canvas (not templates). Stored as versioned JSON panels + layout on the canvas version.
  • Console mode hides the graph; 12-column react-grid-layout (ConsoleView).
  • Edit (panels, layout, YAML import): canvases:update, not template, canvas not deleted.
  • Run (node panel Run, table / board row actions): same as edit — InvokeNodeTriggerHook; UI uses canRunNodes.
  • YAML import is replace-all (max 50 panels, 1 MiB payload).
  • User-facing name: SuperPlane (capital P).
  • Row actions are kind: trigger only — they fire trigger nodes; they do not call HTTP Request nodes directly.

Layer map

LayerKey paths
Console pageweb_src/src/pages/app/console/ConsoleView.tsx — grid, Add Panel picker, YAML modal wiring
Contextconsole/ConsoleContext.tsx, ConsoleContextProvider.tsx
Trigger hookconsole/useConsoleRunTrigger.ts, useConsoleTriggerLock.ts
Panel routerconsole/ConsolePanelCards.tsx
Schemaconsole/panelTypes.ts — types, templates, validators, normalizeTablePanelContent, normalizeBoardPanelContent
YAML (FE)console/consoleYaml.ts, ConsoleYamlModal.tsx
Widget dataconsole/widget/useWidgetData.ts
Widget UIconsole/widget/WidgetTable.tsx, WidgetBoard.tsx, WidgetChart.tsx, WidgetNumber.tsx, WidgetScorecard.tsx
Backendpkg/yaml/console.go — YAML import/export + validators
Protoprotos/canvases.proto — console panels live on the canvas version

Invariant: panelTypes.ts validators (plus satellite modules like boardPanelContent.ts and nodesPanelContent.ts), pkg/yaml/console.go, and widget types.ts must agree. Frontend fast-fails; backend is authoritative on import.

Node references: always accept id or name via resolveConsoleNode in ConsoleContext.tsx.


Panel types

typeRuntimeMain content
markdownGFM body with {{ name.field }} interpolationtitle?, body?, variables?
htmlSanitized HTML body with {{ name.field }} interpolation, scoped <style>, Tailwind via safelisttitle?, body?, variables?
nodesAdaptive card: one entry uses the compact single-node layout; multiple entries render as a row list. Optional per-entry Run button (manual-run triggers only). Optional formMode: "inline" renders the trigger parameter form directly in the widget body (prompt-submission style) for manual-run start triggers that have parameters. Inline entries can suppress the redundant node/field labels and customize submit copy.title?, nodes[] with node, label?, description?, showRun?, triggerName?, promptConfirmation?, formMode?, showNodeLabel?, showFieldLabels?, submitLabel?
node (legacy)Same renderer as nodes — the merged card folds legacy single-node content into a one-entry list. Kept for import compatibility; migrates to nodes on first save.node, showRun?, triggerName?
tableWidgetTabledataSource, render.kind: "table"
boardWidgetBoard — kanban lanes grouped by a scalar groupBy field; same data sources / filters / row actions as the table paneldataSource, render.kind: "board" with groupBy, lanes[], card, optional otherLane, where, sort, rowActions
chartWidgetChart (SVG)dataSource, render.kind: "chart"
numberWidgetNumberdataSource, render.kind: "number"
scorecardWidgetScorecard — single KPI only (no multi-KPI or composite memory); adds change vs the immediately previous value in the series, direction-aware target/progress, and a status-colored sparkline via the shared SparklinedataSource, render.kind: "scorecard" with aggregation, optional field, better, target, showProgress, sparklineField, showChange, changeCaption

New panels: templateForPanelType in panelTypes.ts. Draft states (e.g. empty memory namespace) should stay valid where possible.


Data sources (useWidgetData)

{ kind: "memory", namespace: string, fieldPath?: string }
{ kind: "executions", node?: string, limit?: number }
{ kind: "runs", limit?: number }
KindQueryNotes
memoryuseCanvasMemoryEntriesFilter by namespace; fieldPath flattens nested lists (memoryRow.ts)
executionsuseInfiniteCanvasEventsFlatten executions[]; optional node filter; eager pages until limit or cap (~500 events)
runsuseInfiniteCanvasRunstotalCount for count KPIs

Execution rows get status, nodeName, durationMs. Status vocabulary: passed, failed, running, pending, cancelled, unknown.


Table panels (most complex)

Columns

Non-empty field; optional label, format (text, number, status, relative, link, trend, …), show, href. format: trend also accepts trendBetter (up/down, default up) and trendDisplay (percent/value/none, default percent); the cell compares against the row directly below in the filtered/sorted table (or the first already-loaded row still hidden by the progressive display window).

Filters

render.where[] — AND list; ops: eq, neq, contains, not_contains, gt, lt, exists, not_exists.

Row actions (trigger)

Required: kind: trigger, node (id or name). Optional: hook (default run), template, payload, confirm, show, variant, icon.

Runtime flow: WidgetTable / WidgetBoardWidgetRowActionButtonmergeTriggerPayloadonTriggerNodeuseConsoleRunTriggerInvokeNodeTriggerHook → invalidate events/runs/memory queries.

Legacy fields normalized in FE: targetnode, triggerNametemplate.

Manual-run gate: only the built-in start and schedule triggers expose a user-invokable run hook. The UI filters on node.component against the hardcoded allowlist in web_src/src/pages/app/console/manualRunTriggers.tsTablePanelForm and BoardPanelForm hide non-manual triggers from the dropdown, WidgetTable / WidgetBoard hide their row actions, and NodesPanelCard/NodesPanelForm hide the Run affordance. Backend authorization stays in InvokeNodeTriggerHook; adding a new manual-run trigger requires a matching entry in the frontend allowlist.

Expressions

  • {{ CEL }}@marcbachmann/cel-js via widget/celExpr.ts; row env + now (Unix seconds). The adapter upfront-coerces safe-integer JS numbers (and, on retry, numeric strings) to BigInt for int arithmetic, and normalizes safe-integer BigInt results back to plain number on the way out.
  • Legacy show — e.g. status == "running" (showExpression.ts, rowVisibility.ts).
  • Prefer structured where for simple validated filters.

Lint: loose equality in legacy expressions is intentional (scalar normalization). Do not add eslint-disable for == in dashboard code; refactor instead.

Editor memory hints: MemoryDiscoveryPanel.tsx, useMemoryCatalog.ts (suggestions only; YAML still validated).

Markdown variables

  • content.variables[] carries named live data refs; body uses {{ name.field }} (or {{ name.$["Node"].data.x }} for runs).
  • Sources: { kind: "memory", namespace, orderBy?, direction?, matches?, mode?, limit? } (default mode: single first-row wins, orderBy: createdAt desc) or { kind: "run", select: latest | latest_passed | latest_failed }.
  • mode: list resolves the memory variable to the full sorted array of matching rows (optionally capped by limit), unlocking CEL list macros (rows.map(r, ...).filter(...)) inside {{ }}; pair with the join(list, sep) builtin in celExpr.ts to flatten into Markdown / HTML.
  • Resolution lives in useMarkdownVariables.ts (pickMemoryRows is the exported helper that branches on mode); interpolation in markdownInterpolation.ts (reuses celExpr.compileTemplate/evalTemplate). Validation: markdownVariables.ts (FE, including validateMarkdownContent) + validateMarkdownContent / validateHTMLContent in pkg/models/console_yml.go (BE).
  • Run vars expose status, nodeName, payload, durationMs, and a $ map of node executions (same shape as the table widget).

HTML widget safety

  • Render pipeline (HtmlBody.tsx): interpolate variables → DOMPurify allow-list → scope <style> blocks → dangerouslySetInnerHTML into div[data-console-html-root="<id>"].
  • Sanitizer (htmlSanitize.ts) blocks <script> and all on* handlers, removes head-like and resource-fetching elements (link, meta, base, iframe, object, embed, audio, video, form, svg, math, …), allows <img src>/<img srcset> for http(s)/relative URLs (cross-origin image fetches are permitted by policy), strips poster/background/data/xlink:href, restricts href/src/srcset to http(s)/mailto:/tel:/fragments, and rewrites every <style> rule to scope selectors under the widget root while dropping @import, url(...), and unknown at-rules.
  • Tailwind v4 classes must be in the curated @source inline(...) safelist in web_src/src/App.css to apply at runtime — extend it conservatively, never bypass it.

Chart and number

Chart render.type: bar, stacked-bar, line, area, donut. xField + series[]; omit series[].field to count rows per bucket.

Number aggregations: count, sum, avg, min, max, first, last — non-count requires field.

Scorecard shares the number aggregation vocabulary but is single-KPI only (no multi-KPI / composite memory). Comparison model:

  • Change = current value vs the immediately previous value in the series. The series is derived from sparklineField when set, or the primary field as a fallback. Only first / last aggregations expose a natural "previous" (adjacent anchor via pickChangeAnchors); combining aggregations (sum / avg / min / max / count) hide the chip. Reuses computeTrend (widgetTrend.ts) for percent/absolute math.
  • Target = literal number or {{ CEL }} (evaluated against the newest filtered row + now), used for optional showProgress and fallback status color.
  • better: "up" | "down" controls the polarity for the value change, the sparkline, and the vs-target status.
  • The form relabels the two directional aggregations as Latest / Earliest because all data sources are newest-first (first → Latest, last → Earliest). Persisted YAML still uses first / last.

Helpers live in widget/scorecardMath.ts (extractScorecardSeries, pickChangeAnchors, resolveScorecardTarget, computeScorecardProgress, computeScorecardChange, resolveScorecardStatus, formatScorecardChangeLabel). Rendering is in widget/WidgetScorecard.tsx; the sparkline itself comes from the shared widget/Sparkline.tsx (shared with WidgetNumber) with a className prop for status coloring.


YAML

apiVersion: v1
kind: Console
metadata:
  canvasId: <uuid>   # export only; ignored on import
  name: <display>
spec:
  panels: [{ id, type, content }]
  layout: [{ i, x, y, w, h, minW?, minH? }]
  • FE: consoleYaml.ts — parse/serialize + validatePanelContent
  • BE: ConsoleFromYML / VersionToConsoleYML in pkg/yaml/console.go
  • Unknown fields rejected; missing panels/layout → empty lists

Agent workflows

Fix a console bug

  1. Reproduce in console mode (not template); note panel type and dataSource.kind.
  2. Trace: panel card → useWidgetData → widget renderer → (if trigger) useConsoleRunTrigger.
  3. Check permissions in pkg/authorization/interceptor.go if RPC-related.
  4. Add/update test under web_src/src/pages/app/console/**/*.spec.ts.

Add or change panel content fields

  1. widget/types.ts (if widget-facing)
  2. panelTypes.ts — interface, templateForPanelType, validatePanelContent, normalization (satellite modules like boardPanelContent.ts / nodesPanelContent.ts follow the same pattern)
  3. pkg/yaml/console.go — mirror validation + tests
  4. Panel card + form component
  5. YAML tests: consoleYaml.spec.ts / consoleYaml.validation.spec.ts, pkg/yaml/console_test.go

Add a new panel type

  1. PANEL_TYPES, PANEL_TYPE_META, validator, template in panelTypes.ts
  2. ConsolePanelType* constant + AllowedConsolePanelTypes in pkg/yaml/console.go and a per-type validator
  3. *PanelCard.tsx + case in ConsolePanelCards.tsx
  4. Icon in ConsoleView.tsx PANEL_TYPE_ICONS
  5. Update docs/prd/console-and-widgets.md

Add a data source kind

  1. Extend types in widget/types.ts + panelTypes.ts
  2. DataSourceForm.tsx editor
  3. Branch in useWidgetData.ts
  4. Backend YAML validator + tests

Configure memory table (user/agent task)

Use PRD example; namespace must match canvas memory keys. Row actions target trigger nodes only.


Verification

# Frontend unit tests (console package)
cd web_src && npm run test:run -- src/pages/app/console

# After UI edits (Docker dev env)
make format.js
make check.lint.ui
make check.build.ui

# After Go validation/API edits
make format.go
make lint
make check.build.app
go test ./pkg/yaml -count=1
go test ./pkg/grpc/actions/canvases -count=1

Repo conventions

  • No web_src/src/utils/* — use lib/ or hooks/.
  • Console has strict ESLint budget — refactor touched code; do not raise the budget.
  • Split large components for Fast Refresh where the codebase already does.
  • Never hand-write DB migrations; make db.migration.create NAME=<dash-name> if persistence changes.
  • AGENTS.md: protobuf enum mapping, authorization on new RPCs.

Quick file index

TaskStart here
Grid / add panelConsoleView.tsx
Table CEL / filters / actionsWidgetTable.tsx, WidgetRowActionButton.tsx, celExpr.ts, evalTableWhere.ts, mergeTriggerPayload.ts
Table editorTablePanelForm.tsx, TablePanelFormRows.tsx
Board renderer / editorWidgetBoard.tsx, BoardPanelCard.tsx, BoardPanelForm.tsx, boardPanelContent.ts
Trigger from consoleuseConsoleRunTrigger.ts, consoleTriggerParameters.ts
Node status chip / Run buttonNodesPanelCard.tsx, NodesPanelInlineRunForm.tsx, useConsoleRunTrigger.ts, useConsoleTriggerLock.ts, deriveNodeStatuses.ts
API hooksweb_src/src/hooks/useCanvasData.tsuseCanvasVersion, useUpdateCanvasVersion

Frequently asked questions

What to verify before installation and use

What does the superplane-dashboard-and-widgets source document cover?

Use this skill when working on per-canvas consoles: the console mode overlay, typed panels, widget renderers, YAML import/export, or backend validation.

How do I install superplane-dashboard-and-widgets?

The source record exposes this install command: npx skills add https://github.com/superplanehq/superplane --skill ".cursor/skills/superplane-dashboard-and-widgets". Inspect the command and pinned source before running it.

Which permission-related actions were detected?

Static rules flagged exec-script in the source; the page lists the matching lines and excerpts.

Alternatives

Compare before choosing

Computed 100146

oaustegard/claude-skills

featuring

Generate hierarchical _FEATURES.md files that describe what a codebase DOES from a user/consumer perspective, anchored to source symbols via tree-sitting. Supports large complex codebases through feature-driven decomposition into sub-feature files. Uses a multi-pass synthesis: orientation → detail → overview rewrite. Use when someone says "what does this do", "document features", "feature inventory", "_FEATURES.md", or needs to understand a codebase's purpose before modifying it. Complements tre

Computed 9916

NintendaDev/unikit-ai

unikit-docs

Generate and maintain the project's TECHNICAL documentation from its codebase — scans the project structure, tech stack, and module boundaries, then writes a lean README landing page plus detailed topic pages (architecture, modules, setup, build, APIs), only the docs that are relevant. Use whenever the user wants to create, update, or validate documentation of the CODE or the project itself, e.g. "generate documentation", "create docs", "write the README", "update the project docs", "document th

Computed 9817

eugenelim/agent-ready-repo

work-loop

Use when implementing or resuming a non-trivial repository change: a feature, behavior-changing fix, refactor, migration, framework or dependency upgrade, schema or API change, performance work, infrastructure or build-system change, reversion, or an existing build spec under `docs/specs/`. Also use for bare continuation commands ('resume', 'continue', 'keep going', 'pick up where I left off', 'let's get going') when conversation or workspace context identifies active build work. Do not use for

Computed 9734,478

K-Dense-AI/scientific-agent-skills

esm

Use when working directly with the `esm` Python SDK, ESM3 or ESMC model IDs, Forge/Biohub inference clients, or ESMFold2 folding workflows.