When the Apache Superset Handlebars chart produces the layout you need
Your dashboard needs a layout that standard Superset charts cannot draw, such as a formatted summary card, a grouped list of records or a block that mixes narrative text with a small table. The Handlebars chart answers that need by rendering query results through a custom Handlebars template that you write and store with the chart. The template receives the query results as a data array, so each row is available to your markup, and the chart outputs whatever HTML the template produces inside the dashboard.
The chart covers presentation of data that a query has already returned. Superset supplies helpers for common formatting work: dateFormat uses Day.js format strings, formatNumber formats numeric values, stringify and parseJson handle JSON fields, and group organizes rows for sectioned layouts. Use these helpers before you reach for a custom plugin. The chart does not add new data sources, change how the query runs or manage cross-chart interaction. Confirm in the current Handlebars chart documentation which helpers and template features your Superset version supports, since your release may differ from the docs you read.
Before you commit to a template, decide whether the layout is a one-off presentation or a reusable visual. If the layout must carry its own styling, interaction or behavior across many dashboards, a custom visualization plugin is usually the better fit, and that work needs a front-end build and its own review. If the layout is specific to one dashboard and reads a finite set of rows, a Handlebars template keeps the change inside the chart configuration. Ask whoever will maintain the template how it will be tested when the underlying query or column names change.
Which built-in helpers the chart provides
The Handlebars chart ships with a small set of Superset helpers that handle dates, numbers, JSON and grouping inside the template. Together they decide how much formatting and reshaping happens in the template rather than in the query, so each one is worth understanding before you write markup.
Formatting dates with dateFormat
The dateFormat helper formats date values using Day.js format strings, so a template can show a column such as an order date in the layout your users expect. Use it for labels and captions, and keep the underlying query returning real date values so sorting and filtering stay correct. Confirm the argument order and how the helper treats null or unparseable values in the Superset Handlebars chart documentation before relying on it in a published dashboard.
Presenting values with formatNumber
The formatNumber helper renders numeric results as formatted text for totals, averages and currency-style figures in a custom layout. Because the output is display text, do not feed it back into calculations inside the template. Check the supported format patterns, locale behavior and rounding rules in the documentation, and test them against the decimal precision your finance or operations readers expect.
Serializing values with stringify
The stringify helper converts a value into a JSON string, which is useful when a template needs to pass data into inline scripts, data attributes or a custom plugin's configuration. Escape output carefully when placing it in HTML, since injecting raw query results into markup is a cross-site scripting risk when the data can be influenced by users. Confirm how the helper handles nested objects and special characters in the documentation.
Reading nested data with parseJson
The parseJson helper turns a JSON string stored in a query result column into an object the template can traverse. This matters when a warehouse column holds semi-structured payloads, such as event attributes or configuration blobs. Confirm how it reports invalid JSON, since a malformed value could break rendering for the whole chart. Parsing in the query layer is often easier to test than parsing in the template.
Grouping rows with group
The group helper organizes rows from the data array by a field, so a template can render sections, such as one card per region or a list of line items under each account. It changes only the presentation, not the query, so every row is still returned to the browser. Check how it orders groups and handles missing keys in the documentation, and keep very large result sets in mind when grouping in the template.
Handlebars chart or a custom plugin: which option fits
This table compares a standard Superset chart, the Handlebars chart and a custom visualization plugin on layout control, upkeep, reuse and who can change them. Read each row against your layout need and your team's skills. The main takeaway is that the Handlebars chart covers layouts that standard charts cannot produce without code you must maintain through upgrades.
| Factor | Standard Superset chart | Handlebars chart | Custom visualization plugin |
|---|---|---|---|
| Layout control | Limited to the chart types and options Superset ships | Full HTML and CSS structure around the query results | Full control over rendering, including interactivity and libraries |
| Data access in the view | Chart controls map columns to the visualization | Results arrive as a data array the template loops over | Results are passed to your code through the plugin API |
| Who can edit it | Dashboard editors with chart permissions | Chart editors who can write Handlebars, usually in the chart settings | Developers who build, package and deploy the plugin |
| Maintenance burden | Low, maintained by the Superset project | Low to moderate, templates live in the chart and need review when data changes | Highest, your code must be rebuilt and tested against each Superset release |
| Reuse across dashboards | Reusable by copying the chart | Copy the chart or template, with edits tracked per chart | Reusable across all dashboards once the plugin is registered |
| Upgrade exposure | Changes arrive with Superset upgrades | Templates depend on helper behavior, so test them in staging after upgrades | Plugin breaks are possible on each upgrade, so plan regression tests |
| Best fit | Standard charts answer the question | A one-off or small set of custom layouts from query results | A visualization reused widely or needing logic a template cannot express |
| Confirm before choosing | Chart types available in your version | Helper names and behavior in your Superset version | Plugin API and build steps for your target release |
How to build and test a Handlebars layout
This sequence takes a Handlebars chart from a confirmed query to a reviewed layout on a dashboard. Each step ends with a check against the source data, so formatting, escaping and access scope are verified before users see the chart.
Confirm the query and dataset
Start in SQL Lab or the chart builder by confirming which dataset, metrics, columns and filters the layout needs, and record the expected row count for the default filters. The analyst or data owner signs off on the field names and data types, because the template refers to them by name. Done when a saved query returns the expected rows and every field the template needs appears in that result.
Draft the template on a small result set
Limit the chart to a small slice of data, such as one day or one filter value, and write a first template that loops over the data array. Use the stringify helper to print the structure of a row before you add any markup, so you can confirm field names and nesting. Check that the number of rendered items matches the row count from the first step. If the counts differ, the loop or the filter is wrong, and you fix that before adding layout.
Apply date and number helpers
Replace raw values with the dateFormat helper, which uses Day.js format strings, and the formatNumber helper for thousands separators and similar display rules. Confirm the exact syntax in the Handlebars chart documentation for your release. Compare formatted values with the same rows in SQL Lab, including the first and last date, a zero, and a large value. Confirm that dates display in the time zone your reports use. Done when every sample row formats correctly.
Handle missing values and JSON fields
Add conditional blocks for null and empty values so the layout shows a clear fallback instead of blank or broken cells. Use the parseJson helper on any column that stores JSON text, and treat a malformed string as a case to test, not an assumption. Use the group helper only after confirming its arguments in the documentation for your release, since grouped output changes the shape of the data you loop over. Done when a row with a missing value, a malformed JSON string and a single-member group each render as intended, with no template errors in the browser console.
Style the layout and check escaping
Add CSS under a scoped class name so the styles do not change other charts on the same dashboard, and keep the stylesheet in version control next to the template. Then test escaping by passing a test row that contains HTML characters, such as angle brackets and quotation marks. The value should display as plain text and produce no script execution. Ask your security team to review any template that bypasses default escaping or includes scripts, because unescaped output creates a cross-site scripting risk.
Review output with production data scope
Open the chart as a user from each audience that will see it, including users restricted by row level security, and compare the rendered totals with a SQL Lab query run under the same role. Confirm that restricted users see only their rows and that no column they lack access to appears in the layout. Record the review and the template version in your change log. Done when each audience's figures match the reference query and the data owner's team has approved the output.
Promote the chart to dashboards
Add the approved chart to a staging dashboard and check native filters, interaction with other charts and load time in a browser at the expected screen width. Then promote the same template to production through your deployment process, so the template text matches what was reviewed. Confirm who maintains the template and where its source is stored. Recheck the chart after each Superset upgrade by reading the release notes, since chart plugins can change between versions. Done when the production dashboard matches staging.
Styling choices and what the data scope still controls
Builders control the presentation inside the Handlebars template. The template is markup, so you can apply inline styles and CSS classes to the elements that wrap your data, within what the chart allows in the embedded page. Keep the markup simple enough that a later reviewer can read it without running the chart, and treat the styling as a layout concern rather than a data concern.
- Inline styles: Use inline style attributes for small, element-specific adjustments such as spacing or alignment of a single block.
- CSS classes: Prefer class names for patterns repeated across several cards or rows, so one change updates every instance.
- Helper output: Format values with the built-in helpers, such as
formatNumberanddateFormat, instead of hand-coded string logic, so the display stays consistent across charts. - Test with real result sizes: Preview the chart with the largest result set you expect, because a layout that fits a few rows can break with many.
- Confirm the supported surface: Check the Handlebars chart documentation for which styling methods the chart supports before you rely on any of them.
Before publishing, preview the chart in the dashboard and in any embedded context where it will appear, and confirm that the styling still renders correctly at the sizes your users actually use.
Styling does not decide who sees which data. The template receives the rows that the query returns for the requesting user, and that result set is shaped by row level security filters and chart and dataset permissions. A template can hide or reorder what it receives, but it cannot recover rows that Superset withheld, so the access model has to be correct before the layout is reviewed for presentation.
- Row level security first: Confirm that RLS filters apply to the datasets behind the Handlebars chart, and test them with a representative user for each group.
- Chart and dataset permissions: Verify who can open, edit and save the chart, because a builder who can edit the template can change what is displayed to viewers.
- Template editing rights: Treat the ability to change a Handlebars template as a privilege on par with editing the query, and limit it to the roles that need it.
- Output in the browser: Check how user-provided or query-provided values are rendered and escaped, and do not assume the template handles every field safely.
- Logging and review: Record who changed templates and who can publish dashboards that contain them, so an auditor can trace a layout change.
Before approval, run the chart as each role and confirm that the rows and fields visible in the template match the access model you documented.
Platform teams own the deployment side of a template change, including how it moves between environments and how it is reproduced after an upgrade. A Handlebars template lives in the chart definition in the metadata database, so it changes with the database, not with a file in your repository, unless you manage dashboards as code. That affects backups, promotion and rollback.
- Metadata database backups: Because templates are stored with chart definitions, include the metadata database in your backup and restore tests.
- Promotion between instances: Decide how a tested chart moves from staging to production, and confirm which parts of the definition travel with it.
- Upgrade regression: Recheck rendered templates after each Superset upgrade, following the upgrade guide and the breaking change notes in UPDATING.md.
- Helper dependencies: Confirm the helpers your templates depend on are present in the version you run.
- Change records: Keep a simple record of template changes so rollback targets are known.
Before a template goes to production, confirm that your backup, promotion and rollback steps cover the chart definition, and that the owner of each template is named.
Security risks in custom templates to review before rollout
A Handlebars template is code that runs against live query results, so its risks sit in who can edit it, how it renders data, and how it changes over time. The cards below cover the decisions to make and the checks to run before a template reaches a wider audience.
Template editing rights
Anyone who can edit a Handlebars chart's template can change what every viewer of that chart sees, including the markup and any scripts it emits. Limit template editing to a small group of chart owners rather than all dashboard editors. Confirm which Superset roles can open and save the chart configuration in your environment, and test that a viewer role cannot change the template.
Unescaped output from data values
Values from the query result reach the browser through the template. If a column holds text such as a script tag or an HTML attribute payload, a template that outputs it without escaping can inject markup into the dashboard. Check the escaping behavior of the double-brace and triple-brace output forms in the Handlebars documentation, then confirm it with a test row containing HTML characters before you rely on it.
Parsing untrusted JSON fields
The parseJson helper turns a string column into an object the template can traverse. If that string comes from user-entered or external data, the parsed content can carry unexpected keys, nested values or markup that the template then renders. Parse only fields your own pipeline produces, validate the structure in the query where possible, and test with malformed and hostile values.
Change control for templates
A template stored only in the chart editor has no review history, and an edit made during an incident can reach production without a second reader. Keep the template text in version control, record who approved each change, and promote it through the same staging step you use for dashboard changes. Ask your Superset administrator how chart configuration is exported and restored during backups.
Scope of data exposed to the template
The template receives whatever rows the chart's query returns for the current viewer, so a template cannot hide data the query already exposes. Row level security and dataset permissions decide the result set, and a template that prints every column makes any over-broad query visible at a glance. Review the columns each template renders against the access model before publishing.
Testing before wider rollout
Run escaping and access tests in a staging instance that mirrors production roles. Use test rows with HTML characters, empty and null values, and a viewer account with restricted data. Record the results with the template version, so a reviewer can confirm which version passed. Plan this as part of your Superset upgrade and release process rather than as a one-time check.
Questions buyers ask about Handlebars layouts in Superset
How much effort does a Handlebars layout take to build?
The effort depends mainly on how many distinct regions the layout has, how many fields each region shows, and how much conditional logic the template needs. A single card that prints a few columns from the data array is a small job. A multi-section report with grouped rows, formatted numbers, date ranges and fallbacks for empty results is a larger one, because each branch needs its own check against real query output. Other drivers include how stable the underlying dataset is, since a renamed column breaks the template silently, and how many charts reuse the same markup. Ask any partner to break the quote into template design, data preparation in the query, styling and testing, so you can see which part grows with your requirements.
Can our own team build a Handlebars layout without outside help?
Yes, if someone on the team knows HTML and CSS and can read the shape of the query results. The Handlebars chart gives the template access to results as a data array and provides helpers for dates, numbers, JSON and grouping, so most layouts need no separate build pipeline. The harder part is the governance around the template: who may edit it, how changes are reviewed, and how the template behaves for users with different row level security filters. Teams without someone comfortable with templating usually bring in outside help for the first layout, then keep the pattern in-house. Confirm the skills you already have before deciding.
What does the work need from our analysts and Superset admins?
Analysts need to define the dataset and the query so that every field the template uses is present, named consistently and typed predictably. Admins need to decide which roles may edit chart code, confirm that the chart's data respects existing row level security, and approve any change before it reaches shared dashboards. Plan time for a few review rounds where the analyst compares rendered output with the figures in a standard chart. Ask your partner to define a short handover list covering the dataset contract, the template location, who approves changes and how to roll back a broken version.
How long does testing take for a template layout?
Testing time follows the scope of the template. A simple layout needs checks against a few representative queries, a visual review in the browser and a check with an empty result set. A layout that powers several dashboards, or that shows different content to different users, needs more cases: each filter combination, each role that sees the chart, long text values, missing dates and very large result sets. Testing should also cover the dashboard in embedded or public contexts if those are in use. Ask for the test cases in writing as part of the scope, since they determine how long acceptance takes.
When is a custom visualization plugin a better choice than a Handlebars chart?
A Handlebars chart suits output that is mainly markup built from query results: tables with custom structure, cards, labels or printable summaries. A custom plugin is the better choice when you need new interaction, custom rendering logic in JavaScript, a visualization type with its own state, or behavior that must be packaged, versioned and reused across many dashboards. Plugins carry more build and release work, so they change the maintenance picture. Describe the output you need on paper first, then decide which approach fits. A partner should be able to explain that trade-off using your layout, not a generic rule.
How are templates maintained through Superset upgrades?
Templates depend on the chart's helpers, the shape of the data passed to them and the markup they produce, so each Superset upgrade should include a review of them. Follow the upgrade process the project documents: back up the metadata database, run the upgrade in staging, and read UPDATING.md for breaking changes between versions. Keep templates in version control, record which dashboards use them, and keep a set of sample queries that you can render after every upgrade. Confirm with your partner whether upgrade testing of templates is part of a fixed-scope engagement or part of a retainer, since that recurring work is what drives ongoing cost.
What recurring costs come with a custom template layout?
The recurring costs are the time to review templates after upgrades, the time to fix output when datasets change, and the time to answer questions from dashboard owners. These costs grow with the number of templates and the number of teams that depend on them. Ask whether support for templates is covered by a retainer, how changes to templates are requested and prioritized, and what happens when an upstream Superset release changes a helper. Asking for these terms in writing before the build starts makes the ongoing cost visible.
How DeployOpen scopes Handlebars chart work
DeployOpen scopes Handlebars chart work in writing before any template is written. The scope names each layout to be produced, the query results each layout reads from the data array, the Superset helpers the template will call (such as dateFormat, formatNumber, stringify, parseJson and group), and the dashboards and roles that will see the output. It also records who owns the dataset, which columns may appear in the template, and whether any value is computed in SQL or in the template. Those decisions matter because a template only renders what the chart's query returns, so a layout that needs a field the dataset does not expose is a dataset change, not a template change. Scoping these items first keeps the quote tied to specific work.
The written scope also settles the permission questions that a custom layout quietly raises. A Handlebars chart displays whatever its query returns, so row level security, dataset access and SQL Lab permissions still decide what each viewer sees, and the template cannot widen them. Before work starts, ask your team to confirm which roles can edit chart configuration, whether templates will be stored as chart settings or in version control, and who approves a change to markup that reaches a wider audience. Where a layout needs a different charting approach, the scope should say so, because a custom plugin is a separate build with its own review and upgrade cost.
DeployOpen delivers each template with tests against representative query results, documentation of the data contract and helpers used, and a short handover so your team can maintain it. Because Superset releases change, the scope should also name the Superset version the template is verified against and the upgrade check that follows each version change. Ongoing changes, such as new layouts, data fields or upgrade verification, can be covered by a support retainer that is agreed separately from the build. DeployOpen prepares the templates, tests and documentation; your own change control, approvals and access decisions remain with your organization.

