Skip to main content

Dynamic Text Panel

Grafana CI codecov CodeQL


A Dynamic Text panel is a plugin for Grafana for dynamic, data-driven text with Markdown and Handlebars support.

While the built-in Text panel in Grafana does support variables, that's about as dynamic it gets. This panel lets you define a text template using the data from your data source query.


  • Grafana 8.5+, Grafana 9.0+ is required for version 2.X.
  • Grafana 7.0+ is required for version 1.X.

Getting Started

The Dynamic Text panel can be installed from the Grafana Catalog or use the grafana-cli tool to install from the command line:

grafana-cli plugins install marcusolsson-dynamictext-panel


  • Uses Monaco Code Editor with Auto formatting to update Templates.
  • Supports Markdown and Handlebars.
  • Uses markdown-it for rendering Markdown to HTML.
  • HTML inside templates is sanitized using XSS through textUtil.
  • Allows to display Time global variables (__to and __from) as seconds, ISO, and formatted using dayjs.
  • Supports disable Sanitizing using Grafana configuration disable_sanitize_html.



To display data from your query result, enter the name of the field surrounded by double braces. For example, to display the value from the Time field:


Panels renders the template for every row in the query result. If a query returns multiple query results, you can select the query result you wish to display from a drop-down menu.

Template support text processing using one or more helpers and recipies:

  • Helpers - functions that let you perform text transformation within your template.
  • Recipes - useful snippets that you can use in your templates.

The panel renders Handlebars → Markdown → Sanitized HTML and displays the final result.

Default content

Whenever the data source query returns an empty result, Grafana displays the template in Default content. This can be useful to provide users with instructions on what to do, or who to contact, when the query returns an empty result.

Even though there's no data from the data source, you can still use the available helpers.


Sanitizing is enabled by default and some elements like <button> are unavailable in the content.

To disable sanitizing, panel depends on the Grafana configuration option disable_sanitize_html. For Docker container and Docker Compose, use as:


Every row vs All rows

By default, the template configured in the Content field is rendered for each record in the result. You can render this template only once by selecting All rows. In this case, the query results are passed in as the data field to the template.

Handlebars provides a builtin-helper to iterate over these records.

If your data source returns the following data:

| app  | description                  | cluster | tier     |
| ---- | ---------------------------- | ------- | -------- |
| auth | Handles user authentication. | prod | frontend |

You can then write Markdown with placeholders for the data you want to use. The value inside each double brace expression refers to a field in the query result.

# {{app}}


{{#if (eq tier "frontend")}}
Link: <a href='https://{{cluster}}{{app}}'>https://{{cluster}}{{app}}</a>


We love to hear from users, developers, and the whole community interested in this plugin. These are various ways to get in touch with us:

  • Ask a question, request a new feature, and file a bug with GitHub issues.
  • Sponsor our open-source plugins for Grafana with GitHub Sponsor.
  • Star the repository to show your support.


  • Apache License Version 2.0, see LICENSE.