Grafana logo

Skill

create-dashboard

create Grafana dashboards with gcx

Published by Grafana Updated Jul 25
Covers Dashboards Data Visualization Grafana Design

Description

Designs and creates Grafana dashboards with gcx, using `gcx dashboards snapshot` as a visual feedback loop. Use when the user wants to create a new Grafana dashboard, add panels, variables, or annotations to an existing dashboard, design dashboard panels, variables, queries, or layout, or make a material visual redesign. Triggers on "create dashboard", "new dashboard", "build dashboard", "dashboard for <service>", "add panels", "add variable", "add annotation", "improve this dashboard", or "iterate on a dashboard".

SKILL.md

Create Dashboard

Create dashboards as an iterative product workflow, not as a one-shot manifest write. The loop is:

understand goal → discover data → author dashboard → validate/push → snapshot → inspect → revise

A dashboard creation task is not complete after push succeeds. It is complete only after the dashboard has been visually checked, or after you report exactly why the snapshot step is blocked.

For pure operations on existing dashboards — list, search, pull, push, promote, restore, delete, or one-off snapshot — use manage-dashboards instead.

Hard Rules

  • Do not create dashboards in an arbitrary/default folder. If the target context or folder is ambiguous and the operation will write to Grafana, ask one concise question.
  • If the user gives a context, folder, datasource, or dashboard title, proceed with stated assumptions instead of running a long clarification round.
  • Verify the active gcx context before writes.
  • Verify datasources, metrics, labels, and log fields before adding panels. Do not invent PromQL, LogQL, datasource UIDs, label names, or folder UIDs.
  • Prefer existing project conventions. If the repo already has grafana-foundation-sdk builders, generated manifests, or a dashboards registry, follow that pattern.
  • Use gcx dashboards snapshot for visual feedback. After rendering a PNG, inspect the image with the available image/read tool; do not only report the file path.
  • Iterate at least once after the first snapshot when there are obvious visual or data problems: login page, wrong variables, empty prime panels, title truncation, broken layout, unreadable legends, or poor top-screen triage.
  • Prefer dedicated gcx commands over gcx api. Use raw API only when a needed operation has no dedicated command.

Inputs to Establish

Collect only the missing inputs needed to start:

InputNeeded forDefault if user is vague
Grafana contextAny read/writeActive gcx context after gcx config current-context
FolderDashboard creationAsk; do not default to General silently
AudienceDashboard shapeOn-call/SRE triage audience
Entity scopeQueries/variablesService/team/namespace from the user request
Datasource(s)Panel queriesInfer from similar dashboards, then verify
Time rangeSnapshot and query tests--since 6h for operational dashboards
Storage pathLocal filesExisting repo convention, else ./resources/dashboards/<name>.yaml

Workflow

1. Verify context and permissions

gcx config current-context
gcx config check
gcx config list-contexts

Use --context <name> on subsequent commands when the user named a context and you do not want to mutate global state.

Classify failures before continuing:

  • config/connectivity failure → use setup-gcx first
  • read 401/403 → missing dashboard/datasource read permissions
  • write 403 → token lacks dashboard write permissions
  • folder-specific write failure → wrong folder UID or folder permissions

2. Resolve folder and find local/live conventions

Find the target folder and similar dashboards before authoring.

# Folder/resource inventory. Use JSON for exact UIDs.
gcx resources get folders -o json

# Similar live dashboards are better than generic examples for variables,
# datasource UIDs, tags, units, and team conventions.
gcx dashboards search "<service-or-team-keyword>" -o json

# Pin the API version. Without --api-version the server returns its preferred
# version, which may use a different spec shape (elements/layout/variables
# instead of panels/templating) — the jq recipes below would then silently
# return nothing.
gcx dashboards get <similar-dashboard-uid> --api-version dashboard.grafana.app/v1beta1 -o json > /tmp/similar-dashboard.json

Extract useful patterns:

jq -r '.. | objects | select(.expr?) | .expr' /tmp/similar-dashboard.json | sort -u
jq '.spec.templating.list[]? | {name,type,query,current}' /tmp/similar-dashboard.json
jq '.spec.panels[]? | {id,title,type,gridPos}' /tmp/similar-dashboard.json

If local repository scans are appropriate under project rules, look for existing dashboard builders/manifests and follow their style instead of creating a new parallel convention.

3. Discover data before panels

Discover datasources and metrics directly when datasource choice or metric inventory is unclear. Minimum discovery for Prometheus/Loki dashboards:

gcx datasources list -o json
TypeList namesValues for a specific name
Prometheusgcx datasources prometheus labels -d <uid> --label __name__gcx datasources prometheus labels -d <uid> --label <label>
Lokigcx datasources loki labels -d <uid>gcx datasources loki labels -d <uid> --label <label>
Tempogcx datasources tempo labels -d <uid>gcx datasources tempo labels -d <uid> -l <attr> --llm -o json [--scope span|resource] [-q '<traceql>']
Pyroscopegcx datasources pyroscope list-profile-types -d <uid> then labels -d <uid>gcx datasources pyroscope labels -d <uid> --label <label>

Prometheus also has gcx datasources prometheus metadata -d <uid> for metric type and help text. For Prometheus scoped label lookups, fall back to gcx api "/api/datasources/proxy/uid/<uid>/api/v1/label/<label>/values?match[]=<selector>" — use the datasource uid from gcx datasources list; the list output has no numeric id. Other datasource types may have their own discovery subcommands — check gcx datasources <type> --help before using gcx api.

