Grafana Scenes
Grafana LabsOfficialPublished by Grafana Labs
- Skill
- Tool integration
- Cloud and DevOps
- Apache-2.0
- No issues found
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
Download the skill as a ZIP:
https://autogineer.com/agent-skills/grafana/grafana-scenes/downloadUnzip 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 tabsencodeURIComponent/decodeURIComponentURL params — K8s names can contain/Variables referenced in queries as
$varNamemust exist in an ancestorSceneVariableSetgetSceneis called lazily; don't create side effects in the factoryFor instant queries, set both
instant: trueandformat: 'table'
Resources
Files
- ATTRIBUTION.mdAdded by AutoGineer851 B
- LICENSELicence file added by AutoGineer11.1 KiB
- SKILL.md5.0 KiB
ATTRIBUTION.md
Attribution
This folder is an unmodified copy of the Agent Skill "grafana-scenes", distributed by AutoGineer (https://autogineer.com/agent-skills).
Commit: 8fb72a527961f05e708f53d2a0500709e12d7970
Published by: Grafana Labs (https://github.com/grafana)
Publisher: Grafana Labs (https://github.com/grafana)
Licence: Apache License 2.0 (https://spdx.org/licenses/Apache-2.0.html)
Licence evidence: declared in the frontmatter ("license: Apache-2.0")
Retrieved: 2026-11-07
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