Skip to content
duarteclemente
Go back

Real React Apps That Run Inside Dataverse

Ask most people what “building on Power Platform” looks like and they’ll describe a canvas app: drag a gallery onto a screen, bind it to a data source, write a bit of Power Fx, ship. That’s a real and useful tool. It is not the only one. For a professional-services firm I built a fleet of full React apps — TypeScript, Fluent UI, real component architecture — running natively on the platform against Dataverse. No separate hosting, no bespoke API, no hand-rolled auth. A lot of Power Platform developers don’t realise this is on the menu.

This is a short field note on how that actually fits together, because the interesting part isn’t “React runs here.” It’s the seam between your code and Dataverse.

Table of contents

Open Table of contents

Canvas apps aren’t the ceiling

Power Apps Code Apps let you take an ordinary React/Vite project and push it onto the platform, where it’s wrapped with Entra ID authentication, DLP and conditional-access policy, and a runtime host — and from your own code you can call the same connectors a canvas app would. You write the app you’d write anywhere; the platform governs and hosts it.

That means the things a canvas app makes genuinely hard — complex client state, a real component library, custom rendering, unit-tested logic — stop being hard, because you’re in React, not in a formula bar. What you give up is the “citizen developer drops controls on a screen” simplicity. For an app with real interaction, that’s a trade worth making.

The read/write split

Here’s the part that matters, and the part that isn’t obvious from the docs. Reads and writes go through different doors.

Reads go through the Code Apps SDK. You get proper OData queries — $select, $filter, $expand — typed, paginated, against your Dataverse tables. This is the well-lit path, and it behaves.

Writes drop down to the Dataverse Web API on the host page, and the detail that trips people up is lookups. You don’t set a lookup by stuffing a GUID into a column; you bind it by navigation property with @odata.bind:

"ts_staffid@odata.bind": "/staffs(<id>)"

Set a lookup the naive way and Dataverse rejects it. Bind it by navigation property and it’s clean. Once that clicks, the pattern is: read through the SDK, write through the Web API, and let Dataverse stay the system of record while the platform owns the token acquisition. You never write an auth line.

What the pattern bought

Abstract patterns are boring without the things they let you build, so — three that a canvas app would have fought me on:

The quiet win underneath all three: I templatized the read/write plumbing once, so every new page started from the same proven pattern instead of rediscovering the @odata.bind gotcha from scratch. The first page is where you pay the platform-learning tax. Every page after is just React.

When to reach for this

Code Apps aren’t a canvas-app replacement; they’re the tool for when the interaction outgrows the formula bar. If your app is a form over a table, stay in canvas — it’s faster and lighter. If it’s a genuine application — client state, custom rendering, logic you want to unit-test — then a Code App gives you a modern front end without giving up Dataverse as your backend or writing a line of authentication code.

If you’ve been assuming “Power Platform” caps you at canvas apps, it doesn’t. It just moves the hard part from “how do I make this control behave” to “how does my code talk to Dataverse” — and that part, once you’ve drawn the read/write seam, is genuinely pleasant.


Slides: I pulled the core of this into a short deck — download the PDF.

Have you shipped a Code App yet, or is canvas still doing everything you need?


Share this post:

Next Post
I deleted the server that merged my PDFs