Skill: Project Initialization (PBIP Canvas Bootstrap)
Goal
Bootstrap a new project folder so Power BI Desktop can open it as a PBIP project without requiring the user to manually create the empty canvas first.
This skill creates the minimal PBIP + Report (PBIR) + SemanticModel (TMDL) scaffolding and the project subfolders used by later steps.
Placeholder Guardrail (MANDATORY)
- The literal repository folder
[ProjectName]/is a documentation placeholder and example scaffold only. - NEVER initialize, overwrite, repair, or adopt
[ProjectName]/as the active project. - ALWAYS create or target a real project folder with a business-specific name at repository root.
- If the only matching folder is
[ProjectName]/, STOP and create a new sibling project folder instead of modifying the placeholder. - Treat
<ProjectName>in this skill as a variable token, not as the literal bracketed folder name.
Input / Output
| Input | Target project path (must exist and be writable) |
| Output | Complete PBIP scaffold: .pbip, .Report/, .SemanticModel/, project subfolders |
When to Run
Run this skill whenever:
- The user points to a real project folder
<ProjectName>/at repository root, AND <ProjectName>/PBIP/or the chosen PBIP entry file is missing, OR- the chosen
.Report/or.SemanticModel/folders are missing.
Do NOT run this skill against the literal placeholder folder [ProjectName]/.
Non-Negotiable Constraints
- Use Microsoft official JSON schemas declared in the files.
- Paths inside PBIP/PBIR definitions MUST be relative and MUST use
/as separator. - Files should be encoded as UTF-8 without BOM.
- This repo standard keeps PBIP artifacts under
<ProjectName>/PBIP/(not at project root). - The initialization target MUST be a newly created or explicitly user-approved real project folder, never the placeholder
[ProjectName]/.
PBIP Naming And Path Budget (MANDATORY)
- Before creating the canvas, evaluate the full repository path length.
- If the repository root is already long, choose a short
<PbipBaseName>for the.pbip,.Report, and.SemanticModelitem names instead of blindly reusing<ProjectName>. <PbipBaseName>may differ from the business-facing project folder name, as long as all internal references stay aligned.- Leave margin for Power BI Desktop system-generated metadata files that may be created during save operations and may use autogenerated names.
Examples:
- ✅ Good: project folder
CustomerProfitabilityAnalysis/with PBIP itemsCPA.pbip,CPA.Report,CPA.SemanticModel - ✅ Good: project folder
SalesAnalyticsPerformance/with PBIP itemsSAP.pbip,SAP.Report,SAP.SemanticModel - ❌ Bad: always forcing
.pbip,.Report, and.SemanticModelnames to repeat a long project name under a deep repository path
What to Create
1) Project subfolders (if missing)
Under <ProjectName>/ ensure the existence of:
spec/data/scripts/tests/PBIP/
If you create any of these folders, also create a README.md in each folder with:
data/README.md: This folder contains generated CSV mock data files for local development and testing.scripts/README.md: This folder contains Python scripts for mock data generation and data processing utilities.tests/README.md: This folder contains functional test definitions, execution reports, and test result artifacts.spec/README.md: This folder contains user-provided specification files (requirements, functional specs, etc.).PBIP/README.md: This folder contains PBIP project artifacts (Report and Semantic Model definitions).
2) PBIP shortcut file (required for “open by .pbip”)
Choose a <PbipBaseName> that fits the path budget. It may equal <ProjectName>, but it does not have to.
Create <ProjectName>/PBIP/<PbipBaseName>.pbip with the minimal content:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/pbip/pbipProperties/1.0.0/schema.json",
"version": "1.0.0",
"artifacts": [
{
"report": {
"path": "<PbipBaseName>.Report"
}
}
],
"settings": {
"enableAutoRecovery": true
}
}
3) Report item folder (PBIR)
Create folder: <ProjectName>/PBIP/<PbipBaseName>.Report/
Create <ProjectName>/PBIP/<PbipBaseName>.Report/definition.pbir:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definitionProperties/2.0.0/schema.json",
"version": "4.0",
"datasetReference": {
"byPath": {
"path": "../<PbipBaseName>.SemanticModel"
}
}
}
Create the PBIR definition folder structure:
<ProjectName>/PBIP/<ProjectName>.Report/definition/<ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<PageObjectName>/<ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<PageObjectName>/visuals/<ProjectName>/PBIP/<ProjectName>.Report/StaticResources/SharedResources/BaseThemes/
Where <PageObjectName> is the PBIR page object name (recommended: 20-character lowercase alphanumeric id, for example 32fe1020890a4d7642b0). It must be unique within the report.
Create <ProjectName>/PBIP/<ProjectName>.Report/definition/version.json:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/versionMetadata/1.0.0/schema.json",
"version": "2.0.0"
}
CRITICAL: The
versionfield MUST follow semver format matching^[1-9][0-9]*\.(0|[1-9][0-9]*)\.0$(e.g.,"1.0.0"). Do NOT use"4.0"or any non-semver value — Power BI Desktop will reject it with a regex validation error. The value"4.0"belongs ONLY indefinition.pbiranddefinition.pbism, NOT inversion.json.
Create <ProjectName>/PBIP/<ProjectName>.Report/definition/report.json:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/report/3.1.0/schema.json",
"themeCollection": {
"baseTheme": {
"name": "ProjectDefault",
"reportVersionAtImport": {
"visual": "2.5.0",
"report": "3.1.0",
"page": "2.3.0"
},
"type": "SharedResources"
}
},
"objects": {
"section": [
{
"properties": {
"verticalAlignment": {
"expr": {
"Literal": {
"Value": "'Top'"
}
}
}
}
}
]
},
"resourcePackages": [
{
"name": "SharedResources",
"type": "SharedResources",
"items": [
{
"name": "ProjectDefault",
"path": "BaseThemes/ProjectDefault.json",
"type": "BaseTheme"
}
]
}
],
"settings": {
"useStylableVisualContainerHeader": true,
"exportDataMode": "AllowSummarized",
"defaultDrillFilterOtherVisuals": true,
"allowChangeFilterTypes": true,
"useEnhancedTooltips": true,
"useDefaultAggregateDisplayName": true
}
}
Create <ProjectName>/PBIP/<ProjectName>.Report/definition/pages/pages.json:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/pagesMetadata/1.0.0/schema.json",
"pageOrder": [
"<PageObjectName>"
],
"activePageName": "<PageObjectName>"
}
Create <ProjectName>/PBIP/<ProjectName>.Report/definition/pages/<PageObjectName>/page.json:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/report/definition/page/2.0.0/schema.json",
"name": "<PageObjectName>",
"displayName": "Page 1",
"displayOption": "FitToPage",
"height": 720,
"width": 1280
}
Create <ProjectName>/PBIP/<ProjectName>.Report/StaticResources/SharedResources/BaseThemes/ProjectDefault.json by copying the repository standard template from .github/templates/BaseThemes/ProjectDefault.json.
CRITICAL: Do NOT create
<ProjectName>.Report/report.jsonat report root. That file is PBIR-Legacy and causes a hard failure when combined with PBIR (definition/folder).
CRITICAL: The PBIR page schema
1.0.0does NOT allow additional properties. Only use the 6 properties shown above:$schema,name,displayName,displayOption,height,width. Do NOT addordinalor any other property — Power BI Desktop will reject the file withAdditionalPropertiesvalidation error. Page ordering is determined by folder name alphabetical order, not by any property. Use"FitToWidth"as the standard displayOption.
Notes:
- PBIR allows a report with a single empty page (no visuals).
- Keep the page folder name aligned with the page
nameto avoid surprises. - Keep
<ProjectName>/PBIP/<ProjectName>.Report/.pbi/out of source control and regenerate local settings in Desktop.
4) Semantic model item folder (TMDL)
Create folder: <ProjectName>/PBIP/<PbipBaseName>.SemanticModel/
Create <ProjectName>/PBIP/<PbipBaseName>.SemanticModel/definition.pbism:
{
"$schema": "https://developer.microsoft.com/json-schemas/fabric/item/semanticModel/definitionProperties/1.0.0/schema.json",
"version": "4.0",
"settings": {}
}
Create the TMDL definition folder structure:
<ProjectName>/PBIP/<ProjectName>.SemanticModel/definition/<ProjectName>/PBIP/<ProjectName>.SemanticModel/definition/tables/
Create minimal TMDL files (TAB-indented):
database.tmdl
database <ProjectName>
compatibilityLevel: 1600
model.tmdl
model Model
culture: en-US
defaultPowerBIDataSourceVersion: powerBI_V3
CRITICAL: Always include
defaultPowerBIDataSourceVersion: powerBI_V3. Omitting it causes "metadata version 3 required" errors in Power BI Desktop.
Optionally create empty placeholders (recommended for a stable baseline):
relationships.tmdl(empty)expressions.tmdl(empty)
Validation Gate
Before proceeding to Step 1, confirm:
-
<ProjectName>/PBIP/<PbipBaseName>.pbipexists and points to<PbipBaseName>.Report -
<ProjectName>/PBIP/<PbipBaseName>.Report/definition.pbirexists and references../<PbipBaseName>.SemanticModel -
<ProjectName>/PBIP/<PbipBaseName>.Report/definition/containsversion.json,report.json,pages/pages.json, andpages/<PageObjectName>/page.json -
<ProjectName>/PBIP/<PbipBaseName>.Report/StaticResources/SharedResources/BaseThemes/ProjectDefault.jsonexists and is referenced bydefinition/report.json -
<ProjectName>/PBIP/<PbipBaseName>.Report/report.jsondoes NOT exist -
<ProjectName>/PBIP/<PbipBaseName>.SemanticModel/definition.pbismexists -
<ProjectName>/PBIP/<PbipBaseName>.SemanticModel/definition/contains at leastdatabase.tmdlandmodel.tmdl - The chosen PBIP item basename leaves enough path budget for Desktop-generated metadata with autogenerated names
-
<ProjectName>/workflow_state.jsonexists with initial state
If any check fails, STOP and fix the initialization before running Step 1.
Workflow State Initialization
At the end of Step 00 (after all scaffolding is created and validated), CREATE the initial <ProjectName>/workflow_state.json:
{
"projectName": "<ProjectName>",
"currentStep": 0,
"completedSteps": [],
"pendingStep": null,
"createdAt": "<ISO 8601 timestamp>",
"lastUpdated": "<ISO 8601 timestamp>"
}
This file will be updated by every subsequent step to track workflow progress and enable resumability.