
Browse the model-driven app threads on the Power Platform Community long enough and a pattern jumps out. Someone asks for a user experience that the standard grid and form cannot deliver, such as a Kanban board, an approver workspace, or a richer record summary, and the accepted answer is some version of “build a custom page” or “write a PCF control.” Both answers are correct. Both also assume the maker has canvas skills, front-end skills, or budget for a developer.
Generative pages change that answer. Microsoft describes them as an AI-driven experience where you describe the page you need in natural language, point the app agent at your Dataverse tables, and receive a working React page inside your model-driven app. This article takes two real business questions from the community forums and walks through how you would solve each one with a generative page, including the prompts, the data model, the governance decisions, and the traps worth avoiding before anything reaches production.
What generative pages are, in one minute
According to the official Microsoft Learn documentation, a generative page is built by an app agent that interprets your prompt and generates React code covering both the front-end experience and the business logic. You can refine the result conversationally, edit the code directly, and publish it as a page in your app. The facts that matter most for planning are these:
- A single page can reference up to six Dataverse tables. Power Platform connectors and Dataverse custom APIs are also supported as data sources, but both are in preview.
- You can attach an image to guide the layout, anything from a napkin sketch to a high-fidelity mockup.
- There are two authoring paths. In-browser authoring at make.powerapps.com is available in the United States, Great Britain, Australia, and Singapore, and currently uses GPT-4.1. Microsoft now recommends AI code generation tools such as GitHub Copilot CLI for a local, code-first workflow that is available worldwide on public clouds and gives access to newer models.
- Generative pages are solution-aware, so they move between environments through standard ALM.
- The maker experience does not require additional AI or message credits, according to the documentation FAQ.
- Microsoft is explicit that the agent makes a best-effort attempt at production-ready code, and that validating security, accessibility, and compliance remains your responsibility.

When you select Generate page, you can watch the agent work through four visible stages: thought streaming, where it lists requirements, assumptions, and an execution plan; code generation; transpilation; and final rendering. Read the thought streaming output carefully. It is the fastest way to catch a misunderstood requirement before you spend iterations fixing code.
Scenario 1: “Can I have a Kanban view of my model-driven tables?”
The community question
In the Power Platform Community thread How to make Kanban board in model-driven app?, a maker asked whether a Kanban view with drag and drop was possible over model-driven tables, noting they already knew how to do it in a canvas app. The accepted answer was that out-of-the-box model-driven apps cannot do this, and that a custom page with canvas-style controls and Power Fx was the way forward.
That answer was right at the time. Today there is a third option that requires neither canvas skills nor a PCF project.
The business context
Picture the facilities team at Contoso. They track maintenance work orders across several sites in a model-driven app. Dispatchers live in the Active Work Orders view, sorting and filtering a grid all day, and they have told you repeatedly that they cannot see the flow of work. They want to see what is new, what is scheduled, what is stuck, and move items forward without opening each record.
The data model
Before prompting, confirm that every column you intend to show uses a supported data type. Generative pages currently support Choice, Currency, Customer, Date and Time, Date Only, Decimal Number, Floating Point Number, Image, Lookup, Multiline Text, Status, Status Reason, Text, Whole Number, Yes/No, and Unique Identifier. This design stays inside that list.
| Table | Key columns | Data types |
|---|---|---|
| Work Order | Title, Status Reason, Priority, Scheduled Date, Estimated Hours | Text, Status Reason, Choice, Date Only, Decimal Number |
| Work Order (lookups) | Asset, Site, Assigned Technician | Lookup |
| Asset | Name, Asset Tag, Asset Photo | Text, Text, Image |
| Site | Name, Region | Text, Choice |
| User | Full Name | Text (system table) |
One design decision deserves attention before the prompt. The Kanban columns map to Status Reason values: New, Scheduled, In Progress, On Hold, and Completed. If Completed belongs to the Inactive state in your table, moving a card into that column is a state change, not just a status reason change. Decide now whether Completed stays an active status reason or whether you want the page to set both the state and the status reason together, and say so explicitly in the prompt. If you have configured status reason transitions, test that the page respects them.

