Power Apps Code Apps
Code Apps are code-first web applications (React + TypeScript + Vite) that run inside Power Platform with managed authentication, 1500+ connectors, governance, and ALM.
Architecture
Your Code (React SPA)
↓
Power Apps SDK (@microsoft/power-apps)
↓
Power Apps Host (Entra auth, app loading, error handling)
Authentication is managed by the host — never implement auth flows in app code. End users need a Power Apps Premium license.
Core Workflow
1. Scaffold a New Project
Use the starter template (React 19, Tailwind CSS 4, shadcn/ui, React Router, TanStack Query, TanStack Table, Zustand, Lucide icons). See references/cli-commands.md for scaffolding and all other CLI commands.
2. Add Data Sources
See references/cli-commands.md for the full data source workflow. Key points:
- •Dataverse tables are added directly:
pac code add-data-source -a dataverse -t {tableName} - •All other connectors require a connection and connection reference created in the Power Apps UI first, then use
pac code add-data-source -a {apiName} -cr {connectionRefLogicalName} -s {solutionId} - •Do NOT guess API names — discover them via
pac connection list - •Adding a data source auto-generates typed models and services under
generated/. Never hand-edit these files.
3. Use Generated Services in Code
import { AccountsService } from "./generated/services/AccountsService"
import type { Accounts } from "./generated/models/AccountsModel"
// Read with query options
const { data } = await AccountsService.getAll({
select: ["name", "accountnumber"],
filter: "address1_country eq 'USA'",
orderBy: ["name asc"],
top: 50,
})
// Create
await AccountsService.create({ name: "Contoso" } as Omit<Accounts, "accountid">)
// Update (partial)
await AccountsService.update(id, { name: "New Name" })
// Delete
await AccountsService.delete(id)
For complete API patterns (context, connectors, SharePoint, SQL, metadata, telemetry), see references/sdk-api-patterns.md.
4. Access App/User Context
import { getContext } from "@microsoft/power-apps/app"
const ctx = await getContext()
ctx.user.fullName // Current user's name
ctx.user.objectId // Entra object ID
ctx.app.environmentId // Environment ID
ctx.app.queryParams // URL query parameters
5. Build and Deploy
Always deploy to a specific solution — never to the default solution.
npm run build
pac code push --solutionName {solutionName}
Use Power Platform Pipelines to promote solutions across stages (Dev → Test → Prod).
Key Rules
- •Do NOT call
initialize()— removed in SDK v1.0. All APIs work directly. - •Do NOT edit
power.config.json— generated by the CLI for internal use. - •Do NOT store secrets in app code — apps are hosted on public endpoints. Use authenticated data sources instead.
- •Do NOT hand-edit
generated/— re-runpac code add-data-sourceto regenerate. - •Use the
@import alias — maps to./srcvia Vite config (e.g.,import { Button } from "@/components/ui/button"). - •Use
@microsoft/power-apps-vite— required Vite plugin, already configured in the starter template.
Project Structure
For the complete project layout and technology stack, see references/project-structure.md.
TanStack Query Pattern
Wrap data fetching in TanStack Query for caching and state management:
import { useQuery, useMutation, useQueryClient } from "@tanstack/react-query"
import { AccountsService } from "./generated/services/AccountsService"
function useAccounts() {
return useQuery({
queryKey: ["accounts"],
queryFn: () => AccountsService.getAll({ top: 100 }),
})
}
function useCreateAccount() {
const queryClient = useQueryClient()
return useMutation({
mutationFn: (account: Omit<Accounts, "accountid">) =>
AccountsService.create(account),
onSuccess: () =>
queryClient.invalidateQueries({ queryKey: ["accounts"] }),
})
}
Limitations
- •No Power Apps mobile/Windows app support
- •No Power Platform Git integration
- •No environment variables for secrets
- •No FetchXML, polymorphic lookups, or Dataverse actions/functions
- •Schema changes require delete + re-add of data source
- •Connections must be created in the Power Apps UI, not via CLI