> ## Documentation Index
> Fetch the complete documentation index at: https://cubed3-igor-cub-2467-clarify-html-chart-js-support-and-hand.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# HTML

> Build fully custom layouts using HTML templates with Handlebars.

HTML charts let you render any layout that Vega-Lite cannot produce — custom scorecards, branded cards, or rich tables built with HTML and CSS. Query results are available inside the template via [Handlebars](https://handlebarsjs.com/) expressions, which are evaluated before the chart is rendered.

## Variant

### HTML template

A free-form HTML document with Handlebars expressions. Write any markup and bind query result data directly in the template.

## Template structure

Query result rows are available as a flat `data` array. Each row is keyed by the column name of the current query, which may be unqualified (`count`) or qualified with its cube or view (`order_items.count`) depending on how the query selects its members. Read the exact binding for each column from the **Handlebars reference** panel in the chart editor.

**Access a row by index** with `data.<index>`:

```html theme={"dark"}
<div class="scorecard">
  <h2>{{data.0.status}}</h2>
  <p>{{data.0.count}} orders</p>
</div>
```

**Iterate over all rows** with `{{#each data}}`:

```html theme={"dark"}
<ul>
  {{#each data}}
    <li>{{this.status}}: {{this.count}}</li>
  {{/each}}
</ul>
```

Templates are compiled in strict mode, so referencing a property that doesn't exist raises an error instead of rendering an empty string. If a chart fails to render, check that every path in the template matches a column of the current query.

<Warning>
  A qualified column name must be wrapped in square brackets: `{{data.0.[order_items.count]}}`, and `{{this.[order_items.count]}}` inside a loop. Rows are keyed by literal strings, so without brackets Handlebars reads the dot as a path and looks for a `count` property on a non-existent `order_items` object, which fails in strict mode. Unqualified names never need brackets.
</Warning>

<Tip>
  The chart editor includes a **Handlebars reference** panel listing the bindings for your current query. Add `{{json data}}` to a template to inspect the full context — see the [`json` helper](#helpers).
</Tip>

### Context

Alongside `data`, the following are available:

| Binding       | Description                                                                                                                                   |
| ------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| `data`        | Array of result rows, each keyed by column name                                                                                               |
| `columns`     | Array of columns in the result, each with `name` and `title`                                                                                  |
| `rowCount`    | Number of rows in `data`                                                                                                                      |
| `columnCount` | Number of columns                                                                                                                             |
| `pivot`       | Pivot structure, when the report is pivoted, with `rows`, `columns`, `cellMap`, `grandTotals`, and `config`. Inspect it with `{{json pivot}}` |

## Helpers

In addition to the [built-in Handlebars helpers](https://handlebarsjs.com/guide/builtin-helpers.html), these are available:

| Helper                        | Description                                                                                                      |
| ----------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `formatNumber value "format"` | Format a number using a [d3-format](https://d3js.org/d3-format) string, e.g. `",.2f"`                            |
| `formatDate value "format"`   | Format a date using a [date-fns](https://date-fns.org/docs/format) pattern, e.g. `"yyyy-LL-dd"`                  |
| `formatMonth value "format"`  | Format a date as a month using the same [date-fns](https://date-fns.org/docs/format) patterns, e.g. `"LLL yyyy"` |
| `json value`                  | Serialize a value as JSON — useful for inspecting the context                                                    |
| `get object "path"`           | Read a nested value by dotted path                                                                               |
| `entries object`              | Turn an object into `key`/`value` pairs for iteration                                                            |
| `concat a b …`                | Join values into a single string                                                                                 |
| `coalesce value fallback`     | Use `fallback` when `value` is null or undefined                                                                 |
| `eq`, `ne`, `and`, `or`       | Comparison and boolean logic for `{{#if}}` blocks                                                                |
| `now`                         | The current date                                                                                                 |

```html theme={"dark"}
<p>{{formatNumber data.0.count ",.0f"}} orders</p>
<p>as of {{formatDate now "yyyy-LL-dd"}}</p>
```

## Sandboxing

HTML charts render inside a sandboxed iframe with a restrictive [content security policy](https://developer.mozilla.org/docs/Web/HTTP/Guides/CSP). This is intentional: a chart is authored by one user and viewed by others, so templates are not allowed to execute code or reach the network.

Supported:

* HTML markup and inline `<style>` blocks
* Images and fonts embedded as [`data:` URLs](https://developer.mozilla.org/docs/Web/URI/Reference/Schemes/data)
* Handlebars expressions

Not supported:

* `<script>` tags, inline event handlers, and any other JavaScript
* Stylesheets, scripts, images, and fonts loaded from an external URL, including CDNs
* Network requests from the template, such as `fetch`

Charting libraries like D3 or Chart.js therefore can't be used in an HTML chart. To visualize data, use one of the [built-in chart types](/docs/explore-analyze/charts/chart-types) or a [custom visualization](/docs/explore-analyze/charts/custom), which lets you edit the Vega-Lite spec directly without custom code.
