@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
2. Create the page
3. Register in SceneApp
Add the page to the SceneApp pages array in the root scene file.
Key Patterns
Drilldowns (click-through navigation)
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:
Custom scene object
Extend SceneObjectBase with a static Component for custom interactive UI:
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/decodeURIComponentURL params — K8s names can contain/- Variables referenced in queries as
$varNamemust exist in an ancestorSceneVariableSet getSceneis called lazily; don't create side effects in the factory- For instant queries, set both
instant: trueandformat: 'table'