The prompt
In the app designer, select Add page, then Generative page, then Describe a page. Add the Work Order, Asset, Site, and User tables through Add data, then Add table. A strong prompt states the layout, the data, the interaction, the failure behavior, and the accessibility expectation in plain terms:
Build a Kanban board page for maintenance work orders using the Work Order table.Show one column per Status Reason value in this order: New, Scheduled, In Progress, On Hold, Completed.Show the number of cards in each column header.Each card shows the work order Title, the Asset name, the Site name, the Assigned Technician, the Scheduled Date, and a priority badge (High in amber, Medium in blue, Low in grey).Users can drag a card to another column to update its Status Reason.Show a confirmation message after the save succeeds. If the save fails, move the card back to its original column and show the error.Every card must also have a keyboard-accessible "Move to" menu that performs the same update without drag and drop.Add filters at the top for Site and Assigned Technician, plus a toggle for "Only my work orders".Load active work orders plus work orders completed in the last 30 days.Selecting a card title opens the Work Order form.Let each column scroll independently. Use a clean, modern look consistent with model-driven apps.
Two lines in that prompt do most of the governance work. The failure behavior line prevents a board that silently shows a card in the wrong column when a save is rejected by security or a plug-in. The keyboard-accessible Move to menu matters because drag and drop on its own excludes keyboard and many assistive technology users. Asking for the alternative up front is cheaper than retrofitting it after the Accessibility assistant flags the issue.
Iterating toward something dispatchers will actually use
Expect the first generation to be close but not finished. Typical follow-up prompts for this scenario look like the following:
- “Highlight cards in amber when the Scheduled Date is in the past and the Status Reason is not Completed.”
- “Collapse the Completed column by default and let users expand it.”
- “Show the Asset Photo as a small thumbnail on each card when one exists.”
- “When Only my work orders is on, filter by the signed-in user as Assigned Technician.”
After each iteration, use Compare on the Code tab to see what changed, and check the Accessibility assistant at the bottom of the screen. If it reports violations, Auto fix passes them straight back to the agent. You can also attach a screenshot of the current preview with your next message, which is often faster than describing a visual problem in words.
What to verify before you publish
Microsoft notes that plug-ins registered on create, update, or delete already run when a generative page performs the corresponding data operation. That is good news for this scenario: any existing plug-in or flow that fires when a work order status changes, such as a technician notification, keeps working with no extra wiring. It also means a card move carries every consequence of a status change, so test it with the same rigor as a form save.
Test with a least-privileged dispatcher role, not your System Administrator account. A separate community thread about users not seeing custom page buttons without the admin role is a useful reminder that page experiences often behave differently once real security roles and app sharing are in play. Confirm that a dispatcher who cannot update a work order sees the save fail gracefully, and confirm that auditing captures the status change.
Scenario 2: “How do users submit a record for approval in a model-driven app?”
The community question
In the community thread Send record for approval, a maker asked how to add a command bar button so users could submit records for approval. The suggested approaches were a modern command button that sets the status to awaiting approval and triggers a flow with an adaptive card or in-app notification, or, more simply, a Yes/No approval column protected by column security so only approvers can set it.
Those patterns work well for the submit step. Where they get thin is the approver experience. Approvers bounce between an email, a Teams card, and the record, with no single place to see what is waiting, what is urgent, and the full context of each request. That is the gap a generative page fills.
The business context
Contoso’s finance operations team runs purchase requests through a model-driven app. Requesters submit, a named approver decides, and every decision needs an auditable history. Approvers want two things: a queue showing everything waiting on them, and a clean decision panel on the request itself.
| Table | Key columns | Data types |
|---|---|---|
| Purchase Request | Title, Amount, Status Reason (Draft, Submitted, Approved, Rejected), Urgency, Needed By, Justification | Text, Currency, Status Reason, Choice, Date Only, Multiline Text |
| Purchase Request (lookups) | Cost Centre, Requested By, Approver | Lookup |
| Approval History | Purchase Request, Decision, Comment, Decided By, Decided On | Lookup, Choice, Multiline Text, Lookup, Date and Time |
| Cost Centre | Name, Budget Owner | Text, Lookup |
The key design choice: who enforces the decision?
It is tempting to let the page simply update the Status Reason to Approved when the approver clicks a button. Resist that. Anything enforced only in the user interface can be bypassed by anyone with update rights on the table. The rules that matter here, such as whether the signed-in user is the named approver, whether the request is still in the Submitted state, and whether the amount is within the approver’s limit, belong on the server.
Generative pages support exactly this pattern through Dataverse custom APIs, currently in preview. Microsoft’s documentation describes using a custom API when a page needs to explicitly run server-side business logic such as approving an order, and notes that custom APIs run in the context of the signed-in user and are subject to Dataverse security. For this scenario, register a table-bound action named DecidePurchaseRequest on the Purchase Request table, backed by a plug-in:
- Request parameters: Decision (String) and Comment (String).
- Response property: NewStatus (String).
- Plug-in logic: confirm the caller is the Approver on the record, confirm the Status Reason is Submitted, check the amount against the approver’s limit, set the new Status Reason, and create an Approval History row.
Keep the parameter types simple. The documentation lists custom APIs that use the EntityCollection binding type or Entity parameters as unsupported for generative pages, so design your contract around strings, numbers, and the bound record.

