Generated banner for Grafana Scenes
Generated logo for Grafana Scenes

Grafana Scenes

Grafana LabsOfficialPublished by Grafana Labs

  • Skill
  • Tool integration
  • Cloud and DevOps
  • Apache-2.0
  • No issues found

From the author

Build Grafana plugin pages using the @grafana/scenes framework. Use when creating new scene pages, adding panels/visualizations, setting up drilldown navigation, defining variables, configuring query runners, building table/timeseries/stat panels, or extending SceneObjectBase for custom scene objects. Triggers on any work involving SceneApp, SceneAppPage, EmbeddedScene, SceneQueryRunner, SceneDataTransformer, PanelBuilders, SceneFlexLayout, QueryVariable, or drilldown/tab configuration in Grafana plugins.
— the description by Grafana Labs

AutoGineer summary

Written by AutoGineer from the skill’s own files, not by the author

The @grafana/scenes framework provides a declarative, object-oriented approach to building complex, interactive pages within Grafana plugins. By composing a tree of scene objects—such as SceneApp, SceneAppPage, and EmbeddedScene—developers can manage data, variables, time ranges, and layouts in a hierarchical and reactive manner. This skill covers the implementation of core scene components, including query runners, data transformers, panel builders, and navigation patterns like drilldowns and tabs.

What it does

  • Defines hierarchical scene structures using SceneApp and EmbeddedScene objects.
  • Configures data fetching and transformation with SceneQueryRunner and SceneDataTransformer.
  • Builds standard visualizations like tables, timeseries, and stats using PanelBuilders.
  • Implements dynamic navigation through drilldowns and tabbed sub-pages.
  • Manages state and variables across the scene tree for reactive UI updates.
  • Supports custom interactive UI components by extending SceneObjectBase.

When to use it

  • When developing custom Grafana plugins that require complex, multi-view dashboards.
  • When you need to implement drill-down navigation or tabbed interfaces within a plugin.
  • When building reactive UIs that depend on Grafana variables or time range selections.
  • When you need to apply custom data transformations or RxJS operators to query results.
  • When creating custom interactive widgets that need to integrate with the Grafana scene lifecycle.

Advantages

  • Declarative structure simplifies the management of complex dashboard states.
  • Hierarchical data and variable propagation reduces boilerplate code.
  • Native support for standard Grafana panel types and transformation pipelines.
  • Lazy loading of scenes improves performance for complex plugin pages.
  • Highly extensible architecture allows for custom interactive components.

Usage examples

“How do I create a basic scene page with a table panel in my Grafana plugin?”
You define a SceneQueryRunner for data, use PanelBuilders.table() to create the visualization, and wrap them in an EmbeddedScene with a SceneFlexLayout.
“How can I add drill-down navigation to my scene page?”
You configure the drilldowns property in your SceneAppPage, defining a routePath with a wildcard and a getPage factory function to return the detail view.

Install

  1. Download the skill as a ZIP:

    https://autogineer.com/agent-skills/grafana/grafana-scenes/download
  2. Unzip it into the cross-client skills folder of your project:

    mkdir -p .agents/skills && unzip grafana-scenes.zip -d .agents/skills

Documentation by Grafana Labs

@grafana/scenes Framework

Build reactive, data-driven Grafana plugin pages with declarative scene objects.

Core Concepts

Scenes composes a tree of objects: SceneApp → SceneAppPage → EmbeddedScene → layouts → panels. Each node can own data ($data), variables ($variables), time ranges ($timeRange), and behaviors ($behaviors) that propagate down the tree.

Quick Start: New Scene Page

1. Create the scene file
// src/components/scenes/MyFeature/scene.tsx
import {
  EmbeddedScene, SceneFlexLayout, SceneFlexItem,
  SceneQueryRunner, SceneVariableSet, QueryVariable,
  PanelBuilders, VariableValueSelectors, SceneControlsSpacer,
} from '@grafana/scenes';

export function getMyFeatureScene(params: { datasource: DataSourceRef }) {
  const queryRunner = new SceneQueryRunner({
    datasource: params.datasource,
    queries: [{ refId: 'A', expr: 'up{cluster=~"$cluster"}', instant: true, format: 'table' }],
  });

  const panel = PanelBuilders.table()
    .setData(queryRunner)
    .setTitle('My Table')
    .build();

  return new EmbeddedScene({
    $variables: new SceneVariableSet({
      variables: [
        new QueryVariable({
          name: 'cluster',
          query: 'label_values(up, cluster)',
          datasource: params.datasource,
          isMulti: true, includeAll: true, defaultToAll: true,
        }),
      ],
    }),
    controls: [new VariableValueSelectors({}), new SceneControlsSpacer()],
    body: new SceneFlexLayout({
      direction: 'column',
      children: [new SceneFlexItem({ body: panel })],
    }),
  });
}
2. Create the page
// src/components/scenes/MyFeature/MyFeature.tsx
import { SceneAppPage, SceneTimeRange } from '@grafana/scenes';