Check units, histogram buckets, status labels, route/operation labels, cluster or namespace labels, and cardinality. Prefer topk() or aggregations for high cardinality dimensions.

4. Design the dashboard story

Dashboards should answer a diagnostic question. Prefer a top-to-bottom story:

Context and health → user impact → traffic/errors/latency → dependency path → resources → logs/traces links

Design rules, distilled from Grafana dashboard best practices:

  • Define the dashboard's job before adding panels. If a panel does not support that job, remove it or move it to a collapsed deep-dive row.
  • Prefer fewer, decision-oriented panels over metric inventory. The first screen should answer "is there a problem and where should I look next?"
  • Use variables for the entity scope users will actually change (cluster, namespace, service, route, tenant, datasource), but keep them limited; too many variables make snapshots and debugging ambiguous.
  • Give every panel a clear title, unit, legend, and short description. Keep units, decimals, color semantics, and legend names consistent across panels.
  • Use thresholds only where they encode an operational decision.
  • Avoid unbounded/high-cardinality queries in default panels. Use aggregation, topk(), scoped variables, and sensible time ranges.
  • Tune refresh and time ranges for the use case. Do not make expensive panels auto-refresh faster than the data or the user decision requires.
  • Make empty states intentional: either empty means healthy and the panel description says so, or the panel should be fixed/removed.
  • Add drilldown links when a panel naturally leads to logs, traces, or another dashboard.

5. Author the dashboard

Choose one authoring mode.

Mode A: Existing resources-as-code project

Follow the repo's established pattern. If a typed stub is needed, use the generate-resource-stubs skill or:

gcx dev generate dashboards/<dashboard_file>.go

Then edit the generated builder and any registry/all-files required by the project. Run the project's normal generation/build command before pushing.

Mode B: Standalone resource manifest

Start from the live schema instead of guessing fields:

gcx resources list-types dashboards -o json > /tmp/dashboard-schema.json

Note: the server returns the schema of its preferred dashboard API version, which may use a different spec shape (elements/layout/variables), while the template below uses the classic v1beta1 shape (panels/templating). Both versions are accepted on push — just author consistently against one version and don't mix fields between them.

gcx resources list-examples is useful for resource types that ship examples, but current dashboard authoring should not depend on an example being available.

Create a manifest such as ./resources/dashboards/<dashboard-name>.yaml. Use a stable slug-like metadata.name for the dashboard resource name/UID and a human-readable spec.title for the displayed title.

apiVersion: dashboard.grafana.app/v1beta1
kind: Dashboard
metadata:
  name: <stable-dashboard-slug>
  annotations:
    grafana.app/folder: <folder-uid>
spec:
  title: "<Human readable dashboard title>"
  tags: [gcx]
  timezone: browser
  schemaVersion: 36
  templating:
    list: []
  panels: []

Folder placement is the grafana.app/folder metadata annotation shown above — the same key gcx resources get dashboards reads to display the FOLDER column. There is no folderUID field inside spec; putting one there is ignored and silently lands the dashboard in General, violating the folder rule at the top of this skill.

Fill in panels, variables, links, and layout using patterns discovered above.

6. Validate, dry-run, push, and verify

gcx resources validate -p <dashboard-path-or-dir> -o json
gcx resources push -p <dashboard-path-or-dir> --dry-run
gcx resources push -p <dashboard-path-or-dir>

# Verify the stored object. <name> is metadata.name.
gcx resources get dashboards/<name> -o json

If pushing into a directory that also contains folders, gcx orders folders before dashboards automatically. If an existing dashboard is protected by a different manager annotation, stop and explain; only use --include-managed when the user explicitly wants gcx to take ownership.

7. Snapshot, inspect, and iterate

Render a full-dashboard snapshot with the same variables and time range a user would use. Replace or omit the --var examples below so they match variables actually defined in the dashboard.

mkdir -p ./snapshots
GCX_AGENT_MODE=true gcx dashboards snapshot <dashboard-name> \
  --output-dir ./snapshots \
  --since 6h \
  --var cluster=<cluster> \
  --var namespace=<namespace> \
  --width 1920 \
  --theme dark

Then read/open the PNG returned in file_path. Inspect for:

  • login/error page instead of the dashboard
  • wrong dashboard, wrong folder, wrong time range, or wrong variables
  • empty top-row panels caused by bad queries or labels
  • title truncation or legends consuming the panel
  • overlapping panels, gaps, or poor row order
  • unreadable high-cardinality series
  • missing units/thresholds/descriptions
  • too much chrome; consider a larger --width (the renderer already hides nav chrome — there is no separate kiosk flag)

Render individual panels when a panel is suspect:

GCX_AGENT_MODE=true gcx dashboards snapshot <dashboard-name> --panel <panel-id> \
  --output-dir ./snapshots --since 6h --width 1200 --height 700

If the snapshot reveals issues, edit the source, validate, push, and snapshot again. Keep the loop short but real; one good visual correction is better than a successful push with an unusable dashboard.

8. Final response

Report only the useful operational facts:

  • assumptions made
  • Grafana context and folder
  • dashboard title and resource name/UID
  • local source path
  • validation/push result
  • snapshot path(s) and what you observed
  • iterations performed
  • remaining issues or blockers

If snapshot failed, include the exact failure class: missing image renderer, auth/RBAC, bad variables, rendering timeout, or command error. Do not claim the dashboard was visually reviewed when it was not.

© 2026 YourAI.tools. Every skill from an identity-verified publisher.

Independent catalog. Not affiliated with, endorsed by, or sponsored by Anthropic or any listed publisher. All trademarks belong to their respective owners.