Use Claude Code to Vibe Code an Entire Power App
If you have ever asked an AI coding assistant to build a Power Platform solution, you have probably hit the same wall: it imports cleanly, or it does not, and the error messages Dataverse gives you rarely point at the real cause. Below are the two prompts I use with Claude Code to build a SharePoint-backed Power Apps booking system from scratch, an unmanaged solution for booking shared workspaces and company vehicles, plus the companion PowerShell script that sets up the SharePoint lists it runs on.
Both prompts already include the schema details that caused real import failures the first time around, written in at the exact point each one applies, so a fresh build starts already knowing where the first attempt broke.
What these prompts build
Together they produce a complete, working system with no manual schema editing required:
- An unmanaged Power Apps solution, so the whole app stays editable in Power Apps Studio after import, not locked behind a managed layer.
- A canvas app with five screens for booking desks, rooms, and company vehicles, backed entirely by SharePoint lists, no Dataverse tables and no premium connectors required.
- A PnP.PowerShell script that creates the three SharePoint lists the app needs, with the exact columns the app's formulas expect, safe to run more than once against the same site.
Prompt 1: Build the Power Apps solution
Paste this into Claude Code (or any coding agent with file and terminal access) to generate the solution package.
The request
Build a Power Apps unmanaged solution package (a .zip I can import via make.powerapps.com, Solutions, Import) for a team booking system that lets employees book shared workspaces (desks/rooms) and company vehicles.
Data and connectors
- Data source: SharePoint only. No Dataverse tables, no premium connectors (standard SharePoint connector only). User() is a built in Power Fx function, not a connector, and is fine to use.
- Package as unmanaged, so my team can keep editing it in Power Apps Studio after import.
- Include an environment variable for the SharePoint site URL so I can point the app at the right site during import.
Solution package schema
- A SharePoint connection reference is declared inline inside Customizations.xml under a connectionreferences element (a full connectionreference record). It is not a RootComponent. RootComponent type="372" specifically means a Connector (a custom connector); do not use it for a connection reference, and do not add a RootComponent entry for the connection reference at all.
- Customizations.xml must include explicit container elements, CanvasApps, Connectors, connectionreferences, in the correct position in the element order, even when empty. Omitting them produces a generic, unhelpful Dataverse import error ("the specified node cannot be inserted as the valid child of this node, because the specified node is the wrong type") that does not point at the real cause, so get the skeleton right before filling in content.
- environmentvariabledefinition.xml schema: root element environmentvariabledefinition with schemaname as an XML attribute, not a child element; display name wrapped as displayname with a nested label element carrying the description and languagecode="1033" (not plain text); and type 100000000 for a Text variable (not 0).
- A canvas app inside a solution needs exactly three pieces, and all three must exist or the packer errors: CanvasApps/<name>.meta.xml (the CanvasApp metadata record), CanvasApps/<name>_DocumentUri.msapp (the app itself, renamed with this suffix), and CanvasApps/<name>_BackgroundImageUri (a real file, even a 1x1 placeholder PNG is fine, not just a reference marked xsi:nil).
Canvas app YAML: control choices and formula syntax to use from the start
- Use ModernTextInput@1.0.0 and ModernDatePicker@1.0.0, not bare or unqualified TextInput or DatePicker. The unqualified versions resolve to a stripped down template missing common properties (Default, HintText, Format, DefaultDate). ModernTextInput uses Placeholder instead of HintText and has no Format property (parse numbers with Value() in formulas instead); ModernDatePicker does support DefaultDate.
- CheckBox uses Label and Checked as its property names, not Text and Default.
- The default (bare) Button only supports a limited property set. It does not support Size, Fill, or Color. Either use only supported properties, or convey state through text content instead of styling.
- SharePoint Choice columns (for example a status or resource type field) are read and written in Power Fx as {Value: "ChoiceText"}. Build every formula that touches a Choice column around that shape from the start, not as a later fix.
- Any single line (plain scalar) formula containing a literal colon followed by a space, such as {IsActive: true} or the string "Selected: ", breaks YAML parsing (YamlInvalidSyntax: found invalid mapping). Wrap such formulas in single quotes, or write them as a block scalar, rather than as a bare plain scalar.
Build and validation approach
- Build and validate everything using the real Power Platform CLI (pac) rather than hand authoring the solution or canvas app formats from memory. Install it locally if needed (.NET SDK via the non admin dot.net/v1/dotnet-install.sh script plus dotnet tool install --global Microsoft.PowerApps.CLI.Tool), and use pac canvas pack/unpack and pac solution pack/unpack to round trip everything before delivering it.
- Cross check Customizations.xml and Solution.xml structure against a real, working Microsoft solution that also has a canvas app, a connection reference, and an environment variable, for example microsoft/coe-starter-kit's ALMAcceleratorSampleSolution on GitHub, rather than guessing the schema.
- Treat the pack and unpack round trip as necessary but not sufficient. It only proves the package is structurally well formed, not that every control property name is valid. Those errors only surface when Power Apps Studio actually compiles the YAML on first open. Budget for at least one more round of property name fixes after the first real import, and treat Studio's exact error text as ground truth over any documentation guess, including this one.
- Goal: bug free, imports successfully on the first try. But say so explicitly if a particular constraint above could not be verified without a live environment, rather than presenting an untested guess as confirmed.
Prompt 2: Set up the SharePoint lists
This second prompt produces a standalone PowerShell script. Run it once against your SharePoint site before or after importing the solution above.
The request Write a PnP.PowerShell script that provisions the three SharePoint lists the Booking System Power App needs (Workspaces, Vehicles, Bookings), with their exact columns, at a site URL I pass in as a parameter. It needs to be safe to run more than once against the same site without creating duplicates or erroring on things that already exist, since I will run it again any time I add a new environment or re-run it after a partial failure. List schema (match this exactly, the app's formulas already assume these internal names and types) - Workspaces: Title (built in), Location (Text), Capacity (Number), IsActive (Boolean). - Vehicles: Title (built in), LicensePlate (Text), Seats (Number), IsActive (Boolean). - Bookings: ResourceType (Choice: Workspace, Vehicle, required), ResourceId (Number, required), ResourceName (Text), StartDateTime (DateTime, required), EndDateTime (DateTime, required), BookedByEmail (Text), BookedByName (Text), Status (Choice: Confirmed, Cancelled, required). Authentication, handle this from the start, not as a later fix - Since September 2024 Microsoft retired the old shared "PnP Management Shell" Entra ID app that PnP.PowerShell used to sign in with by default, for every tenant, with no replacement default. The script needs its own Entra ID app registration to connect, there is no working shared ClientId it can fall back to anymore. - Take an optional -ClientId parameter. If it is supplied, connect with it directly. If it is not supplied, register a one time Entra ID app automatically via Register-PnPEntraIDAppForInteractiveLogin, print the resulting Client ID clearly, and tell the user to pass -ClientId on future runs to skip re-registering. Note in the script's help text that registering an app requires Application Developer or Global Administrator rights in the tenant. - The app registration cmdlet's return object does not have a guaranteed property name for the Client ID across PnP.PowerShell versions. Check ClientId, then AppId, then ApplicationId, then AzureAppId, then AADAppId in that order, and if none of those are populated, fall back to scanning every property on the returned object for a value that matches a GUID shape and use the first match. If nothing matches, print the full object so the user can find the value themselves, tell them to re-run with -ClientId followed by that value, and exit with a non zero code rather than continuing with a blank ClientId. - Take an optional -Tenant parameter (the tenant's onmicrosoft.com domain), used only when auto registering the app. Default it to a guess derived from the SiteUrl's subdomain (contoso.sharepoint.com becomes contoso.onmicrosoft.com), and document clearly that this guess can be wrong and the user should override it with -Tenant if their onmicrosoft.com domain differs from their SharePoint hostname. - Take an optional -DeviceLogin switch that applies to both the app registration step and the site connection step, using device code sign in instead of the interactive browser redirect flow. Document that this exists specifically because the browser redirect flow commonly hangs or errors behind VPNs, behind corporate firewalls, or when multiple Microsoft accounts are already signed into the browser, and that device login is the fix when that happens. - If the PnP.PowerShell module is not installed, install it automatically for the current user (CurrentUser scope, Force, AllowClobber) rather than erroring and telling the user to install it themselves first. Idempotency and seed data - Before creating each list, check whether it already exists (Get-PnPList) and skip creation if it does, only setting the description on first creation. Same pattern for every column (Get-PnPField): check first, skip if it exists, only add if it is missing. Wrap this list and field creation logic in small reusable helper functions rather than repeating the check in line for every single list and column. - After the Workspaces and Vehicles lists are confirmed to exist, check whether each one is currently empty and only then insert one sample record (a sample desk, a sample vehicle), so the app has something to display the first time someone opens it, but re running the script never adds a second sample record on top of real data. Do not seed the Bookings list; it should start empty. - Set the error action preference to Stop at the top so a real failure actually halts the script instead of continuing silently past it. Script behavior and output - Take -SiteUrl as the only mandatory parameter, matching the format the user will also enter as the Power Platform environment variable when they import the solution, and say so in the parameter's help text. - Print clear, color coded progress as it runs (what is being created, what is being skipped because it already exists), not just silent success or a wall of default PnP.PowerShell output. - End with an explicit what to do next message: import the solution zip, set the SharePoint Site URL environment variable to this same site, open the app in Studio, and add these three lists as data sources. Someone should be able to run this script, read the last few lines, and know exactly what to do next without opening a README. - Disconnect the PnP session at the end rather than leaving it open. - Write full comment based help (Synopsis, Description, a Parameter entry for each parameter, and Example entries for the plain case, the DeviceLogin case, and the ClientId case) so Get-Help with the Full switch is actually useful, since this will be run by people who are not necessarily familiar with PnP.PowerShell or Entra ID app registration.
Frequently asked questions
- Do I need Dataverse for this to work?
- No. Both prompts are written specifically to avoid Dataverse and any premium connector. The app runs on the standard SharePoint connector only, so it works on a standard Microsoft 365 license.
- Which order do I run these in?
- Either order works. Run the PowerShell script to create the SharePoint lists, and import the solution package, in whichever order is convenient, then open the app in Power Apps Studio and add the three lists as data sources once both exist.
- Why does the PowerShell script need its own Entra ID app registration?
- Microsoft retired the shared default app that PnP.PowerShell used to rely on for every tenant. Since then, PnP.PowerShell needs its own Entra ID app registration to sign in. The script handles this automatically on first run if you do not supply one yourself.
- Can I reuse this with a different coding agent, not Claude Code?
- Yes. Nothing in either prompt is specific to one tool. Any AI coding assistant with file and terminal access can follow the same instructions, though the build and validation steps assume access to the Power Platform CLI.