export function getMyFeaturePage(params) {
  return new SceneAppPage({
    title: 'My Feature',
    url: '/a/my-plugin-id/my-feature',
    routePath: 'my-feature/*',
    $timeRange: new SceneTimeRange({ from: 'now-1h', to: 'now' }),
    getScene: () => getMyFeatureScene(params),
    drilldowns: [],
  });
}
3. Register in SceneApp

Add the page to the SceneApp pages array in the root scene file.

Key Patterns

Drilldowns (click-through navigation)
drilldowns: [{
  routePath: ':cluster/*',
  getPage: (match, parent) => new SceneAppPage({
    title: decodeURIComponent(match.params.cluster),
    url: `${parent.state.url}/${match.params.cluster}`,
    routePath: `${match.params.cluster}/*`,
    getScene: () => detailScene(decodeURIComponent(match.params.cluster)),
  }),
}]
Tabs (sub-pages within a detail view)

Pass tabs: [SceneAppPage, ...] instead of getScene on a SceneAppPage. Each tab is itself a SceneAppPage with its own scene.

Query with transformations

Wrap a SceneQueryRunner in SceneDataTransformer to apply Grafana transforms or custom RxJS operators:

new SceneDataTransformer({
  $data: queryRunner,
  transformations: [
    { id: 'organize', options: { renameByName: { 'Value #A': 'CPU' } } },
    (ctx) => (source) => source.pipe(map((frames) => /* custom transform */)),
  ],
})
Custom scene object

Extend SceneObjectBase with a static Component for custom interactive UI:

class MyWidget extends SceneObjectBase<MyWidgetState> {
  static Component = ({ model }: SceneComponentProps<MyWidget>) => {
    const state = model.useState();
    return <div>{state.value}</div>;
  };
}
Table column overrides

Build ConfigOverrideRule objects for drill-down links, filtering, units, widths, custom cells.

Panel types

PanelBuilders.table(), .timeseries(), .stat(), .gauge(), .barchart() — chain .setData(), .setTitle(), .setUnit(), .setOption(), .setOverrides(), then .build().

Common Pitfalls

  • Always use routePath: 'path/*' (with wildcard) on pages that have drilldowns or tabs

  • encodeURIComponent/decodeURIComponent URL params — K8s names can contain /

  • Variables referenced in queries as $varName must exist in an ancestor SceneVariableSet

  • getScene is called lazily; don't create side effects in the factory

  • For instant queries, set both instant: true and format: 'table'

Resources

Files

ATTRIBUTION.md

Attribution

This folder is an unmodified copy of the Agent Skill "grafana-scenes", distributed by AutoGineer (https://autogineer.com/agent-skills).

The skill's own files are unmodified copies. AutoGineer is not affiliated with or endorsed by the author or the publisher.

Files added by AutoGineer

  • ATTRIBUTION.md: this file, written by AutoGineer

  • LICENSE: copied from LICENSE

Requirements and compatibility

Works with: Claude Code, Claude apps, OpenAI Codex, GitHub Copilot, Cursor, Gemini CLI, Kiro, OpenCode, Goose, Amp, Roo Code, JetBrains Junie, Factory Droid, Devin (ex-Windsurf), Mistral Vibe, OpenHands, Letta

“Works with” means the tool reads the open Agent Skills format; a skill written for one tool may use features others lack.

Needs: Needs Node.js

Security

No issues found by our static scan· No issues found

A static scan is not a guarantee. Skills are third-party content: review a skill before you let an agent use it.

Attribution and licence

Published by
Grafana Labs
Publisher
Grafana Labs (Official)
Source
grafana/skills · skills/grafana-plugins/grafana-scenes · commit 8fb72a5
Licence
Apache License 2.0 (redistribution allowed)
  • LICENSE (added by AutoGineer from LICENSE)
  • ATTRIBUTION.md (written by AutoGineer)
Synced

AutoGineer is not affiliated with or endorsed by Grafana Labs or Grafana Labs.

Download ZIP

The ZIP holds the skill’s files, its licence files and an ATTRIBUTION.md. Download grafana-scenes.zip