Page A: the Approver Queue
Create the first page as a full-page generative page in the app navigation. Add the Purchase Request, Cost Centre, and User tables, then prompt:
Build an Approver Queue page using the Purchase Request, Cost Centre, and User tables.Show Purchase Requests where the Approver is the signed-in user and the Status Reason is Submitted.At the top, show three summary tiles: number of pending requests, total pending Amount, and number of requests whose Needed By date is within the next 3 days.Below the tiles, group the requests by Urgency (High first), sorted by Needed By ascending.Each row shows Title, Requested By, Cost Centre, Amount, and Needed By.Format currency and dates using the signed-in user's Dataverse settings, not hardcoded formats.Selecting a row opens the Purchase Request form.Show a friendly empty state when nothing is waiting.
The formatting instruction borrows from Microsoft’s localization guidance, which recommends formatting dates, numbers, and currency from each user’s Dataverse settings. It costs one sentence and prevents a class of bugs for approvers in other regions.
Page B: the embedded Decision Panel
The second page lives on the Purchase Request form. Generative pages can accept the input parameters recordId, entityName, and data, and when a page is embedded on a form, the form passes the current record ID automatically. Add the Purchase Request and Approval History tables, then select Add, then Custom API, and choose DecidePurchaseRequest. Prompt:
Set up the page to accept a Purchase Request recordId. When the page loads, fetch that Purchase Request.Show Title, Amount, Cost Centre, Requested By, Needed By, and Justification in a compact summary card.Below it, list the related Approval History rows, newest first, showing Decision, Comment, Decided By, and Decided On.Show a multiline Reviewer comment field and two buttons: Approve and Reject. Reject requires a comment.When the user selects either button, call the DecidePurchaseRequest custom API for the current record.Pass Decision as "Approved" or "Rejected" and pass the Reviewer comment text.Disable both buttons while the call is running.Display the returned NewStatus in a success message and refresh the Approval History list.If the call fails, show the error message returned by the server.If the Status Reason is not Submitted, hide the buttons and show a read-only message.
Notice that hiding the buttons is a courtesy, not a control. The plug-in behind the custom API still rejects a decision from the wrong user or on the wrong status, no matter what the page shows.
After publishing Page B, embed it on the form. Open the form designer, select Components, expand Display, select Generative page, choose the Decision Panel, then save and publish the form. You do not need to configure a static recordId, because the form supplies it.
Optional: open the panel from the command bar
Some teams prefer the decision panel in a side dialog rather than on the form body. Microsoft’s client API examples for generative pages show how to open a page with Xrm.Navigation.navigateTo using the generative page type. A command bar button calling a small JavaScript function like this one passes the current record:
function openDecisionPanel(primaryControl) { var recordId = primaryControl.data.entity.getId().replace(/[{}]/g, ""); var pageInput = { pageType: "generative", pageId: "REPLACE-WITH-DECISION-PANEL-PAGE-GUID", entityName: "cr_purchaserequest", recordId: recordId }; var navigationOptions = { target: 2, position: 2, width: { value: 520, unit: "px" }, title: "Purchase request decision" }; Xrm.Navigation.navigateTo(pageInput, navigationOptions).then( function () { primaryControl.data.refresh(false); }, function (error) { console.error(error.message); } );}
Find the page GUID in the app designer by selecting the generative page and copying the value in the Generative page field of the properties pane. One caution from the same documentation: opening a generative page in a side pane with Xrm.App.sidePanes is not currently supported, so use a centered or side dialog instead.
Governance notes that apply to both scenarios
Region availability is still a real constraint
A community thread from a maker in a Canadian environment captures a common frustration: every AI feature enabled, and still no generative pages. In-browser authoring is limited to environments in the United States, Great Britain, Australia, and Singapore. If your production environments sit elsewhere, the AI code generation tools path is available worldwide on public clouds and is Microsoft’s recommended approach. Note also that Microsoft’s separate generative pages FAQ, last updated earlier in 2026, still describes a US-only, Dataverse-only scope, while the main article describes four regions plus connectors and custom APIs in preview. Treat the main article as current and verify before you commit a regional rollout plan.
Keep your prompts in source control
Generative pages travel in solutions as UX Agent Project rows, but when a page is imported into another environment, only the first prompt and the published code come with it. The full agent conversation stays behind. Your iteration history is design documentation, so capture the prompts that shaped each page in your repository or wiki alongside the solution. If you created pages during the preview period, open each one in the designer to trigger the one-time migration to the solution-aware data model before you try to export.
One maker at a time
Collaboration is not supported. If two makers edit the same page, expect conflicts. Assign a named owner per page in the same way you would assign ownership of a PCF control.
Preview features stay out of production
Scenario 1 uses only Dataverse tables. Scenario 2 depends on custom API support, which is in preview, as is connector support. Microsoft states that preview features are not meant for production use. Build and prove Scenario 2 in a sandbox now, and keep a fallback such as the command button and flow pattern from the original community thread until custom API support reaches general availability.
Know the remaining limits
- Prompts can be up to 50,000 characters, and in-browser prompting supports US English only.
- Column types outside the supported list will not work on a page. Review your tables before you promise a design to stakeholders.
- The sitemap entry for a generative page is not localized by default, so handle that separately in the app designer if your app is multilingual.
- Generative pages are available in model-driven apps only, not canvas apps.
Choosing between generative pages, custom pages, and PCF
| Option | Best fit | Watch out for |
|---|---|---|
| Generative page | Rich, data-centric pages over Dataverse built quickly by makers, such as boards, queues, dashboards, and record panels | Region limits for in-browser authoring, six tables per page, preview status of connectors and custom APIs, code review responsibility |
| Custom page | Teams already fluent in canvas apps and Power Fx who want low-code control over every element | Canvas performance tuning and a separate skill set from model-driven configuration |
| PCF code component | A reusable control that must behave identically across many forms, views, or apps | Requires professional developers and a build and release pipeline |
These options are not mutually exclusive. A generative page is often the fastest way to validate a user experience with the business. If the page later needs to become a governed, reusable component, you already have working React code and a clear specification to hand to a developer.
Pre-publication checklist
- Every column on the page uses a supported data type.
- The page has been tested with least-privileged security roles, not only as an administrator.
- Failure paths are visible to users: rejected saves, failed custom API calls, and empty states.
- Every drag and drop interaction has a keyboard-accessible alternative, and the Accessibility assistant shows no open violations.
- Server-side rules live in plug-ins or custom APIs, not only in page code.
- The generated code has been reviewed against your organization’s standards.
- The prompts behind the page are stored with your solution documentation.
- Any preview dependency is flagged in your release notes and kept out of production.
- The app, including its sitemap, is in a solution and the export requests the UX Agent Project rows.
The takeaway
Both community questions in this article were answered correctly at the time with “build a custom page.” Generative pages add a new answer: describe the experience clearly, keep the rules on the server, and treat the generated code with the same review discipline as anything else you ship. The makers who get the most from this feature will not be the ones who write the cleverest prompts. They will be the ones who bring a clean data model, a clear security design, and a release process that expects AI-generated code to be reviewed.
Have a question about generative pages? Reach out
Trying one of these scenarios in your own tenant, or stuck on a prompt that will not behave? We would like to hear about it. Send us your question with a short description of your tables and what you are trying to build, and we will help where we can. The most useful questions may become follow-up articles, with your permission and without identifying details.
- Use the contact form on this site to send a question directly.
- Leave a comment below so other readers can benefit from the answer.
- Connect with Manoj Annavajjala on LinkedIn and send a message.
Sources
- Microsoft Learn: Generate a page using natural language
- Microsoft Learn: Create and edit generative pages with AI code generation tools
- Microsoft Learn: Navigate to and from a generative page using client API
- Microsoft Learn: FAQ about generative pages in model-driven apps
- Microsoft Learn: Create and use custom APIs
- Microsoft Intelligent Apps Catalog (prompt templates)