Skill: Report Implementation (PBIR Visual Generation)
Purpose
Generate the physical Power BI Report (PBIR) files from the report design blueprint (report_blueprint.json) produced in Step 8. This step creates the actual page folders, page.json files, visual folders, and visual.json files inside the PBIP Report definition.
This step must implement the strategy already decided in the blueprint. It must not silently redesign mockup translation decisions or feasibility constraints.
Prerequisites — MANDATORY
Before starting report implementation:
- ✅ Step 8 completed and approved —
<ProjectName>/spec/report_blueprint.jsonexists on disk. - ✅ Semantic Model exists —
<ProjectName>/PBIP/<ProjectName>.SemanticModel/definition/contains valid TMDL files. - ✅ PBIP Report scaffold exists —
<ProjectName>/PBIP/<ProjectName>.Report/definition/folder exists (created in Step 00). - ✅ Empty-canvas report baseline is intact before adding visuals:
definition/report.jsonuses the current baseline schema and theme resources.definition/version.jsonanddefinition/pages/pages.jsonexist.- At least one page folder exists and is referenced by
pages.json. StaticResources/SharedResources/BaseThemes/ProjectDefault.jsonexists.<ProjectName>.Report/report.jsonat report root does NOT exist.
Input / Output
| Input | <ProjectName>/spec/report_blueprint.json, all TMDL files (model object registry) |
| Output | PBIR files in <ProjectName>/PBIP/<ProjectName>.Report/definition/pages/ + updated pages/pages.json |
References — MANDATORY
Before generating ANY PBIR JSON:
- READ
.github/skills/report-implementation/references/pbir-visual-templates.mdfor validated visual JSON templates. - READ
.github/references/pbip-folder-structure.mdfor correct folder hierarchy. - READ
.github/references/pbir-cli-integration.mdbefore using the localpbirCLI for any packaged report operation. - READ on demand (load only when needed for the specific task):
references/fields-and-bindings.md— Field types (Column/Measure/Extension), data roles by visual type, queryState structurereferences/filters.md— Filter types (Categorical, TopN, Advanced, RelativeDate), scope, JSON structurereferences/conditional-formatting.md— CF types, container.property mapping, measure-driven patternsreferences/extension-measures.md— reportExtensions.json structure, common patterns, DAX verificationreferences/visual-formatting-properties.md— Universal containers, property catalogue, formatting hierarchy
- VERIFY all PBIR visual structures against the official Microsoft documentation:
- Primary reference: https://learn.microsoft.com/en-us/power-bi/developer/projects/projects-report
- PBIR schema source:
https://developer.microsoft.com/json-schemas/fabric/item/report/definition/visualContainer/2.5.0/schema.json
- If uncertain about any PBIR schema, use
microsoft_docs_searchMCP tool with queries like:"Power BI PBIR page definition schema""Power BI PBIR visual container schema""Power BI report definition JSON format"
- Use
microsoft_docs_fetchfor full documentation pages when search results are insufficient. - If the step uncovers a new reusable PBIR rule about schema, folder structure, serialization, payload stability, or visual-role mapping, update the relevant reference file before ending the step. Do not leave recurring guidance only in chat output.
PBIR CLI Mutation Policy (Mandatory for Existing Artifacts)
When the local pbir CLI is available, this skill must use it as the mutation backend for existing local PBIR report artifacts.
Use it for:
- report inspection:
pbir ls,pbir tree,pbir model,pbir get,pbir cat - schema/property discovery:
pbir schema types,pbir schema containers,pbir schema describe - targeted local edits:
pbir add,pbir pages,pbir visuals,pbir set,pbir fields,pbir filters,pbir dax,pbir theme - local safety loop:
pbir backup,pbir validate,pbir open
Rules:
- Do NOT run
pbir setupfrom this skill. - Do NOT let CLI behavior replace blueprint-driven design or repository templates.
- Use the CLI for existing-report mutations that map cleanly to the requested change.
- Before any CLI read or write command, clear or replace any existing active
pbirconnection and reconnect it to the current project report under<ProjectName>/PBIP/<PbipBaseName>.Report. - Never assume the active
pbirsession already points to the current project; verify withpbir connector reconnect explicitly. - Before bulk or structurally risky commands, run
pbir backup. - After every CLI mutation, run
pbir validate(prefer--allwhen available), then still satisfy the repository validation gate below. - If the CLI is unavailable or unsupported for a requested mutation, stop and request explicit approval before falling back to direct JSON edits.
- Do not use
pbir downloadorpbir publishin Step 9 unless the user explicitly requests Fabric-edge operations.
Direct JSON edit prohibition (existing artifacts):
- Do not hand-edit
visual.json,page.json,pages.json, or theme JSON for routine report mutations. - Use CLI commands (
pbir set,pbir visuals,pbir fields,pbir filters,pbir theme) as the default path. - If fallback is approved, record rationale and run dual validation before completion.
Mandatory Implementation Safety Gate
Before marking implementation complete, run this exact sequence:
pbir connect --clear
pbir connect "<PbipBaseName>.Report"
pbir validate "<PbipBaseName>.Report" --all
python .github/skills/report-quality-validation/scripts/validate_pbir_report.py <ProjectName>
Gate rules:
- If either validation fails, implementation is NOT complete.
- Fix errors first, rerun both commands, then update workflow state.
- Treat Desktop
AdditionalPropertiesfailures as schema-blocking defects.
Schema red flags to check explicitly:
visualContainerObjectsmust be insidevisual.drillFilterOtherVisualsmust be insidevisual.- Visual filters must be in top-level
filterConfig.filters, never invisual.filters. - Top-level keys in
visual.jsonmust stay within the schema surface ($schema,name,position,visual|visualGroup, optionalfilterConfig).
Canonical pbir Command Patterns
Use these examples only when they match the requested local report task.
- Inspect an existing report before edits:
pbir connect --clear
pbir connect "Sales.Report"
pbir tree "Sales.Report" -v
pbir model "Sales.Report" -d
- Create a backup before risky local changes:
pbir connect --clear
pbir connect "Sales.Report"
pbir backup "Sales.Report" -m "Before report implementation changes"
- Add a native visual with explicit binding:
pbir connect --clear
pbir connect "Sales.Report"
pbir add visual card "Sales.Report/Overview.Page" --title "Revenue" -d "Values:Sales.Revenue"
- Apply a narrow formatting or layout change:
pbir connect --clear
pbir connect "Sales.Report"
pbir visuals title "Sales.Report/Overview.Page/Revenue.Visual" --text "Net Revenue" --bold
pbir visuals position "Sales.Report/Overview.Page/Revenue.Visual" --x 40 --y 32 --width 260 --height 120
- Apply a safe theme-first formatting change:
pbir connect --clear
pbir connect "Sales.Report"
pbir theme set-colors "Sales.Report" --primary "#2B579A" --secondary "#217346"
pbir theme set-formatting "Sales.Report" "card.*.border.show" --value true
- Validate after mutation:
pbir connect --clear
pbir connect "Sales.Report"
pbir validate "Sales.Report"
Fallback:
- if any of these commands cannot express the blueprint requirement cleanly, return to the repository templates and direct file generation flow
- if a command requires broader destructive scope than requested, stop and keep the change in the repository-managed workflow instead
- if
pbir catfails with a packaged runtime error butpbir lsorpbir getstill work, treatcatas unavailable for the current environment and continue with repository-managed file inspection instead of blocking Step 9
CRITICAL: NEVER invent or guess PBIR JSON structures. Always validate against Microsoft official documentation or the template reference file. In the current baseline,
drillFilterOtherVisualsbelongs tovisual, cards usevisualType: cardVisualwithqueryState.Data, page navigation is governed bydefinition/pages/pages.json, and PBIR JSON must be written as UTF-8 without BOM.
CRITICAL: Schema lookup findings belong in repository knowledge, not in ad-hoc local scratch files. Temporary inspection artifacts may be used while working, but any durable conclusion must be normalized into a reference file and temporary files must not remain as project artifacts.
Anti-Hallucination Protocol
CRITICAL: PBIR JSON is verbose and deeply nested. The agent MUST NOT guess JSON structures.
- Use templates: Every visual MUST be generated from a template in
.github/skills/report-implementation/references/pbir-visual-templates.md. - Validate field names: Every
EntityandPropertyin visual queries MUST match exactly the TMDL table and column/measure names. - No invented visuals: Only generate visuals defined in
report_blueprint.json. - Schema compliance: All JSON files MUST reference the correct Microsoft
$schemaURLs. - Physical ID discipline: Page and visual runtime ids used in PBIR folders and
nameproperties MUST be generated explicitly and kept synchronized across all referencing files. - Encoding discipline: Write every generated PBIR JSON file as UTF-8 without BOM.
- Knowledge-base discipline: If a new rule is discovered that is not specific to the current report, persist it in the corresponding reference before closing the step.
Step 9 Procedure
9.1 Read Inputs
- READ
<ProjectName>/spec/report_blueprint.json— Parse the complete blueprint. - READ TMDL files — Build a Model Object Registry (same as Step 7, Step B.0):
- All table names
- All column names per table (PascalCase)
- All measure names from
_Measures.tmdl(natural language with spaces)
- CROSS-VALIDATE: Verify that every field referenced in
report_blueprint.jsonexists in the Model Object Registry. If any field is missing, STOP and report the discrepancy. - READ strategy metadata: If a visual declares
implementationStrategy, honor the selected mode (native,composite-native,svg,deneb,approximation,not-feasible) during generation. - LOAD custom-visual skills on demand:
- If
implementationStrategy.mode = svg, load thesvg-visualsskill before implementation. - If
implementationStrategy.mode = deneb, load thedeneb-visualsskill before implementation. - If
implementationStrategy.mode = approximation, implement only the documented approximation. Do not invent a new strategy. - If
implementationStrategy.mode = not-feasible, STOP and report the blueprint conflict instead of generating a fake equivalent.
- If
9.2 Clean Up Existing Report Pages
Before generating new pages:
- CHECK if
<ProjectName>/PBIP/<ProjectName>.Report/definition/pages/already contains page folders. - If the folder contains only the default
Page1/from Step 00 initialization, remove it (it will be replaced by the blueprint pages). - If the folder contains pages from a previous Step 9 execution, ask the user whether to overwrite or skip.
- CHECK
definition/pages/pages.jsonbefore deletion or creation. Folder cleanup is invalid unless the metadata file is updated in the same operation.
9.3 Derive Physical PBIR IDs (MANDATORY)
The blueprint provides canonical logical identifiers for design intent. Step 09 must translate them into physical PBIR runtime ids.
For each page and visual:
- Generate a runtime-safe id following the repository-safe baseline observed from Desktop output:
- 20 lowercase alphanumeric characters
- Keep a deterministic mapping:
blueprint pageId->pageRuntimeIdblueprint visualId->visualRuntimeId
- Use the runtime id for:
- page folder names
page.json.namepages/pages.json.pageOrder[]pages/pages.json.activePageName- visual folder names
visual.json.name
CRITICAL: Do NOT use user-facing labels like
Page1,Page2, orvisual_01as final PBIR folder names. They are blueprint identifiers, not the physical PBIR object names.
9.4 Generate Page Folders and Files
For each page defined in report_blueprint.json:
A) Create Page Folder
<ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<pageRuntimeId>/
Where <pageRuntimeId> is the generated PBIR runtime id for the page.
B) Create page.json
Use the page template from .github/skills/report-implementation/references/pbir-visual-templates.md:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/page/2.0.0/schema.json",
"name": "<pageRuntimeId>",
"displayName": "<displayName from blueprint>",
"displayOption": "FitToPage",
"height": <height from blueprint>,
"width": <width from blueprint>
}
CRITICAL: The PBIR page schema
2.0.0does NOT allow additional properties. Only use the 6 properties shown above. Do NOT addordinalor any other custom property — Power BI Desktop enforces strict schema validation and rejects unknown properties withAdditionalPropertieserror.
File location: <ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<pageRuntimeId>/page.json
C) Create visuals/ Folder
<ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<pageRuntimeId>/visuals/
D) Update pages/pages.json
Generate or update:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/pagesMetadata/1.0.0/schema.json",
"pageOrder": ["<pageRuntimeId1>", "<pageRuntimeId2>"],
"activePageName": "<firstPageRuntimeId>"
}
Guardrails:
pageOrdermust reflect blueprint navigation order.activePageNamemust point to a generated page.- Page folders on disk and entries in
pageOrdermust match exactly.
9.5 Generate Visual Files
For each visual defined in a page's visuals array in the blueprint:
A) Create Visual Folder
<ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<pageRuntimeId>/visuals/<visualRuntimeId>/
Where <visualRuntimeId> is the generated PBIR runtime id for the visual.
B) Create visual.json
Identify the visual type from the blueprint's
visualTypefield.Look up the corresponding template in
.github/skills/report-implementation/references/pbir-visual-templates.md(use the Visual Type Mapping table).Populate the template with:
name: ThevisualRuntimeIdgenerated for the visual.position: Mapx,y,width,heightfrom the blueprint'spositionobject. SetzandtabOrderas deterministic monotonic integers based on visual order. Do NOT assume that increments of1000are required.- usability sizing guardrails:
- top-row dropdown slicers should default to about
width = 180,height = 64-66 - grouped KPI bands should default to about
height = 120 - gauges should default to a primary analytical tile size above
300 x 130 - azure maps and treemaps should default to large analytical surfaces and should not be compressed into small tiles
- top-row dropdown slicers should default to about
- operational token guardrails:
- consume
designSystem.pagePadding,visualGap,sectionGap,gridUnit, and per-visualrenderTokensfrom the blueprint when present - if tokens are absent, use repository-safe fallback defaults
- treat overlap as forbidden unless a visual explicitly sets
renderTokens.allowOverlap = true
- consume
visual.visualType: The PBIR visual type (from mapping table).visual.query.queryState: Map measures and fields from the blueprint to the correct PBIR query structure:- Card measures →
Dataprojections withMeasurefield type,Entity=_Measures.- Grouped KPI band / multi-row card intent → safe baseline is
cardVisualwith multipleDataprojections.
- Grouped KPI band / multi-row card intent → safe baseline is
- Table/Slicer values →
Valuesprojections. - Axis/Category fields →
Categoryprojections withColumnfield type. - Legend fields →
Seriesprojections withColumnfield type.- Combo chart →
Y(column values) +Y2(line values).
- Combo chart →
- Scatter chart →
X,Y, optionalSize. For colored bubbles by category, place the categorical field inSeries(Legend). For distinct unlabeled points, useDetails(Values). At least one ofSeriesorDetailsmust carry a categorical field. - Gauge →
Y,TargetValue, optionalTooltips. - Treemap →
GroupplusValues. - Azure Map →
CategoryplusSize; include validated object settings when using the repository baseline map behavior. - Row fields (matrix) →
Rowsprojections. - Column group fields (matrix) →
Columnsprojections. - Field parameter bindings → keep the active concrete projection for the target role and also emit
queryState.<Role>.fieldParameters[]referencing the parameter display column. - Measure parameter on
Values→ keep any companion grouping dimensions only if they are valid filter context for all selectable measures.
- Card measures →
visual.drillFilterOtherVisuals: settrueas baseline behavior.filterConfig: optional for handcrafted files; Desktop may generate it automatically on save.visual.query.sortDefinition: generate explicitly whenever the blueprint definessortBy.
visual.objects.value.fontSize: for grouped KPI bands and the current card baseline, set explicit20Dunless a user-approved design token overrides it.visual.visualContainerObjects: apply only the metadata needed by that visual family.- slicers: prefer
titlemetadata plusdropShadowwhen container separation is required - gauge / azureMap:
dropShadowis part of the observed stable baseline - treemap: do not force
titleordropShadowif the canonical baseline does not require them
- slicers: prefer
Validate: Ensure every
Entityvalue matches a TMDL table name and everyPropertyvalue matches a column or measure name.Validate folder/name contract: Ensure visual folder name equals
visual.json.name.Validate layout contract: Ensure computed positions respect page bounds, token spacing, and non-overlap rules.
Validate field-parameter contract: When a blueprint visual declares
fieldParameterBindings, ensure the consuming PBIR role contains both the concrete projection and the matchingfieldParametersdescriptor.Validate context compatibility: When a blueprint visual declares a measure parameter, ensure any non-parameter grouping fields are present in
allowedContextDimensionsand are reachable from every selectable measure through the active relationships.Validate reference coverage: If the chosen visual family or payload pattern is not already represented in the PBIR references, add the generalized rule or stop and capture a Desktop-generated reference before continuing.
Validate scatter grouping: A scatter visual must have at least one categorical field in
queryState.Series(Legend — colored bubbles) orqueryState.Details(Values — point identity). UseSerieswhen the design requires color-coded bubbles per category. If neither role contains a categorical field, the visual collapses to a single point.Validate unique nativeQueryRef: When the same measure is placed in multiple query-state roles within the same visual, each projection must have a distinct
nativeQueryRef. Duplicate values cause a Desktop runtime error. Append a disambiguating suffix such as(Size)or(Tooltip)to the secondary occurrence.Validate strategy alignment: The generated PBIR payload must remain compatible with the blueprint's
implementationStrategy. If the implementation requires a different mode than the one declared in the blueprint, STOP and send the issue back to report design rather than silently switching strategy.Selection/Layer Metadata Naming (CONDITIONAL):
When the visual family uses
visualContainerObjects.title, settext.expr.Literal.Valueusing this pattern:'<ComponentName> - <DataOrMetadataReference>'
Examples:
'Slicer - FiscalYear''Card - Sales Amount FYTD''Chart - Sales Amount vs Budget Amount by FiscalMonth'
The label must be unique within the page and must help identify objects in the Selection pane for layer order/tab order management.
For slicers, it is acceptable and recommended to keep
show = falsewhile still populating the metadata title text.Do NOT force a
titleblock onto every visual family if the canonical baseline for that visual works without it.
File location: <ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<pageRuntimeId>/visuals/<visualRuntimeId>/visual.json
9.6 Generate Slicer Visuals
For each slicer defined in a page's slicers array in the blueprint:
- Parse the field reference: Extract table name and column name from
Table[Column]syntax. - Use the slicer template from
.github/skills/report-implementation/references/pbir-visual-templates.md. - Set slicer mode: Map the blueprint's
typeto PBIR mode:dropdown→"Dropdown"list→"List"dateRange→"Between"
- Generate a unique visual runtime id for each slicer.
- Position slicers: Place slicers at the top or left of the page (before data visuals).
- Observed guardrail: include
active: trueon the slicer projection when using the current Desktop baseline pattern. - Usability guardrail: do not compress dropdown slicers below 64 px height in the standard top-row layout, otherwise the dropdown affordance can become visually cramped and hard to click.
If the slicer is bound to a field parameter:
- Bind the slicer projection to the visible parameter column (for example
Dimension[Dimension]). - If the blueprint declares a default selection, emit the Desktop-observed
visual.objects.general[].properties.filterpayload against the hidden object-reference column (for exampleDimension[Dimension Fields]) using the correspondingNAMEOF(...)literal value. - Keep the slicer metadata title readable, because field-parameter slicers behave like report controls and are harder to identify later in the Selection pane.
9.7 Encoding and Serialization Guardrails (MANDATORY)
When writing PBIR files:
- use UTF-8 without BOM
- avoid shell or serializer defaults that prepend BOM bytes
- avoid rewriting unrelated report baseline files
- write JSON atomically where possible to prevent partial report corruption
Recommended validation:
- check that the first bytes of each generated JSON file are not
EF BB BF - verify JSON parses cleanly before ending the step
- convert any generalized lesson from this validation into
.github/skills/report-implementation/references/pbir-visual-templates.mdor.github/references/pbip-folder-structure.md
PowerShell BOM Warning (CRITICAL)
When using PowerShell to write JSON files, [System.Text.Encoding]::UTF8 produces UTF-8 WITH BOM.
Power BI Desktop rejects BOM-prefixed PBIR files with: "Only text with UTF8 encoding without BOM is supported."
Always use the BOM-free encoder:
$utf8NoBom = New-Object System.Text.UTF8Encoding $false
[System.IO.File]::WriteAllText($path, $content, $utf8NoBom)
Never use: [System.IO.File]::WriteAllText($path, $content, [System.Text.Encoding]::UTF8)
9.8 Apply Layout Tokens and Resolve Overlaps
Before writing the final PBIR files:
- Read blueprint-level layout tokens when present.
- Apply page padding and inter-visual gaps before finalizing positions.
- Snap or normalize positions to the declared grid when required by the design system.
- Detect rectangle overlap between all visual bounding boxes on the page.
- If overlap is detected and
allowOverlapis not explicitly enabled, reposition the later visual or stop with a blocking validation message.
Fallback defaults when tokens are absent:
pagePadding = 16visualGap = 16sectionGap = 24gridUnit = 8
9.9 Update report.json (if needed)
If the blueprint specifies navigation bookmarks, themes, or other report-level settings, update:
<ProjectName>/PBIP/<ProjectName>.Report/definition/report.json
For basic reports, the existing report.json from Step 00 is sufficient.
CRITICAL: During Step 9, do NOT downgrade or rewrite the Step 00 report baseline (
report.json,version.json,pages/pages.json, page schema family,StaticResources) unless explicitly requested by the user and validated against a Desktop-generated reference.
Error Handling
Common Errors and Mitigations
Field Not Found in TMDL:
- Cause: Blueprint references a field that doesn't exist in the semantic model.
- Action: STOP. Report the exact field name and suggest corrections based on TMDL registry.
Invalid Visual Type:
- Cause: Blueprint uses a visual type not in the mapping table.
- Action: Use
microsoft_docs_searchto find the correct PBIR visual type name. If not found, STOP and ask the user.
JSON Schema Validation:
- Cause: Generated JSON doesn't conform to Microsoft schema.
- Action: Re-validate against templates. Use
microsoft_docs_fetchto check official schema.
Position Overlap:
- Cause: Multiple visuals have overlapping positions.
- Action: Apply operational layout tokens, recompute spacing, and adjust positions to avoid overlap. Use the blueprint's position values as guidelines, but ensure no two visuals share the same pixel space unless overlap is explicitly allowed.
Compressed Slicer / Unusable Dropdown:
- Cause: Slicer height too small for the chosen layout and visual chrome.
- Action: Increase slicer height to the repository baseline range of
64-66 pxand revalidate alignment.
Oversized KPI Callout:
- Cause: Default card value font too large for grouped KPI presentation.
- Action: Set explicit
objects.value.fontSize = 20Dfor the grouped KPI band baseline unless a validated design token specifies another size.
Runtime Load Error (
visualContainers):- Cause: Structurally valid files but unstable visual payload generated in bulk.
- Action: Reset to empty visual canvas and reintroduce visuals incrementally (first slicer + card, then reopen Desktop, then next batch).
Compressed Analytical Visual:
- Cause: Gauge, treemap, or map placed into a tile too small for legible rendering.
- Action: Expand the visual to the minimum analytical surface implied by tokens or repository defaults; if page space is insufficient, stop and request a layout revision instead of forcing a crowded render.
Strategy Mismatch:
- Cause: Blueprint declares
nativeorcomposite-native, but implementation would requiresvgordenebto preserve the intended behavior. - Action: STOP. Report the mismatch and require a blueprint update instead of silently changing the implementation mode.
- Cause: Blueprint declares
BOM in PBIR JSON files:
- Cause: PowerShell System.Text.Encoding.UTF8 writes UTF-8 with BOM by default.
- Error: "Only text with UTF8 encoding without BOM (byte order marks) is supported. Detected BOM: 'UTF-8'"
- Action: Use New-Object System.Text.UTF8Encoding $false as the encoder for all file writes. Run a post-write BOM scan: check first 3 bytes for xEF 0xBB 0xBF.
Page background not visible:
- Cause: PBIR eport.json /objects does not support ackground or wallpaper properties.
- Action: Use a asicShape visual at z=0, x=0, y=0, width=pageWidth, height=pageHeight with the desired fill color. Set drillFilterOtherVisuals: false on this visual.
Validation Gate — MANDATORY
Before presenting results to the user, verify:
- All pages from
report_blueprint.jsonhave corresponding folders inpages/ -
definition/pages/pages.jsonexists and includes every generated page runtime id inpageOrder -
activePageNamereferences an existing generated page runtime id - Each page folder contains a valid
page.json - Each page folder name matches
page.json.name - Each page has a
visuals/folder with the correct number of visual subfolders - Each visual folder contains a valid
visual.json - Each visual folder name matches
visual.json.name - All
Entityreferences in visual queries match TMDL table names exactly - All
Propertyreferences match TMDL column/measure names exactly - Visual types use correct PBIR type names (from mapping table)
- Slicer modes are valid PBIR slicer mode values
- Visuals that declare field parameter bindings also serialize
queryState.<Role>.fieldParameters[]correctly - Field-parameter slicers bind to the visible parameter column and use the hidden metadata column only for explicit default selection filters
- Measure-parameter visuals use only relationship-safe context dimensions declared in the blueprint
- No duplicate visual IDs within a page
- All JSON files reference the correct Microsoft
$schemaURLs - All JSON files are encoded as UTF-8 without BOM
- Every visual requiring explicit ranking or ordering has
query.sortDefinition - Every visual with
implementationStrategyis implemented with the declared strategy mode or an explicitly approved equivalent - Top-row dropdown slicers respect the minimum usable height baseline (
>= 64 px) - Grouped KPI bands use an explicit value font size baseline (
20D) unless a validated design override exists - Gauge visuals use canonical
Y/TargetValuequery buckets - Treemap visuals use canonical
Group/Valuesquery buckets - Azure Map visuals use canonical
Category/Sizequery buckets and stable map object settings when the baseline behavior is required - Visual positions respect page padding, spacing tokens, and no-overlap rules unless explicitly overridden
Save all generated PBIR artifacts to disk.
Output Structure Example
The Report definition folder should look like:
<ProjectName>/PBIP/<ProjectName>.Report/definition/
├── report.json
├── version.json
└── pages/
├── Page1/
│ ├── page.json
│ └── visuals/
│ ├── slicer_01/
│ │ └── visual.json
│ ├── visual_01/
│ │ └── visual.json
│ ├── visual_02/
│ │ └── visual.json
│ └── visual_03/
│ └── visual.json
└── Page2/
├── page.json
└── visuals/
├── slicer_01/
│ └── visual.json
└── visual_01/
└── visual.json
References
| Reference | Path | Load |
|---|---|---|
| Visual JSON Templates | references/pbir-visual-templates.md |
MANDATORY — always load |
| Fields and Bindings | references/fields-and-bindings.md |
On demand — field types, data roles, queryState |
| Filters | references/filters.md |
On demand — filter types and JSON structure |
| Conditional Formatting | references/conditional-formatting.md |
On demand — CF types, container mappings |
| Extension Measures | references/extension-measures.md |
On demand — reportExtensions.json patterns |
| Visual Formatting Properties | references/visual-formatting-properties.md |
On demand — containers, property catalogue |
| Folder Structure | .github/references/pbip-folder-structure.md |
MANDATORY — folder hierarchy |
| Design Best Practices | .github/skills/report-design/references/report-design-visualization-best-practices.md |
On demand |