Theme branding
Skill bcastelino/powerbi-dashboard-generator/skills/theme-branding
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.From its SKILL.md
npx -y skills add bcastelino/powerbi-dashboard-generator --skill theme-brandingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
11.3 KB, ~2.8k tokens by cl100k_base, as published. Nobody here has run it
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-pbiphas produced a PBIP and beforebi-dash-creatorcomposes 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 byquery-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
| Preset | Style | Primary | Secondary | Background | Foreground |
|---|---|---|---|---|---|
corporate | Professional, conservative, navy/grey | #1F3864 | #5B9BD5 | #FFFFFF | #333333 |
modern | Bold, high-contrast, teal/coral | #19A0AA | #F15A29 | #F7F7F7 | #222222 |
minimal | Monochrome, lots of whitespace | #444444 | #888888 | #FFFFFF | #111111 |
dark | Dark 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,secondaryBackgroundforeground,secondaryForegroundtableAccent
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:
$schemaautocomplete in VS Code / a JSON editor- Format pane in Power BI Desktop — card names match
cardName, property labels match property keys after camelCasing - PBIR files — inspect
<Project>.Report/definition/pages/<page>/visuals/<visual>/visual.jsonobjectssection; the keys you see (background,title,labels, …) are exactly thecardNamevalues needed invisualStyles
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→ copyassets/themes/<theme>.jsoninto the BaseThemes directory - If
theme = custom→ copy the user-supplied theme JSON into the BaseThemes directory (validate it first againstreferences/theme-schema.md§10 — Validation Rules) - If
themeis omitted or unknown → keep the defaultCY25SU11.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:
dataColors[0..2]— setprimary/secondary/accentif provided.tableAccent— mirrorprimaryso tables get the brand accent.titletext class color — useprimaryfor visual titles.good/bad— leave defaults unless the user supplies sentiment overrides (the default green/red are accessibility-tuned).visualStyles.cardVisual.*.labels[0].color— if the card big-number color is hard-coded in the preset, swap toprimary. Prefer rewriting it as aThemeDataColorexpression (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:
- Copy the image into
<ProjectName>.Report/StaticResources/RegisteredResources/<sanitized-name>.<ext> - Register it in
report.jsonunderresourcePackages[]withtype: "RegisteredResources" - 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:
- Theme JSON parses as valid JSON.
nameis present and matches the file basename and thethemeCollection.baseTheme.nameinreport.json.dataColorshas ≥ 8 entries; each is a 6-digit hex.- All structural color slots (
background,secondaryBackground,foreground,secondaryForeground,tableAccent) and sentiment/diverging slots are valid hex when present. - All
textClasses[*].fontSizevalues are integers in[6, 72]; alltextClasses[*].colorvalues are valid hex. - Colors inside
visualStylesare wrapped as{ "solid": { "color": "#hex" } }(orThemeDataColorexpressions) — never bare hex strings. resourcePackages[].items[].pathfiles all exist on disk.- The default
CY25SU11theme 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 themeassets/themes/modern.json— Modern preset themeassets/themes/minimal.json— Minimal preset themeassets/themes/dark.json— Dark preset themescripts/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
| Error | Resolution |
|---|---|
| Theme JSON fails schema validation | Stop and surface validation errors to the user |
report.json not found | Verify the PBIP path is correct |
| Logo file not found | Skip logo embedding; warn the user |
| Image visual type not supported by the current report version | Fall 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 theme | Likely 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
$schemaURL date suffix.
What ships with it: 6 files
39.2 KB alongside SKILL.md, 1 of them executable
assets/
- themes/corporate.json3.5 KB
- themes/dark.json3.7 KB
- themes/minimal.json3.4 KB
- themes/modern.json3.7 KB
references/
- theme-schema.md12.9 KB
scripts/
- apply_theme.pyruns12.0 KB
Gives 0 of the 12 instructions most design systems skills give in ~2.8k tokens
Counted across 501 of the 520 authors here whose files we hold, read 2026-09-06
- Extract colors, typography, spacing, radii, shadows, breakpointsin 20 of 501, across 10 files
- Create a self-contained dependency-free HTML preview pagein 20 of 501, across 10 files
- Keep touch targets at least 44x44pxin 20 of 501
- Score the UI across ten dimensionsin 18 of 501, across 8 files
- Animate exclusively via transform and opacityin 18 of 501, across 15 files
- Ensure WCAG AA color contrastin 18 of 501, across 13 files
- Generate DESIGN.md with rationale for each decisionin 17 of 501, across 7 files
- Ensure proper contrast and readabilityin 15 of 501, across 10 files
- Scan the codebase for existing style patternsin 15 of 501, across 6 files
- Give every interactive element a visible focus indicatorin 15 of 501, across 13 files
- Propose a design token setin 14 of 501, across 5 files
- Create a custom theme when none fitin 14 of 501, across 9 files
Said here and by no other author read
- Copy the chosen theme JSON into BaseThemes
- Validate custom themes against schema rules before copying
- Keep the default theme when selector is unknown
- Patch brand colors in the prescribed order
- Preserve untouched theme properties during overrides
- Update report.json theme references to the new theme
Grouped from the skills themselves: near-identical wordings counted once, and counted by distinct author, so one author publishing three of these counts once. Length counted with cl100k_base; the agent that loads this file may tokenize it differently.