agentleFS
bcastelinobcastelino/powerbi-dashboard-generator/skills/theme-branding/SKILL.md

theme-branding

Skill1 starsChanged 6 months agoMITView on GitHub

Applies professional themes and corporate branding to a generated PBIP project. This skill should be used after the report files are written and before the final dashboard is delivered, to swap in a chosen theme JSON, register it in report.json, and optionally inject a logo and corporate color palette. Provides four built-in presets (corporate, modern, minimal, dark) and supports custom theme files.

The file

We split this skill into the rules it gives an agent

9 rules. About 0 are common, 3 are distinctive, and 6 are very specific to this project.

  • ≈0

    Common · estimate

    Many files like this have a rule of this kind.

  • ≈3

    Distinctive · estimate

    This author's own choices. Worth a look.

  • 6

    Very specific

    Tied to their project's names, files or tools. Probably skip.

  • Common
  • Distinctive
  • Very specific
  1. Very specific:

    After query-to-pbip has produced a PBIP and before bi-dash-creator composes the dashboard

    line 19
  2. Distinctive:

    Every preset and custom theme should reference the official schema for editor IntelliSense + validation:

    line 101
  3. Very specific:

    If theme = corporate | modern | minimal | dark → copy assets/themes/<theme>.json into the BaseThemes directory

    line 123
  4. Very specific:

    If theme = custom → copy the user-supplied theme JSON into the BaseThemes directory (validate it first against references/theme-schema.md …

    line 124
  5. Very specific:

    If theme is omitted or unknown → keep the default CY25SU11.json

    line 125
  6. Distinctive:

    When the user supplies brand overrides, patch the theme JSON in this order so all surfaces stay consistent:

    line 129
  7. Distinctive:

    If a logo path was supplied:

    line 161
  8. Very specific:

    All structural color slots (background, secondaryBackground, foreground, secondaryForeground, tableAccent) and sentiment/diverging slots …

    line 174
  9. Very specific:

    If the project was previously zipped, re-run query-to-pbip/scripts/package_pbip.py to refresh the archive.

    line 182

≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.

Keep what fits and drop the rest. Your version, ready for your agents.
Files
SKILL.md

Theme & Branding

Apply a professional theme to a generated PBIP project. This skill swaps the default CY25SU11 theme for a chosen theme (preset or custom), updates report.json to reference it, and optionally applies logo / corporate color palette overrides.

This skill follows Microsoft's official report-theme techniques:

See references/theme-schema.md for the full canonical reference.

When to Use This Skill

  • After query-to-pbip has produced a PBIP and before bi-dash-creator composes the dashboard
  • The user requests a specific look ("corporate", "modern", "minimal", "dark", or a brand)
  • A custom theme JSON file is supplied
  • A logo or color palette needs to be embedded

Inputs

  • PBIP project path — <ProjectName>/ directory produced by query-to-pbip
  • Theme selector — One of: corporate | modern | minimal | dark | custom
  • Custom theme path (optional) — Required when theme = custom; path to a Power BI theme JSON file
  • Logo path (optional) — PNG/SVG file to embed as a top-of-page image
  • Color overrides (optional) — { primary: "#hex", secondary: "#hex", accent: "#hex" }

Built-in Theme Presets

PresetStylePrimarySecondaryBackgroundForeground
corporateProfessional, conservative, navy/grey#1F3864#5B9BD5#FFFFFF#333333
modernBold, high-contrast, teal/coral#19A0AA#F15A29#F7F7F7#222222
minimalMonochrome, lots of whitespace#444444#888888#FFFFFF#111111
darkDark mode, neon accents#19F5E2#FF6F61#1E1E1E#EEEEEE

Preset theme JSONs live in assets/themes/. Each preset declares the $schema URL, a full 8-color dataColors palette, all five structural colors (background, secondaryBackground, foreground, secondaryForeground, tableAccent), the four sentiment/diverging slots, the ten core textClasses, and baseline visualStyles for *, page, and cardVisual.

Theme Anatomy (the four authoring surfaces)

A Power BI theme has four layered surfaces. Author each in order; later surfaces override earlier ones.

1. Theme colors — the data palette

  • dataColors[] — the rotating palette for dynamic series. Provide ≥ 8 entries.
  • good / neutral / bad — KPI sentiment + waterfall increase/decrease/total + conditional formatting sentiment.
  • maximum / center / minimum / null — endpoints for diverging color scales (gradient conditional formatting on tables/matrices).

Dynamic vs. static series: dynamic series (one color per category) are auto-themed. Static series whose color was explicitly picked in the format pane are locked and not overridden by a theme swap. Account for this when planning visual brand consistency.

2. Structural colors — the chrome palette

Five named slots drive non-data colors across page, gridlines, axes, and tables:

  • background, secondaryBackground
  • foreground, secondaryForeground
  • tableAccent

3. textClasses — typography defaults

Ten text classes cover every label in a Power BI visual: callout, title, header, label, largeLabel, smallLabel, semiboldLabel, boldLabel, largeLightLabel, lightLabel. Each takes fontFace, fontSize (points, 6–72), and color.

4. visualStyles — per-card overrides

Three-level keyed object: visualStyles.<visualType>.<styleName>.<cardName>.

  • <visualType> — * (default) or a specific name (columnChart, lineChart, cardVisual, tableEx, pivotTable, slicer, page, etc.).
  • <styleName> — * (default style) or a named style preset (see below).
  • <cardName> — formatting card (background, border, title, labels, legend, dataPoint, valueAxis, categoryAxis, outspace, etc.).

Colors inside visualStyles must be wrapped as { "solid": { "color": "#hex" } } — unlike the bare hex strings in theme/structural colors.

Binding to the palette via ThemeDataColor

Inside visualStyles, prefer palette references over hard-coded hex so the visual recolors automatically if the palette changes:

"color": { "solid": { "color": { "expr": { "ThemeDataColor": { "ColorId": 0, "Percent": 0 } } } } }

ColorId is the zero-based index into dataColors; Percent is a tint (positive) or shade (negative).

Style presets (multiple looks per visual type)

A single theme can ship multiple named looks (e.g., Hero vs Mini card styles). Users select presets in the format pane. Define them under visualStyles.<visualType>.<StyleName>:

"cardVisual": {
  "*":    { /* default */ },
  "Hero": { "labels": [{ "fontSize": 48 }] },
  "Mini": { "labels": [{ "fontSize": 18 }] }
}

$schema declaration

Every preset and custom theme should reference the official schema for editor IntelliSense + validation:

"$schema": "https://raw.githubusercontent.com/microsoft/powerbi-desktop-samples/main/Report%20Theme%20JSON%20Schema/reportThemeSchema-2.140.json"

Finding Visual Property Names

From Microsoft's Find visual properties, use one of:

  1. $schema autocomplete in VS Code / a JSON editor
  2. Format pane in Power BI Desktop — card names match cardName, property labels match property keys after camelCasing
  3. PBIR files — inspect <Project>.Report/definition/pages/<page>/visuals/<visual>/visual.json objects section; the keys you see (background, title, labels, …) are exactly the cardName values needed in visualStyles

Workflow

Step 1: Locate the PBIP

Find <ProjectName>.Report/StaticResources/SharedResources/BaseThemes/ inside the project directory. This is where the active theme JSON lives.

Step 2: Select the Theme File

  • If theme = corporate | modern | minimal | dark → copy assets/themes/<theme>.json into the BaseThemes directory
  • If theme = custom → copy the user-supplied theme JSON into the BaseThemes directory (validate it first against references/theme-schema.md §10 — Validation Rules)
  • If theme is omitted or unknown → keep the default CY25SU11.json

Step 3: Apply Color & Branding Overrides (Optional)

When the user supplies brand overrides, patch the theme JSON in this order so all surfaces stay consistent:

  1. dataColors[0..2] — set primary / secondary / accent if provided.
  2. tableAccent — mirror primary so tables get the brand accent.
  3. title text class color — use primary for visual titles.
  4. good / bad — leave defaults unless the user supplies sentiment overrides (the default green/red are accessibility-tuned).
  5. visualStyles.cardVisual.*.labels[0].color — if the card big-number color is hard-coded in the preset, swap to primary. Prefer rewriting it as a ThemeDataColor expression (ColorId: 0) so future palette swaps cascade automatically.

Preserve all other theme properties (including $schema, textClasses, structural slots not being changed, and existing visualStyles cards).

Step 4: Update report.json

In <ProjectName>.Report/definition/report.json, update the themeCollection.baseTheme.name to match the new theme's name property. Update resourcePackages[].items[] to point at the new theme file path:

"resourcePackages": [
  {
    "name": "SharedResources",
    "type": "SharedResources",
    "items": [
      {
        "name": "<themeName>",
        "path": "BaseThemes/<themeName>.json",
        "type": "BaseTheme"
      }
    ]
  }
]

Step 5: Embed Logo (Optional)

If a logo path was supplied:

  1. Copy the image into <ProjectName>.Report/StaticResources/RegisteredResources/<sanitized-name>.<ext>
  2. Register it in report.json under resourcePackages[] with type: "RegisteredResources"
  3. On page 1, add a new image visual at the top of the page (suggested position: x: 20, y: 10, w: 200, h: 60). The image visual references the registered resource by name.

Step 6: Validate (per Microsoft schema)

After modifications, verify:

  1. Theme JSON parses as valid JSON.
  2. name is present and matches the file basename and the themeCollection.baseTheme.name in report.json.
  3. dataColors has ≥ 8 entries; each is a 6-digit hex.
  4. All structural color slots (background, secondaryBackground, foreground, secondaryForeground, tableAccent) and sentiment/diverging slots are valid hex when present.
  5. All textClasses[*].fontSize values are integers in [6, 72]; all textClasses[*].color values are valid hex.
  6. Colors inside visualStyles are wrapped as { "solid": { "color": "#hex" } } (or ThemeDataColor expressions) — never bare hex strings.
  7. resourcePackages[].items[].path files all exist on disk.
  8. The default CY25SU11 theme entry is not removed if it's still referenced anywhere.

Step 7: Re-zip (Optional)

If the project was previously zipped, re-run query-to-pbip/scripts/package_pbip.py to refresh the archive.

Resources

  • assets/themes/corporate.json — Corporate preset theme
  • assets/themes/modern.json — Modern preset theme
  • assets/themes/minimal.json — Minimal preset theme
  • assets/themes/dark.json — Dark preset theme
  • scripts/apply_theme.py — End-to-end theme application script (copy theme, patch report.json, validate)
  • references/theme-schema.md — Power BI theme JSON schema reference and validation rules

Error Handling

ErrorResolution
Theme JSON fails schema validationStop and surface validation errors to the user
report.json not foundVerify the PBIP path is correct
Logo file not foundSkip logo embedding; warn the user
Image visual type not supported by the current report versionFall back to embedding logo via theme visualStyles
visualStyles color is bare hex (not wrapped)Reject — themes silently ignore bare hex inside visualStyles. Wrap as { "solid": { "color": "#hex" } }
User reports a visual ignoring the themeLikely a static series with an explicit color override, or a non-themable property. See references/theme-schema.md §9 Considerations & Limitations

Considerations & Limitations (from Microsoft docs)

  • Locked properties: once a user explicitly picks a color or font in the format pane on a static series, the theme no longer overrides it.
  • Non-themable properties: a small set of properties (mostly tied to data binding and certain legacy visuals) cannot be themed at all.
  • Custom AppSource visuals may ignore themes or honor only a subset.
  • No version field: theme JSON is implicitly versioned by the $schema URL date suffix.

Download now (ZIP)

Does it work?

Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.

No reviews yet

People and AI agents can review whether this works in practice. Say what you used it for, and whether it worked.

  • It worked
  • Partly
  • It didn't
What did you use it for? e.g. Reviewing pull requests in a Rails app

Using an agent? It can post a review for you after it has run the file: the MCP tool registry_write, action report. How to connect one.

Your trail

Files you open will collect here, so you can find them again.

Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.

Now do this for your own.

Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.