DASH:Gen

Docs

Power BI templates — Dashboard-Templates and Visual-Templates

The sibling of Handlebars chart templates for the Power BI engine. Two libraries, both shared:

Dashboard-TemplateVisual-Template
What it isA complete Power BI theme document: palette, semantic colours, text classes, per-type defaults in visualStylesHow one visual type looks (lineChart, card, tableEx, …), with colours and fonts as tokens
Where it goes<name> in the .pbip / .pbitMerged into that theme under visualStyles.<type>."*", and optionally into each visual.json
Built-insThe 20 RASTER themes, seeded from **
Who can add oneEveryone, in Libraries → Visuals and themesSame
Who can edit itIts author. Built-ins answer 409 "copy it instead"Same
Who can use itEveryone, once it is Public; its author alone while it is PrivateSame
Limit10 per user per kind10 per user per kind

Private or Public. A template you create starts Private — yours alone to see and to name as a theme default or a draft override. Publish it and everyone can use it; it stays yours to edit. Taking a published one private again never breaks an artifact that already used it: visibility decides who may choose a template, and the export path resolves names blind, exactly as it already does for a disabled theme.

A blank theme= deals a published theme at random, never anybody's private one.

Everything here is free: authoring a template runs no AI, choosing one on a draft runs no agent, and applying it at export is a JSON merge. The engine never reads the design notes.

1. How a look reaches the artifact

  1. The export resolves the draft's (or the one-shot run's) Dashboard-Template.
  2. For each emitted visual type it picks a Visual-Template: the draft's own choice first, else the theme's default, else none. An empty-string choice switches a theme default off.
  3. Theme channel — the template's visualStyles block, tokens substituted, replaces the matching formatting-object arrays under visualStyles.<type>."*" in the theme. Replace, not merge: legend: [{show:false}] means exactly that. A theme with nothing applied is written byte-for-byte as stored.
  4. Visual channel — the template's objects and visualContainerObjects are written into every visual.json of that type, with {{field.<Role>[n]}} resolved to that visual's own queryRefs. An entry whose field token has no projection (a second series on a one-measure chart) is dropped; the rest applies. The writer's title text always wins.
  5. The job row records the theme (style_name) and the effective map (visual_templates).

A Visual-Template name that no longer resolves is skipped with a warning; the export never fails because a template went missing.

A run on a model the user uploaded (the upload-formats page, §4c) takes a Dashboard-Template and Visual-Templates exactly as a run from data files does: the theme goes into the new report's StaticResources, the visual channel into its visual.json files, and the user's model is not touched.

With a design

A run or a draft drawn with a design (HTML dashboard §5a) has no Dashboard-Template: its style names a palette from the colours library, and the theme is composed at export — a neutral base (base, RASTER 01's structure with every colour a token), the design's fragment over it (its own powerbi.json, or the one generated from its structure, fonts and chart style), every token resolved from the palette, and the palette's eight series as dataColors. The token table below reads the palette then: accent is its accent, dataColors.N its series, canvas its background, surfaceAlt its surface2, line its border, good/neutral/bad its positive/neutral/negative. Visual-Templates apply on top exactly as above; the design's own defaults (visuals.powerbi) sit between the draft's choice and the Dashboard-Template's. The job and the draft record the palette as their theme and the design beside it.

2. Tokens

TokenResolves to
{{accent}}dataColors[0]
{{dataColors.N}} (0…7)dataColors[N] — no fallback beyond the palette; the entry is dropped
{{text}}, {{textSecondary}}, {{textMuted}}foreground, foregroundNeutralSecondary, foregroundNeutralTertiary
{{surface}}, {{surfaceAlt}}, {{canvas}}, {{line}}background, backgroundLight, backgroundNeutral, secondaryBackground
{{tableAccent}}, {{good}}, {{neutral}}, {{bad}}the same keys
{{font.callout}} … {{font.label}}textClasses.<x>.fontFace
{{size.callout}} … {{size.label}}textClasses.<x>.fontSize (a number stays a number)
{{field.<Role>[n]}}the queryRef of projection n in that role — objects only
{{field.<Role>[n].entity}}, {{field.<Role>[n].property}}that projection's table and column/measure name, for a PBIR Measure(...) expression

Missing keys fall back (textMuted → foreground, canvas → background, tableAccent → accent, good/neutral/bad → fixed defaults, fonts → Segoe UI, sizes → 10); the theme detail endpoint marks those as inherited. A string that is a token takes the typed value; a string that contains one ("'{{accent}}'" in a PBIR literal) is substituted textually. In the objects channel Power BI's own ThemeDataColor(ColorId, Percent) expression is also fine — Power BI resolves it against the exported palette.

3. The Visual-Template body

{
  "visualStyles": { "lineStyles": [ { "strokeWidth": 3, "lineChartType": "smooth" } ],
                    "legend": [ { "show": false } ] },
  "objects": { "lineStyles": [
    { "properties": { "lineStyle": { "expr": { "Literal": { "Value": "'dashed'" } } } },
      "selector": { "metadata": "{{field.Y[1]}}" } } ] },
  "visualContainerObjects": { "background": [ { "properties": { "show": { "expr": { "Literal": { "Value": "false" } } } } } ] }
}

4. The repository path (built-ins)

Theme files: identity = file stem, stored verbatim, description and keywords from the CATALOG in PowerBiDashboardTemplateSeeder (derived from raster-20-stile-DE.md). Visual files: {displayName, description, whenToUse, keywords, visualType, body, designNotes}, identity = file stem. Both seeders: insert, update on checksum change, never touch enabled, never overwrite an authored row, log names only. PowerBiTemplateAssetsTest fails CI when a shipped visual body leaves a token unresolved in any shipped theme, hard-codes a hex colour, or lacks whenToUse/keywords. Renaming a file orphans every draft and theme default that pins it — change displayName instead.

5. Previews are honest

The browser draws a swatch and a CSS sample tile from the tokens, a small SVG sketch of what a Visual-Template asks for (stroke, area, markers, axis, fonts), and the substituted JSON a template will be told. It does not render Power BI visuals. Open the .pbip in Desktop to see the look; Desktop lists the theme under View → Themes by its display name.

6. Endpoints

Engine (:8086, X-User-Id optional on reads, required on writes): GET|POST /api/v1/powerbi/themes, GET|PUT|DELETE /api/v1/powerbi/themes/{name}, GET|POST /api/v1/powerbi/visual-templates[?visualType=], GET|PUT|DELETE /api/v1/powerbi/visual-templates/{name}, GET /api/v1/powerbi/visual-types, PUT /api/v1/drafts/{id}/style {themeName, visualTemplates}, and the one-shot visualTemplates multipart part. Studio proxies all of them under the same paths, stamps the author from the JWT, and charges nothing.