Power Apps Development
Power Apps Overview
Microsoft Power Apps is a low-code application development platform in the Power Platform family. It provides two primary app types:
Canvas Apps give full pixel-level control over the UI. Developers drag controls onto a canvas, bind them to data sources, and write Power Fx formulas for behavior and logic. Canvas apps run in a browser or mobile player.
Model-Driven Apps are built on top of Dataverse tables. The UI is auto-generated from the data model — forms, views, dashboards, and business process flows are configured rather than designed from scratch. Model-driven apps enforce consistent navigation, security roles, and business rules.
Power Fx Language
Power Fx is the formula language used in canvas apps (and increasingly across Power Platform). It's inspired by Excel formulas, making it approachable for spreadsheet users.
Core Functions
Data operations:
Patch(DataSource, Record, Changes) — Create or update a record. The most important data write function.
Collect(Collection, Records) — Add records to a collection (local in-memory table) or data source.
ClearCollect(Collection, Records) — Clear a collection and add new records.
Remove(DataSource, Record) — Delete a record.
UpdateIf(DataSource, Condition, Changes) — Update records matching a condition.
RemoveIf(DataSource, Condition) — Delete records matching a condition.
LookUp(DataSource, Condition, Column) — Return the first matching record or column value.
Filter(DataSource, Condition) — Return all matching records.
Search(DataSource, SearchText, Column1, Column2) — Full-text search across columns.
Sort(Table, Column, Order) — Sort a table by a column.
SortByColumns(Table, Column1, Order1, Column2, Order2) — Multi-column sort.
Text:
Concatenate(str1, str2) or str1 & str2 — Join strings.
Text(Value, Format) — Format numbers, dates, and times as text.
Value(Text) — Parse text to a number.
Left, Right, Mid, Len, Find, Substitute, Upper, Lower, Trim.
Logic:
If(Condition, TrueResult, FalseResult) — Conditional branching.
Switch(Value, Match1, Result1, Match2, Result2, DefaultResult) — Multi-way branching.
IsBlank(Value), IsEmpty(Table) — Null and empty checks.
Coalesce(Value1, Value2) — Return first non-blank value.
Navigation:
Navigate(Screen, Transition, Context) — Navigate to a screen with optional context variables.
Back() — Return to the previous screen.
Set(Variable, Value) — Set a global variable.
UpdateContext({Var1: Value1}) — Set context (screen-scoped) variables.
User:
User() — Returns .Email, .FullName, .Image of the signed-in user.
Delegation
Delegation is the most critical performance concept in canvas apps. When a formula can be delegated, the data source (e.g., Dataverse, SharePoint, SQL) processes the query server-side and returns only the results. When delegation is not supported, Power Apps downloads up to 500 (or 2,000 max) rows and processes locally.
Delegable functions: Filter, Sort, SortByColumns, Search (Dataverse only), LookUp, FirstN.
Delegable operators (varies by data source): =, <>, <, >, <=, >=, &&, ||, !, in, exactin, StartsWith.
Non-delegable (always local): CountRows, Sum, Average, GroupBy, AddColumns, DropColumns, ShowColumns, RenameColumns, Distinct, First, Last, ForAll (as aggregate), Concat.
Dataverse has the broadest delegation support. SharePoint and SQL Server have partial support. Excel has no delegation.
Collections and Variables
- Global variables (
Set): Accessible from any screen. Used for app-wide state (selected record, user preferences).
- Context variables (
UpdateContext): Screen-scoped. Reset when navigating away. Good for modal dialogs and temporary state.
- Collections (
Collect, ClearCollect): In-memory tables. Used for offline caching, temporary data manipulation, and multi-step form workflows.
Error Handling
IfError(Value, Fallback) — Return fallback if the value is an error.
IsError(Value) — Check if a value is an error.
Notify(Message, NotificationType) — Display a toast notification. Types: Success, Error, Warning, Information.
Errors(DataSource) — Return a table of errors from the last data operation.
Model-Driven App Configuration
Forms
Model-driven app forms are configured via Dataverse form designer or solution XML:
- Main forms: Full-page record forms with tabs, sections, and controls.
- Quick create forms: Compact forms for rapid data entry (modal).
- Quick view forms: Read-only embedded views of related records.
- Card forms: Compact representations for mobile views.
Key form elements: tabs, sections, columns, sub-grids (related records), business process flows, timeline (notes/activities), web resources.
Views
Views are saved queries that display records in a grid:
- Public views: Available to all users.
- Personal views: Created by individual users.
- System views: Default views (Active Records, Inactive Records, etc.).
- Quick find views: Used by the search bar.
Defined by a FetchXML query and a layoutxml for column display.
Business Rules
Declarative server-side or client-side logic on forms:
- Show/hide fields based on conditions.
- Set field values.
- Set required/optional fields.
- Show error messages.
- Lock/unlock fields.
Business rules run without code and are defined in the Dataverse solution.
Business Process Flows
Guided multi-stage processes that walk users through a defined workflow. Each stage has steps (fields to complete). Stages can span multiple tables (e.g., Lead → Opportunity → Order).
Site Map
Defines the navigation structure: areas → groups → sub-areas (links to tables, dashboards, web resources, or custom pages).
Custom Connectors
Custom connectors wrap external REST APIs for use in Power Apps, Power Automate, and Copilot Studio.
Definition (OpenAPI 2.0 / Swagger):
{
"swagger": "2.0",
"info": { "title": "My API", "version": "1.0" },
"host": "api.example.com",
"basePath": "/v1",
"schemes": ["https"],
"securityDefinitions": {
"oauth2": {
"type": "oauth2",
"flow": "accessCode",
"authorizationUrl": "https://login.example.com/authorize",
"tokenUrl": "https://login.example.com/token",
"scopes": { "read": "Read access" }
}
},
"paths": {
"/items": {
"get": {
"summary": "List items",
"operationId": "ListItems",
"produces": ["application/json"],
"responses": {
"200": {
"description": "Success",
"schema": {
"type": "array",
"items": { "$ref": "#/definitions/Item" }
}
}
}
}
}
}
}
Auth types: API Key, Basic, OAuth 2.0 (authorization code, client credentials), Azure AD.
Policy templates: Set Host URL, route request, set header, convert JSON to object.
Component Libraries
Reusable canvas component libraries allow you to build controls once and share across multiple apps:
- Canvas components: Custom controls with input/output properties, built with the same Power Fx formulas.
- Input properties: Parameters passed into the component (e.g.,
ItemColor, DataSource).
- Output properties: Values emitted from the component (e.g.,
SelectedItem).
- Behavior properties: Actions triggered by events (e.g.,
OnSelect, OnChange).
Component libraries are stored as Dataverse solutions and can be published to the tenant.
Responsive Design
Canvas apps support responsive layouts using container controls:
- Horizontal container: Lay out children side by side.
- Vertical container: Stack children vertically.
- Flexible height/width: Use
LayoutMinWidth and LayoutMinHeight for responsive breakpoints.
- Fill portions: Allocate space proportionally among siblings.
Solution Checker
The Power Apps Solution Checker runs static analysis to identify performance issues, security vulnerabilities, and design anti-patterns. Key rule categories:
- Performance: N+1 queries, unbounded loops, missing delegation warnings.
- Security: Hardcoded credentials, insecure HTTP connections.
- Reliability: Unhandled errors, missing required fields.
- Maintainability: Unused variables, overly complex formulas.
- Web API: Deprecated API usage, incorrect metadata.
Run via pac solution check --path <solution.zip> or via the Power Platform admin center.
Power Apps Management REST API
The Business Application Platform (BAP) API provides environment and app lifecycle management outside of the maker portal.
Base URL: https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform
| Method |
Endpoint |
Purpose |
| GET |
/scopes/admin/environments |
List all environments in the tenant |
| GET |
/scopes/admin/environments/{envId} |
Get environment details (type, region, state) |
| POST |
/environments |
Create a new environment |
| DELETE |
/scopes/admin/environments/{envId} |
Delete an environment |
| GET |
/scopes/admin/environments/{envId}/apps |
List canvas apps in an environment |
| GET |
/scopes/admin/environments/{envId}/apps/{appId} |
Get app details (version, owner, last modified) |
| DELETE |
/scopes/admin/environments/{envId}/apps/{appId} |
Delete a canvas app |
| POST |
/scopes/admin/environments/{envId}/apps/{appId}/permissions |
Grant or revoke app permissions |
| GET |
/scopes/admin/environments/{envId}/apps/{appId}/permissions |
List current app permissions |
Headers: Authorization: Bearer <token>, api-version: 2016-11-01
Create environment body:
{
"location": "unitedstates",
"properties": {
"displayName": "Dev Sandbox",
"environmentSku": "Sandbox",
"linkedEnvironmentMetadata": {
"type": "Dynamics365Instance",
"securityGroupId": "<aad-group-id>"
}
}
}
Environment SKU values: Production, Sandbox, Trial, Developer.
Dataverse Web API for App Data
The Dataverse Web API provides REST-based CRUD operations on Dataverse tables — the data layer behind model-driven and canvas apps.
Base URL: https://{org}.api.crm.dynamics.com/api/data/v9.2
| Method |
Endpoint |
Purpose |
| GET |
/{entitySetName} |
List records (with OData query) |
| GET |
/{entitySetName}({id}) |
Get a single record |
| POST |
/{entitySetName} |
Create a record |
| PATCH |
/{entitySetName}({id}) |
Update a record (merge semantics) |
| DELETE |
/{entitySetName}({id}) |
Delete a record |
| POST |
/{entitySetName}({id})/Microsoft.Dynamics.CRM.{actionName} |
Execute a bound action |
Create record example:
POST /api/data/v9.2/accounts
{
"name": "Contoso Ltd",
"telephone1": "555-0100",
"address1_city": "Seattle",
"primarycontactid@odata.bind": "/contacts(00000000-0000-0000-0000-000000000001)"
}
Update record example:
PATCH /api/data/v9.2/accounts(00000000-0000-0000-0000-000000000002)
{
"telephone1": "555-0200",
"address1_city": "Redmond"
}
OData query options: $select, $filter, $orderby, $top, $skip, $expand, $count.
Example: GET /accounts?$select=name,telephone1&$filter=address1_city eq 'Seattle'&$top=50
Permissions and Scopes
| Scope / Resource |
Purpose |
https://api.bap.microsoft.com/.default |
BAP Management API — environment and app management |
https://{org}.crm.dynamics.com/.default |
Dataverse Web API — record-level CRUD |
https://graph.microsoft.com/User.Read |
Basic user profile for maker identity |
https://service.powerapps.com/.default |
Power Apps authoring service |
Token acquisition uses @azure/identity with ClientSecretCredential or InteractiveBrowserCredential. The {org} placeholder is the Dataverse organization URL (e.g., contoso.crm.dynamics.com).
HTTP Error Handling
| Status |
Meaning |
Action |
| 400 |
Bad Request — invalid JSON, missing required field, or malformed OData query |
Check request body schema and query syntax |
| 401 |
Unauthorized — expired or missing token |
Re-acquire token; verify scope matches the resource |
| 403 |
Forbidden — insufficient privileges or security role |
Verify the user/app has the required Dataverse security role or BAP admin role |
| 404 |
Not Found — record, app, or environment does not exist |
Confirm the ID and entity set name; check for deleted records |
| 409 |
Conflict — duplicate key or concurrent update |
Retry with fresh ETag; check for alternate key collisions |
| 429 |
Too Many Requests — throttled by Dataverse or BAP |
Retry after the Retry-After header value (seconds); implement exponential backoff |
Dataverse error responses follow this structure:
{
"error": {
"code": "0x80040265",
"message": "The specified record was not found or you do not have permission."
}
}
Common Patterns
Multi-Step Canvas Form with Offline Collection
Build a multi-screen form that collects data offline and syncs on connectivity:
- Create a
colPendingRecords collection on app start with ClearCollect.
- Each form screen writes to the collection via
Collect(colPendingRecords, {Field1: txt1.Text, ...}).
- A "Submit All" button iterates with
ForAll(colPendingRecords, Patch(DataSource, Defaults(DataSource), ThisRecord)).
- Wrap each
Patch in IfError to track failures: Collect(colErrors, {Record: ThisRecord, Error: FirstError.Message}).
- Show a summary screen with success count and error table.
- Use
Connection.Connected to check connectivity before submission.
Model-Driven App with Custom Business Process Flow
Build a model-driven app for a multi-stage approval workflow:
- Create a Dataverse table (e.g.,
cr_expense_request) with status columns for each stage.
- Define a Business Process Flow with stages: Submission → Manager Review → Finance Approval → Completed.
- Add branching logic: if amount > $5,000, route to VP Approval stage before Finance.
- Configure each stage with required fields (justification, receipt attachment, approval notes).
- Add a Business Rule to lock the Amount field after Submission stage completes.
- Use a Real-time Workflow or Power Automate flow to send email notifications on stage transitions.
PCF Control with Dataverse Web API
Build a custom PCF (PowerApps Component Framework) control:
- Scaffold with
pac pcf init --namespace Contoso --name MapPicker --template field.
- Define the manifest (
ControlManifest.Input.xml) with input properties: latitude, longitude, zoomLevel.
- In
index.ts, implement init() to render a map container, updateView() to re-center on property changes, and getOutputs() to return the selected coordinates.
- Use
this.context.webAPI.retrieveMultipleRecords("account", "?$select=name,address1_latitude,address1_longitude&$top=100") to fetch nearby records.
- Build with
npm run build, test with npm start watch, and package with pac pcf push --publisher-prefix cr.
App Creation Workflows
Source Format Note
The current Power Apps canvas source format is .pa.yaml (Source Code v3.0). The older .fx.yaml format is retired. New apps should always use .pa.yaml with Power Platform Git Integration. See references/canvas-app-source.md for the full schema reference.
Decision Tree — Which Command to Use
Want to create a Power App?
├── Canvas app (custom UI)?
│ ├── Have a data source schema? → /pa-app-from-data
│ ├── Know the app pattern? → /pa-app-create --template <type>
│ │ ├── CRUD (list/detail/edit) → --template crud
│ │ ├── Dashboard with KPIs → --template dashboard
│ │ ├── Approval workflow → --template approval
│ │ ├── Side-by-side master/detail → --template master-detail
│ │ └── Empty starting point → --template blank
│ └── Need a single screen? → /pa-canvas-screen
├── Model-driven app (Dataverse UI)?
│ └── /pa-mda-create --template crud|service-desk
└── Ready to deploy?
└── /pa-deploy canvas|solution
Canvas App Creation Workflow
- Scaffold — Use
/pa-app-create to generate the project directory with .pa.yaml files. Choose a template that matches your use case.
- Customize — Edit individual screens with
/pa-canvas-screen. Add formulas with /pa-formula. Create components with /pa-component-create.
- Validate — Run
pac canvas validate --path ./src to check for errors.
- Deploy — Use
/pa-deploy canvas to pack and import, or push to the connected Git branch for Git Integration sync.
Model-Driven App Creation Workflow
- Scaffold — Use
/pa-mda-create to generate the solution with sitemap, forms, views, and optional BPF/business rules.
- Customize — Edit forms with
/pa-model-driven-form. Add custom connectors with /pa-connector-create.
- Validate — Run
/pa-solution-checker to check for issues.
- Deploy — Use
/pa-deploy solution to pack and import to the target environment.
Best Practices
- Delegation first: Design data access patterns to be delegable. Use Dataverse as the primary data source for the best delegation support.
- Minimize data calls: Use
ClearCollect on app start for reference data, then filter collections locally.
- Concurrent loading: Use
Concurrent() in App.OnStart to load multiple data sources in parallel.
- Component reuse: Build component libraries for common UI patterns (headers, sidebars, data cards).
- Naming conventions: Use prefixes —
scr for screens, btn for buttons, gal for galleries, txt for text inputs, lbl for labels, ico for icons.
- Error handling: Wrap data operations with
IfError and show Notify messages to users.
- App.Formulas: Use
App.Formulas (named formulas) instead of App.OnStart for declarative data loading — they're recalculated automatically and improve app startup time.
Reference Files
| Reference |
Path |
Content |
| Power Fx Functions |
references/power-fx-functions.md |
Complete function reference with delegation info |
| Model-Driven Config |
references/model-driven-config.md |
Forms, views, business rules, site map |
| Custom Connectors |
references/custom-connectors.md |
OpenAPI definition, auth, policies |
| Responsive Layout |
references/responsive-layout.md |
Container controls and responsive patterns |
Example Files
| Example |
Path |
Content |
| CRUD Canvas App |
examples/crud-canvas-app.md |
Complete Dataverse CRUD with gallery, form, and error handling |
| Custom Connector |
examples/custom-connector.md |
REST API wrapper with OAuth 2.0 |
| Component Library |
examples/component-library.md |
Reusable header, sidebar, and data card components |
| Responsive App |
examples/responsive-app.md |
Mobile-first responsive layout with containers |
Progressive Disclosure — Reference Files
| Topic |
File |
| Canvas app creation, PAC CLI, screen navigation, Gallery patterns, Patch, offline mode, ALM |
references/canvas-apps.md |
.pa.yaml source format, control type catalog, Git Integration workflow, PAC CLI pack/unpack |
references/canvas-app-source.md |
| App template patterns — CRUD, Dashboard, Approval, Master-Detail, Model-Driven CRUD/Service Desk |
references/app-templates.md |
| Model-driven app creation, sitemap XML, form/view XML, business rules, command bar, PCF |
references/model-driven-apps.md |
| Power Fx core functions, delegation, type coercion, error handling, named formulas, ParseJSON |
references/power-fx-formulas.md |
| Custom connectors, OpenAPI definition, auth types, actions vs triggers, code policy, sharing |
references/custom-connectors.md |
1---2name: power-apps-development3description: Deep expertise in Microsoft Power Apps — canvas app Power Fx formulas, model-driven app configuration, custom connector development, component libraries, PCF code components, solution checker validation, and responsive layout design.4---56# Power Apps Development78## Power Apps Overview910Microsoft Power Apps is a low-code application development platform in the Power Platform family. It provides two primary app types:1112**Canvas Apps** give full pixel-level control over the UI. Developers drag controls onto a canvas, bind them to data sources, and write Power Fx formulas for behavior and logic. Canvas apps run in a browser or mobile player.1314**Model-Driven Apps** are built on top of Dataverse tables. The UI is auto-generated from the data model — forms, views, dashboards, and business process flows are configured rather than designed from scratch. Model-driven apps enforce consistent navigation, security roles, and business rules.1516## Power Fx Language1718Power Fx is the formula language used in canvas apps (and increasingly across Power Platform). It's inspired by Excel formulas, making it approachable for spreadsheet users.1920### Core Functions2122**Data operations**:23- `Patch(DataSource, Record, Changes)` — Create or update a record. The most important data write function.24- `Collect(Collection, Records)` — Add records to a collection (local in-memory table) or data source.25- `ClearCollect(Collection, Records)` — Clear a collection and add new records.26- `Remove(DataSource, Record)` — Delete a record.27- `UpdateIf(DataSource, Condition, Changes)` — Update records matching a condition.28- `RemoveIf(DataSource, Condition)` — Delete records matching a condition.29- `LookUp(DataSource, Condition, Column)` — Return the first matching record or column value.30- `Filter(DataSource, Condition)` — Return all matching records.31- `Search(DataSource, SearchText, Column1, Column2)` — Full-text search across columns.32- `Sort(Table, Column, Order)` — Sort a table by a column.33- `SortByColumns(Table, Column1, Order1, Column2, Order2)` — Multi-column sort.3435**Text**:36- `Concatenate(str1, str2)` or `str1 & str2` — Join strings.37- `Text(Value, Format)` — Format numbers, dates, and times as text.38- `Value(Text)` — Parse text to a number.39- `Left`, `Right`, `Mid`, `Len`, `Find`, `Substitute`, `Upper`, `Lower`, `Trim`.4041**Logic**:42- `If(Condition, TrueResult, FalseResult)` — Conditional branching.43- `Switch(Value, Match1, Result1, Match2, Result2, DefaultResult)` — Multi-way branching.44- `IsBlank(Value)`, `IsEmpty(Table)` — Null and empty checks.45- `Coalesce(Value1, Value2)` — Return first non-blank value.4647**Navigation**:48- `Navigate(Screen, Transition, Context)` — Navigate to a screen with optional context variables.49- `Back()` — Return to the previous screen.50- `Set(Variable, Value)` — Set a global variable.51- `UpdateContext({Var1: Value1})` — Set context (screen-scoped) variables.5253**User**:54- `User()` — Returns `.Email`, `.FullName`, `.Image` of the signed-in user.5556### Delegation5758Delegation is the most critical performance concept in canvas apps. When a formula can be delegated, the data source (e.g., Dataverse, SharePoint, SQL) processes the query server-side and returns only the results. When delegation is not supported, Power Apps downloads up to 500 (or 2,000 max) rows and processes locally.5960**Delegable functions**: `Filter`, `Sort`, `SortByColumns`, `Search` (Dataverse only), `LookUp`, `FirstN`.6162**Delegable operators** (varies by data source): `=`, `<>`, `<`, `>`, `<=`, `>=`, `&&`, `||`, `!`, `in`, `exactin`, `StartsWith`.6364**Non-delegable** (always local): `CountRows`, `Sum`, `Average`, `GroupBy`, `AddColumns`, `DropColumns`, `ShowColumns`, `RenameColumns`, `Distinct`, `First`, `Last`, `ForAll` (as aggregate), `Concat`.6566**Dataverse** has the broadest delegation support. **SharePoint** and **SQL Server** have partial support. **Excel** has no delegation.6768### Collections and Variables6970- **Global variables** (`Set`): Accessible from any screen. Used for app-wide state (selected record, user preferences).71- **Context variables** (`UpdateContext`): Screen-scoped. Reset when navigating away. Good for modal dialogs and temporary state.72- **Collections** (`Collect`, `ClearCollect`): In-memory tables. Used for offline caching, temporary data manipulation, and multi-step form workflows.7374### Error Handling7576- `IfError(Value, Fallback)` — Return fallback if the value is an error.77- `IsError(Value)` — Check if a value is an error.78- `Notify(Message, NotificationType)` — Display a toast notification. Types: `Success`, `Error`, `Warning`, `Information`.79- `Errors(DataSource)` — Return a table of errors from the last data operation.8081## Model-Driven App Configuration8283### Forms8485Model-driven app forms are configured via Dataverse form designer or solution XML:8687- **Main forms**: Full-page record forms with tabs, sections, and controls.88- **Quick create forms**: Compact forms for rapid data entry (modal).89- **Quick view forms**: Read-only embedded views of related records.90- **Card forms**: Compact representations for mobile views.9192Key form elements: tabs, sections, columns, sub-grids (related records), business process flows, timeline (notes/activities), web resources.9394### Views9596Views are saved queries that display records in a grid:9798- **Public views**: Available to all users.99- **Personal views**: Created by individual users.100- **System views**: Default views (Active Records, Inactive Records, etc.).101- **Quick find views**: Used by the search bar.102103Defined by a FetchXML query and a layoutxml for column display.104105### Business Rules106107Declarative server-side or client-side logic on forms:108109- Show/hide fields based on conditions.110- Set field values.111- Set required/optional fields.112- Show error messages.113- Lock/unlock fields.114115Business rules run without code and are defined in the Dataverse solution.116117### Business Process Flows118119Guided multi-stage processes that walk users through a defined workflow. Each stage has steps (fields to complete). Stages can span multiple tables (e.g., Lead → Opportunity → Order).120121### Site Map122123Defines the navigation structure: areas → groups → sub-areas (links to tables, dashboards, web resources, or custom pages).124125## Custom Connectors126127Custom connectors wrap external REST APIs for use in Power Apps, Power Automate, and Copilot Studio.128129**Definition** (OpenAPI 2.0 / Swagger):130```json131{132 "swagger": "2.0",133 "info": { "title": "My API", "version": "1.0" },134 "host": "api.example.com",135 "basePath": "/v1",136 "schemes": ["https"],137 "securityDefinitions": {138 "oauth2": {139 "type": "oauth2",140 "flow": "accessCode",141 "authorizationUrl": "https://login.example.com/authorize",142 "tokenUrl": "https://login.example.com/token",143 "scopes": { "read": "Read access" }144 }145 },146 "paths": {147 "/items": {148 "get": {149 "summary": "List items",150 "operationId": "ListItems",151 "produces": ["application/json"],152 "responses": {153 "200": {154 "description": "Success",155 "schema": {156 "type": "array",157 "items": { "$ref": "#/definitions/Item" }158 }159 }160 }161 }162 }163 }164}165```166167**Auth types**: API Key, Basic, OAuth 2.0 (authorization code, client credentials), Azure AD.168169**Policy templates**: Set Host URL, route request, set header, convert JSON to object.170171## Component Libraries172173Reusable canvas component libraries allow you to build controls once and share across multiple apps:174175- **Canvas components**: Custom controls with input/output properties, built with the same Power Fx formulas.176- **Input properties**: Parameters passed into the component (e.g., `ItemColor`, `DataSource`).177- **Output properties**: Values emitted from the component (e.g., `SelectedItem`).178- **Behavior properties**: Actions triggered by events (e.g., `OnSelect`, `OnChange`).179180Component libraries are stored as Dataverse solutions and can be published to the tenant.181182## Responsive Design183184Canvas apps support responsive layouts using container controls:185186- **Horizontal container**: Lay out children side by side.187- **Vertical container**: Stack children vertically.188- **Flexible height/width**: Use `LayoutMinWidth` and `LayoutMinHeight` for responsive breakpoints.189- **Fill portions**: Allocate space proportionally among siblings.190191## Solution Checker192193The Power Apps Solution Checker runs static analysis to identify performance issues, security vulnerabilities, and design anti-patterns. Key rule categories:194195- **Performance**: N+1 queries, unbounded loops, missing delegation warnings.196- **Security**: Hardcoded credentials, insecure HTTP connections.197- **Reliability**: Unhandled errors, missing required fields.198- **Maintainability**: Unused variables, overly complex formulas.199- **Web API**: Deprecated API usage, incorrect metadata.200201Run via `pac solution check --path <solution.zip>` or via the Power Platform admin center.202203## Power Apps Management REST API204205The Business Application Platform (BAP) API provides environment and app lifecycle management outside of the maker portal.206207Base URL: `https://api.bap.microsoft.com/providers/Microsoft.BusinessAppPlatform`208209| Method | Endpoint | Purpose |210|--------|----------|---------|211| GET | `/scopes/admin/environments` | List all environments in the tenant |212| GET | `/scopes/admin/environments/{envId}` | Get environment details (type, region, state) |213| POST | `/environments` | Create a new environment |214| DELETE | `/scopes/admin/environments/{envId}` | Delete an environment |215| GET | `/scopes/admin/environments/{envId}/apps` | List canvas apps in an environment |216| GET | `/scopes/admin/environments/{envId}/apps/{appId}` | Get app details (version, owner, last modified) |217| DELETE | `/scopes/admin/environments/{envId}/apps/{appId}` | Delete a canvas app |218| POST | `/scopes/admin/environments/{envId}/apps/{appId}/permissions` | Grant or revoke app permissions |219| GET | `/scopes/admin/environments/{envId}/apps/{appId}/permissions` | List current app permissions |220221**Headers**: `Authorization: Bearer <token>`, `api-version: 2016-11-01`222223**Create environment body**:224```json225{226 "location": "unitedstates",227 "properties": {228 "displayName": "Dev Sandbox",229 "environmentSku": "Sandbox",230 "linkedEnvironmentMetadata": {231 "type": "Dynamics365Instance",232 "securityGroupId": "<aad-group-id>"233 }234 }235}236```237238Environment SKU values: `Production`, `Sandbox`, `Trial`, `Developer`.239240## Dataverse Web API for App Data241242The Dataverse Web API provides REST-based CRUD operations on Dataverse tables — the data layer behind model-driven and canvas apps.243244Base URL: `https://{org}.api.crm.dynamics.com/api/data/v9.2`245246| Method | Endpoint | Purpose |247|--------|----------|---------|248| GET | `/{entitySetName}` | List records (with OData query) |249| GET | `/{entitySetName}({id})` | Get a single record |250| POST | `/{entitySetName}` | Create a record |251| PATCH | `/{entitySetName}({id})` | Update a record (merge semantics) |252| DELETE | `/{entitySetName}({id})` | Delete a record |253| POST | `/{entitySetName}({id})/Microsoft.Dynamics.CRM.{actionName}` | Execute a bound action |254255**Create record example**:256```json257POST /api/data/v9.2/accounts258{259 "name": "Contoso Ltd",260 "telephone1": "555-0100",261 "address1_city": "Seattle",262 "primarycontactid@odata.bind": "/contacts(00000000-0000-0000-0000-000000000001)"263}264```265266**Update record example**:267```json268PATCH /api/data/v9.2/accounts(00000000-0000-0000-0000-000000000002)269{270 "telephone1": "555-0200",271 "address1_city": "Redmond"272}273```274275**OData query options**: `$select`, `$filter`, `$orderby`, `$top`, `$skip`, `$expand`, `$count`.276277Example: `GET /accounts?$select=name,telephone1&$filter=address1_city eq 'Seattle'&$top=50`278279## Permissions and Scopes280281| Scope / Resource | Purpose |282|------------------|---------|283| `https://api.bap.microsoft.com/.default` | BAP Management API — environment and app management |284| `https://{org}.crm.dynamics.com/.default` | Dataverse Web API — record-level CRUD |285| `https://graph.microsoft.com/User.Read` | Basic user profile for maker identity |286| `https://service.powerapps.com/.default` | Power Apps authoring service |287288Token acquisition uses `@azure/identity` with `ClientSecretCredential` or `InteractiveBrowserCredential`. The `{org}` placeholder is the Dataverse organization URL (e.g., `contoso.crm.dynamics.com`).289290## HTTP Error Handling291292| Status | Meaning | Action |293|--------|---------|--------|294| 400 | Bad Request — invalid JSON, missing required field, or malformed OData query | Check request body schema and query syntax |295| 401 | Unauthorized — expired or missing token | Re-acquire token; verify scope matches the resource |296| 403 | Forbidden — insufficient privileges or security role | Verify the user/app has the required Dataverse security role or BAP admin role |297| 404 | Not Found — record, app, or environment does not exist | Confirm the ID and entity set name; check for deleted records |298| 409 | Conflict — duplicate key or concurrent update | Retry with fresh ETag; check for alternate key collisions |299| 429 | Too Many Requests — throttled by Dataverse or BAP | Retry after the `Retry-After` header value (seconds); implement exponential backoff |300301Dataverse error responses follow this structure:302```json303{304 "error": {305 "code": "0x80040265",306 "message": "The specified record was not found or you do not have permission."307 }308}309```310311## Common Patterns312313### Multi-Step Canvas Form with Offline Collection314315Build a multi-screen form that collects data offline and syncs on connectivity:3163171. Create a `colPendingRecords` collection on app start with `ClearCollect`.3182. Each form screen writes to the collection via `Collect(colPendingRecords, {Field1: txt1.Text, ...})`.3193. A "Submit All" button iterates with `ForAll(colPendingRecords, Patch(DataSource, Defaults(DataSource), ThisRecord))`.3204. Wrap each `Patch` in `IfError` to track failures: `Collect(colErrors, {Record: ThisRecord, Error: FirstError.Message})`.3215. Show a summary screen with success count and error table.3226. Use `Connection.Connected` to check connectivity before submission.323324### Model-Driven App with Custom Business Process Flow325326Build a model-driven app for a multi-stage approval workflow:3273281. Create a Dataverse table (e.g., `cr_expense_request`) with status columns for each stage.3292. Define a Business Process Flow with stages: Submission → Manager Review → Finance Approval → Completed.3303. Add branching logic: if amount > $5,000, route to VP Approval stage before Finance.3314. Configure each stage with required fields (justification, receipt attachment, approval notes).3325. Add a Business Rule to lock the Amount field after Submission stage completes.3336. Use a Real-time Workflow or Power Automate flow to send email notifications on stage transitions.334335### PCF Control with Dataverse Web API336337Build a custom PCF (PowerApps Component Framework) control:3383391. Scaffold with `pac pcf init --namespace Contoso --name MapPicker --template field`.3402. Define the manifest (`ControlManifest.Input.xml`) with input properties: `latitude`, `longitude`, `zoomLevel`.3413. In `index.ts`, implement `init()` to render a map container, `updateView()` to re-center on property changes, and `getOutputs()` to return the selected coordinates.3424. Use `this.context.webAPI.retrieveMultipleRecords("account", "?$select=name,address1_latitude,address1_longitude&$top=100")` to fetch nearby records.3435. Build with `npm run build`, test with `npm start watch`, and package with `pac pcf push --publisher-prefix cr`.344345## App Creation Workflows346347### Source Format Note348349The current Power Apps canvas source format is **`.pa.yaml`** (Source Code v3.0). The older `.fx.yaml` format is retired. New apps should always use `.pa.yaml` with Power Platform Git Integration. See `references/canvas-app-source.md` for the full schema reference.350351### Decision Tree — Which Command to Use352353```354Want to create a Power App?355├── Canvas app (custom UI)?356│ ├── Have a data source schema? → /pa-app-from-data357│ ├── Know the app pattern? → /pa-app-create --template <type>358│ │ ├── CRUD (list/detail/edit) → --template crud359│ │ ├── Dashboard with KPIs → --template dashboard360│ │ ├── Approval workflow → --template approval361│ │ ├── Side-by-side master/detail → --template master-detail362│ │ └── Empty starting point → --template blank363│ └── Need a single screen? → /pa-canvas-screen364├── Model-driven app (Dataverse UI)?365│ └── /pa-mda-create --template crud|service-desk366└── Ready to deploy?367 └── /pa-deploy canvas|solution368```369370### Canvas App Creation Workflow3713721. **Scaffold** — Use `/pa-app-create` to generate the project directory with `.pa.yaml` files. Choose a template that matches your use case.3732. **Customize** — Edit individual screens with `/pa-canvas-screen`. Add formulas with `/pa-formula`. Create components with `/pa-component-create`.3743. **Validate** — Run `pac canvas validate --path ./src` to check for errors.3754. **Deploy** — Use `/pa-deploy canvas` to pack and import, or push to the connected Git branch for Git Integration sync.376377### Model-Driven App Creation Workflow3783791. **Scaffold** — Use `/pa-mda-create` to generate the solution with sitemap, forms, views, and optional BPF/business rules.3802. **Customize** — Edit forms with `/pa-model-driven-form`. Add custom connectors with `/pa-connector-create`.3813. **Validate** — Run `/pa-solution-checker` to check for issues.3824. **Deploy** — Use `/pa-deploy solution` to pack and import to the target environment.383384## Best Practices385386- **Delegation first**: Design data access patterns to be delegable. Use Dataverse as the primary data source for the best delegation support.387- **Minimize data calls**: Use `ClearCollect` on app start for reference data, then filter collections locally.388- **Concurrent loading**: Use `Concurrent()` in `App.OnStart` to load multiple data sources in parallel.389- **Component reuse**: Build component libraries for common UI patterns (headers, sidebars, data cards).390- **Naming conventions**: Use prefixes — `scr` for screens, `btn` for buttons, `gal` for galleries, `txt` for text inputs, `lbl` for labels, `ico` for icons.391- **Error handling**: Wrap data operations with `IfError` and show `Notify` messages to users.392- **App.Formulas**: Use `App.Formulas` (named formulas) instead of `App.OnStart` for declarative data loading — they're recalculated automatically and improve app startup time.393394## Reference Files395396| Reference | Path | Content |397|-----------|------|---------|398| Power Fx Functions | `references/power-fx-functions.md` | Complete function reference with delegation info |399| Model-Driven Config | `references/model-driven-config.md` | Forms, views, business rules, site map |400| Custom Connectors | `references/custom-connectors.md` | OpenAPI definition, auth, policies |401| Responsive Layout | `references/responsive-layout.md` | Container controls and responsive patterns |402403## Example Files404405| Example | Path | Content |406|---------|------|---------|407| CRUD Canvas App | `examples/crud-canvas-app.md` | Complete Dataverse CRUD with gallery, form, and error handling |408| Custom Connector | `examples/custom-connector.md` | REST API wrapper with OAuth 2.0 |409| Component Library | `examples/component-library.md` | Reusable header, sidebar, and data card components |410| Responsive App | `examples/responsive-app.md` | Mobile-first responsive layout with containers |411412## Progressive Disclosure — Reference Files413414| Topic | File |415|---|---|416| Canvas app creation, PAC CLI, screen navigation, Gallery patterns, Patch, offline mode, ALM | [`references/canvas-apps.md`](./references/canvas-apps.md) |417| `.pa.yaml` source format, control type catalog, Git Integration workflow, PAC CLI pack/unpack | [`references/canvas-app-source.md`](./references/canvas-app-source.md) |418| App template patterns — CRUD, Dashboard, Approval, Master-Detail, Model-Driven CRUD/Service Desk | [`references/app-templates.md`](./references/app-templates.md) |419| Model-driven app creation, sitemap XML, form/view XML, business rules, command bar, PCF | [`references/model-driven-apps.md`](./references/model-driven-apps.md) |420| Power Fx core functions, delegation, type coercion, error handling, named formulas, ParseJSON | [`references/power-fx-formulas.md`](./references/power-fx-formulas.md) |421| Custom connectors, OpenAPI definition, auth types, actions vs triggers, code policy, sharing | [`references/custom-connectors.md`](./references/custom-connectors.md) |