<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: david wyatt</title>
    <description>The latest articles on DEV Community by david wyatt (@wyattdave).</description>
    <link>https://dev.to/wyattdave</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F653003%2Ff6da9df7-019e-4189-ab7f-c5c527fe1db6.png</url>
      <title>DEV Community: david wyatt</title>
      <link>https://dev.to/wyattdave</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/wyattdave"/>
    <language>en</language>
    <item>
      <title>How to Create Your Own AI Coding Agent</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 06 Apr 2026 06:10:11 +0000</pubDate>
      <link>https://dev.to/wyattdave/how-to-create-your-own-ai-coding-agent-2h1o</link>
      <guid>https://dev.to/wyattdave/how-to-create-your-own-ai-coding-agent-2h1o</guid>
      <description>&lt;p&gt;Nearly all developers are taking advantage of AI coding tools, but what happens when you have a particular niche, where not only do LLM's have less knowledgeable, but potentially their knowledge is based on the general, which is straight up wrong for your niche.&lt;/p&gt;

&lt;p&gt;This is what I found when making Power Platform Code Apps. Code Apps are full React apps that are hosted in the Power Platform. For that reason they have a specific SDK kit and cli commands. Models like Opus 4.6 do a good job considering how niche it is, but imagine when you then build someone bespoke on top of that niche. That's what I did, as I don't use React I wanted a vanilla JavaScript build (before you comment yes I know I should use React and Typescript, but remember I'm a little strange). This meant there was simply no training or even docs on it. And because it was using vanilla JavaScript, all of the training data actually kept sending the LLM down the wrong path. So at this point I wanted to create my own coding agent.&lt;/p&gt;




&lt;p&gt;In general there are 3 ways to get a more bespoke model&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Build your own&lt;/li&gt;
&lt;li&gt;Fine‑tune or distil an existing model (optionally with reinforcement learning)&lt;/li&gt;
&lt;li&gt;Prompt&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You can imagine the path I chose, yep the easy one.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prompt Overview&lt;/li&gt;
&lt;li&gt;Platform&lt;/li&gt;
&lt;li&gt;Implementation&lt;/li&gt;
&lt;li&gt;Learnings&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Prompt Overview
&lt;/h2&gt;

&lt;p&gt;If you already know this feel free to skip, but I wanted to give a quick overview of the full prompt stack.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh9c5v3x16cnlc65u5tr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxh9c5v3x16cnlc65u5tr.png" alt="prompt stack" width="385" height="363"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are many levels to a prompt, each higher and more important, you have:&lt;/p&gt;

&lt;h3&gt;
  
  
  Model System Prompt
&lt;/h3&gt;

&lt;p&gt;This is the highest level, often added by the model owner, it is for things like security and legality. It will cover things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Not to share how to do illegal actions&lt;/li&gt;
&lt;li&gt;Not to encourage harmful actions&lt;/li&gt;
&lt;li&gt;Not to share confidential information about the model
&lt;em&gt;Not an exhaustive list&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Application System Prompt
&lt;/h3&gt;

&lt;p&gt;Next level down, and this will be what the application you use adds. This covers specific tools the application provides, and pattern/mechanisms the app designer found to improve performance. Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;This Tool reads the local folder&lt;/li&gt;
&lt;li&gt;This Resource provides information about x&lt;/li&gt;
&lt;li&gt;When dealing with cli ensure that authentication is validated first
&lt;em&gt;Theoretical examples, as these are closely kept secrets&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Instruction.md
&lt;/h3&gt;

&lt;p&gt;Instruction files are project specific instructions, these generally cover things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Naming conventions&lt;/li&gt;
&lt;li&gt;Folder structure&lt;/li&gt;
&lt;li&gt;Design principles&lt;/li&gt;
&lt;li&gt;What Skills you want to be used when&lt;/li&gt;
&lt;li&gt;Any learnings the LLM has made (you can set the agent to update the file itself)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This helps ensure the project is consistent and easier to read/maintain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Skill.md
&lt;/h3&gt;

&lt;p&gt;These kind of blur the line between prompt and context. They are specific instructions/knowledge sources for specific situations. By moving them out of the instruction the LLM decides when to add it in (kind of like a dynamic context/instruction). Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md" rel="noopener noreferrer"&gt;Frontend-design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anthropics/skills/blob/main/skills/pptx/SKILL.md" rel="noopener noreferrer"&gt;Working-With-PowerPoint-Files&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/anthropics/skills/blob/main/skills/canvas-design/SKILL.md" rel="noopener noreferrer"&gt;Canvas-design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/wyattdave/Power-Automate-Utility/blob/main/extension/src/skill.md" rel="noopener noreferrer"&gt;Power-Automate-expressions&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Instructions and Skills where created by Anthropic and designed for Claude Code, but other tools and models can use them to, just with less consistent or hierarchy results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Your Prompt
&lt;/h3&gt;

&lt;p&gt;And finally we have your prompt that you send, with any additional context.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Platform
&lt;/h2&gt;

&lt;p&gt;There are a few ways I could approach this, but the ones I considered the most were:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CLI Wrapper&lt;/li&gt;
&lt;li&gt;VS Code Extension&lt;/li&gt;
&lt;li&gt;GitHub Copilot Extensions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I use GitHub Copilot so you can see why my choices are what they are, and with my experience being in VS Code Extensions, and the fact I like to hybrid write code with the agent, it made sense for me to build there, though one day I want to try a CLI wrapper.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Call out here, you will see later that you can get most of the functionality with just a well setup workspace, covering instructions and skills, but that's no fun 😎&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Building in VS Code has some killer advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Built in auth to GitHub Copilot&lt;/li&gt;
&lt;li&gt;Built in terminal&lt;/li&gt;
&lt;li&gt;Can have custom UI&lt;/li&gt;
&lt;li&gt;Expand beyond text with buttons etc&lt;/li&gt;
&lt;li&gt;No hosting/backend&lt;/li&gt;
&lt;li&gt;Distributed for free in VS Code market&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So once decided on platform the next step is the build.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Implementation
&lt;/h2&gt;

&lt;p&gt;My AI Coding Agent was going to have 3 main advantages over simple GitHub Copilot&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simplified UI based CLI commands&lt;/li&gt;
&lt;li&gt;System Prompt - built specifically to ensure the LLM didn't use its JavaScript training to go off plan&lt;/li&gt;
&lt;li&gt;Skill files - all of the learnings from implementing CodeApp JS&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Simplified UI based CLI commands&lt;/strong&gt;&lt;br&gt;
For Code Apps to work they require the Power Platform CLI, this gives the ability to authenticate, create connections, and deploy to the Power Platform environment. So to make things more LowCode and easier I want to abstract away those commands and make it more integrated.&lt;/p&gt;

&lt;p&gt;For this I built a kind of pipeline based on button presses, these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Setup the CodeApp JS files&lt;/li&gt;
&lt;li&gt;Authenticated with tenant&lt;/li&gt;
&lt;li&gt;Listed and selected environment (updating config files too)&lt;/li&gt;
&lt;li&gt;Created connections based on what code was written&lt;/li&gt;
&lt;li&gt;Deployed app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;System Prompt and Skill.md&lt;/strong&gt;&lt;br&gt;
This were most of the value codes from, I've banded them together because they are created in the same way, with the only difference being system prompt is always used and skills specific to the task.&lt;/p&gt;

&lt;p&gt;To create the right prompts and skills I kind of trained the model, and by that I mean I built lots of apps. During the process I made sure I read the reasoning, and every time there was a bug, built the resolution into the files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8t4y43637nzox338tbyj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8t4y43637nzox338tbyj.png" alt="learning cycle" width="651" height="571"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Looking at my GitHub Copilot usage can you guess the days I was testing/learning 😎&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foioxncavalpehnwcou9s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foioxncavalpehnwcou9s.png" alt="usage" width="800" height="457"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's time consuming, boring, and expensive, but by working this way the idea is to only make the mistake once.&lt;/p&gt;

&lt;p&gt;And that's the real secret sauce, all I'm doing is learning from experience and then documenting it so that the agent knows what to do and what not to do. &lt;/p&gt;

&lt;p&gt;I think this process of training/learning is key to all AI development, including Copilot Studio. You need to test, test, test, test, with each test generating a nudge/tweak to your instruction/prompt. This iterative approach improves results and consistency from your LLM's.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Learnings
&lt;/h2&gt;

&lt;p&gt;There are a couple of things that definitely got me, and the biggest was dealing with context/prompt stack. I found when using the agent on my personal Copilot license it worked perfectly, but when I used my work account I would get failures with "No choices", and this was because my work account has lower context limits. This meant I could send less data to the agent, which was not good considering how small the code base is compared to full applications.&lt;/p&gt;

&lt;p&gt;The issue with context limits can be massively impacted by how you build your agent. Incase you didn't know the prompt/context stack is everything you have to send to the LLM. See the LLM has no memory, so you have to send all of the history each time. And with the use of tools you don't actually send one request, but multiple. This can create a huge stack. Below shows this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fuxk6jr1td4yg84wizg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F2fuxk6jr1td4yg84wizg.png" alt="context stack" width="754" height="2431"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see in the above not only was the all the system prompts etc sent, they were sent 5 times (and this is a simple example). &lt;/p&gt;

&lt;p&gt;But what is worst is the last message to the LLM, the context stack at the end of these back and forth can get big, very big. As you can see the LLM wants to read files, write the code, and it wants to double check/test it by reading again. And that's how you can run out of context even with small projects.&lt;/p&gt;

&lt;p&gt;There are a few ways to fix this (and a few bugs I found in my code).&lt;/p&gt;

&lt;p&gt;The first and most obvious is getting your system prompts, instruction.md, and skill.md content down to the minimum. Make sure they are concise, don't duplicate, and are not too verbose.&lt;/p&gt;

&lt;p&gt;Next is make sure you send only the right data, this is where one of my bugs was, I was sending all of the skill.md files every time. I tried getting the extension to pick the right files by keywords, but this often meant they were missed. In the end I passed a list/description to the LLM and got it to decide which ones it wanted. The other thing to do is use file trees and keep them tight. File trees allow the LLM to know what files are related and only to send the right ones. You can set how wide they are, but the wider equals more text sent.&lt;/p&gt;

&lt;p&gt;The final approach is to deal with the context history. As I said you send all of the previous interactions back each time, but what if you can decrease that. The normal approach is compacting, this is where you ask the LLM to summaries the history and use that instead. It definitely works, but it can mean important context is lossed. The approach I tried was to break up the process and then remove unnecessary information. &lt;br&gt;
I did this by creating a decision log file that is used by the LLM to store a todo list and any key decisions (also useful when returning for new dev session). The LLM then breaks up the project into tasks and completes one by one. When one is complete it updates the todo list and removes all of the tool calls and reasoning, leaving just results.&lt;/p&gt;

&lt;p&gt;As with everything there are trade offs, you don't want to remove to much context, especially if most of your users have higher limits (new models keep pushing the boundary of input/output token limits).&lt;/p&gt;

&lt;p&gt;Another issue I found was the model, it has such a big impact on performance. Using Opus 4.6/GPT5.4 would deliver great result, but dropping to Auto or GPT4.1 would deliver terrible results. There isn't much I can do here but recommend better models on setup, and look at some documentation how to prompt/structure your build better for older models. &lt;/p&gt;

&lt;p&gt;The other issue I got was duplicate CLI installs. My laptop had a old CLI installed directly and a updated version from the Power Platform extension. This would lead the the extension giving the LLM the wrong CLI (the out of date one). This is a niche case, but it does show the risk is in relying on external dependencies like CLI's and VS Code extensions. There isn't much you can do here, but it did drive me to build more into the UI, and getting the LLM to tell the user to use the buttons when it is having issues. The simple truth is code is deterministic, so whenever you can, move the functionality to old fashion code and UI.&lt;/p&gt;



&lt;p&gt;And there you have it, if I can create my own AI Coding Agent, anyone can.&lt;/p&gt;

&lt;p&gt;If you want to try the agent it you can get it for free here &lt;a href="https://marketplace.visualstudio.com/items?itemName=PowerDevBox.codeappjsplus" rel="noopener noreferrer"&gt;https://marketplace.visualstudio.com/items?itemName=PowerDevBox.codeappjsplus&lt;/a&gt;, and if you want to learn more about CodeAppJS or contribute checkout here codeappjs.com &lt;/p&gt;



&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=aicodag" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerapps</category>
      <category>vscode</category>
      <category>coding</category>
      <category>powerplatform</category>
    </item>
    <item>
      <title>Setting Your Environments Up for Code Apps</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 23 Mar 2026 06:41:41 +0000</pubDate>
      <link>https://dev.to/wyattdave/setting-your-environments-up-for-code-apps-16i8</link>
      <guid>https://dev.to/wyattdave/setting-your-environments-up-for-code-apps-16i8</guid>
      <description>&lt;p&gt;Im not going to lie, Code Apps are now my favourite thing about the Power Platform (well maybe not, my heart still belongs to Power Automate, but man its close).&lt;/p&gt;

&lt;p&gt;The reason I love it is because I always wanted to be a ProCode developer, but I never had the time or skill. I could just about build something with vanilla JavaScript, but libraries/frameworks lie Next.js, Vue and Angular, I didn't have the time. And although Code Apps are React based, with a little creativity you can build vanilla JavaScript apps instead (&lt;a href="https://dev.to/wyattdave/power-apps-a-cooler-way-to-use-code-apps-3nb6"&gt;Power Apps - A Cooler Way to use Code Apps&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;Now the truth is they are not right for everyone, and vibe coding them is still a little more painful then fun, but they are definitely cool and something you should be looking at.&lt;/p&gt;

&lt;p&gt;So this blog is all about getting setup to build them, I don't think they are ready for citizen developers, but have potential for professional Power Platform developers.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Environment Setup&lt;/li&gt;
&lt;li&gt;Content Security Policy&lt;/li&gt;
&lt;li&gt;Code Storage&lt;/li&gt;
&lt;li&gt;Code Reviews&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Environment Setup
&lt;/h2&gt;

&lt;p&gt;This one is quick and easy. For once Microsoft did the right thing and left something new as off by default. To turn on Code Apps in an environment goto PPAC, select your chosen environment and select features.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38oho2pfznr6b03jir89.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F38oho2pfznr6b03jir89.png" alt="code app setting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Then with a little scrolling you should see the option to turn it on.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Content Security Policy
&lt;/h2&gt;

&lt;p&gt;This is one you might not know about, but is super important.&lt;br&gt;
The DLP policy is the main way we secure the Power Platform, it's a whitelist for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Connectors&lt;/li&gt;
&lt;li&gt;Custom Connector Urls&lt;/li&gt;
&lt;li&gt;HTTP Action Urls&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and the good news is they work across Code Apps. As Code Apps should use the SDK to create connections just like a Canvas App. &lt;/p&gt;

&lt;p&gt;But as we have said, Code Apps are React apps, which are JavaScript apps. So we can use simple JavaScript to call API's instead of connectors.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
      &lt;span class="s2"&gt;`https://restcountries.com/v3.1/name/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nf"&gt;encodeURIComponent&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;)}&lt;/span&gt;&lt;span class="s2"&gt;?fullText=true`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;signal&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;currentAbort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;signal&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ok&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`HTTP &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;status&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;json&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;renderCountryDetail&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;data&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nf"&gt;showError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`No details found for "&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;name&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;".`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;Example fetch api call&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So how do we stop this, well good news Microsoft has thought of that. And by thought of that I mean use the existing PCF controls that allow you to edit the CPS (Content Policy Security), and guess what by default it is fully locked down (2 for 2 Microsoft, so proud of you).&lt;/p&gt;

&lt;p&gt;The CPS can be found in PPAC environment settings, but instead of features its under Privacy + Security, scroll to bottom right and you will see it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32wlfz1kyh0abid9yoiu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F32wlfz1kyh0abid9yoiu.png" alt="Content Security Policy setting"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are settings for Model Drive, Canvas, and App. We want App as that is for Code App.&lt;/p&gt;

&lt;p&gt;As you can see by default it isn't on, and is blocking everything.&lt;/p&gt;

&lt;p&gt;You can simply turn it off, but I strongly recommend against that even for innovation environments.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyz70z17s2pynpopkyei4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyz70z17s2pynpopkyei4.png" alt="Content Security Policy setting off"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are a lot of settings you can play with:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkhh2avinwxm0h753rb3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ffkhh2avinwxm0h753rb3.png" alt="settings"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the most useful ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use default frame-ancestors - sites where the app can be embedded&lt;/li&gt;
&lt;li&gt;Use default connect-src - this is for those fetch API calls I mentioned&lt;/li&gt;
&lt;li&gt;Use default script-src - use code hosted in a different location&lt;/li&gt;
&lt;li&gt;Use default style-src - use css hosted in a different location&lt;/li&gt;
&lt;li&gt;Use default img-src - use images hosted in a different location&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And the 3 to be really careful with are:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use default frame-ancestors&lt;/strong&gt;&lt;br&gt;
Cam allow any site to pretend to be the app, allowing the users can be clickjacked.&lt;/p&gt;

&lt;p&gt;*&lt;em&gt;Use default connect-src *&lt;/em&gt;&lt;br&gt;
This is your dlp policy, so it exposes data exfiltration.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use default script-src&lt;/strong&gt;&lt;br&gt;
This allows remote code execution, as you are running someone else JavaScript code in your app.&lt;/p&gt;

&lt;p&gt;The image one is less of a risk but one you will probably hit, there are still small risks (data leakage, copyright, etc), so keep a whitelist is still recommended.&lt;/p&gt;

&lt;p&gt;I don't recommend messing with the other settings (I personally would only stick with img-src and a little but with connect-src to start with). &lt;/p&gt;

&lt;p&gt;In a counter intuitive way turning them off doesn't actually turn them off, it just switches to a whitelist, which by default is empty (3 for 3!). So you need to actively add your source.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqhz763hm0huc2mjggkv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fbqhz763hm0huc2mjggkv.png" alt="add source"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You don't need to use wildcards (*) for all endpoints, only for subdomains.  Which means you can enable for everything (not recommended) by using just a wildcard.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;th&gt;Needed in connect-src&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://restcountries.com/v3.1/name/peru" rel="noopener noreferrer"&gt;https://restcountries.com/v3.1/name/peru&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://restcountries.com" rel="noopener noreferrer"&gt;https://restcountries.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;a href="https://restcountries.com/v3.1/all" rel="noopener noreferrer"&gt;https://restcountries.com/v3.1/all&lt;/a&gt;&lt;/td&gt;
&lt;td&gt;&lt;a href="https://restcountries.com" rel="noopener noreferrer"&gt;https://restcountries.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;a href="https://api.restcountries.com/" rel="noopener noreferrer"&gt;https://api.restcountries.com/&lt;/a&gt;...&lt;/td&gt;
&lt;td&gt;&lt;a href="https://api.restcountries.com" rel="noopener noreferrer"&gt;https://api.restcountries.com&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Multiple subdomains&lt;/td&gt;
&lt;td&gt;https://*.restcountries.com&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Any URL anywhere&lt;/td&gt;
&lt;td&gt;* (not recommended)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;And you should be all ready. Just a quick call out, CPS runs when the browser hits the site, so updates don't always appear without closing and opening the browser.&lt;/p&gt;

&lt;p&gt;More info can be found here &lt;a href="https://learn.microsoft.com/en-us/power-platform/admin/content-security-policy" rel="noopener noreferrer"&gt;MS Learn CPS&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Though I think it's important to say, connectors are by far the better way to go, if you need to call an external API you should be using custom connectors. Just some of the benefits include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;DLP is across tenant and environments so easier to manage&lt;/li&gt;
&lt;li&gt;Stops you having to deal with storing secrets&lt;/li&gt;
&lt;li&gt;It handles the risky stuff like auth&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if you are going to use it, is probably only good for unauthenticated API's.&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Code Storage
&lt;/h2&gt;

&lt;p&gt;Code Apps are stored in the Power Platform as simple HTML, JavaScript, CSS files (like Canvas Apps they are not actually stored in Dataverse, there is just a reference table - {{dataverseURL}}/api/data/v9.2/canvasapps?$filter=canvasapptype eq 4).&lt;/p&gt;

&lt;p&gt;But it means you cant edit/build in the Power Platform, you have to build it code editing tools like VS Code. So if you want to edit it you have to export it in a solution, and this leads to the big problem, when building in React the code is transpiled to JavaScript, which is a one way process. So you can't edit it, which means you need to store the code somewhere else.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quick all out, I mentioned I build in vanilla JavaScript, and one of the benefits to this is it's not transpiled, so as long as you don't minify the files you can export the solution and edit the files. Check out codeapp.js to find out more.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyksytmr925t3k5h9868.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcyksytmr925t3k5h9868.png" alt="code app using codeapp.js"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;code app using codeapp.js&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;The best place to store your code is probably GitHub, its free, works great with VS Code/most code editors, and has features like version control/multi dev. But it's just code in files, so you can store it anywhere, the most important thing is to set up a central location and ensure its used, as else once its lost you cannot get it back.&lt;/p&gt;
&lt;h2&gt;
  
  
  4. Code Reviews
&lt;/h2&gt;

&lt;p&gt;Not really part of the environment setup, but something I wanted to call out because it needs to be part of you deployment process between environments. As Code Apps use standard code it means that your normal code review process wont work, tools like &lt;a href="https:appreview-prod.dev" rel="noopener noreferrer"&gt;appreview-pro&lt;/a&gt; don't support them (yet 😎), on top of that there are more risks/vulnerabilities. &lt;/p&gt;

&lt;p&gt;But on the flip side it's just code, and this is a tried and tested path, so there are already lots of tools for code scanning/reviewing, just use your organizations preferred tool.&lt;/p&gt;

&lt;p&gt;But that then leads to the broken line of trust, as what is deployed is transpiled, how do you review it? I recommend that your deployment pipeline changes, and you do not follow the standard Dev - Test - Prod, you need to deploy from your repo to Test - Prod, and that needs to be done by someone who is not the developer, and after they have completed the code review / scan.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16sw5xbg287lwsx6paps.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F16sw5xbg287lwsx6paps.png" alt="code app deployment process"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;And that's it, you should have the foundation to build safe Code Apps, but as I said I still don't think they are right for everyone, but they definitely are something you should explore/have in your toolbox, and are definitely cool 😎&lt;/p&gt;

&lt;p&gt;If you want to use the demo app I created that uses &lt;a href="https://restcountries.com/" rel="noopener noreferrer"&gt;https://restcountries.com/&lt;/a&gt; api you can download it from my repo here: &lt;a href="https://github.com/wyattdave/Power-Platform/tree/main/Power%20App%20Artifacts" rel="noopener noreferrer"&gt;https://github.com/wyattdave/Power-Platform&lt;/a&gt;. Its built with &lt;a href="https://codeappjs.com" rel="noopener noreferrer"&gt;https://codeappjs.com&lt;/a&gt; so you can read all of the code too.&lt;/p&gt;



&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=codapEnvir" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerapps</category>
      <category>powerplatform</category>
      <category>react</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Power Apps - A Cooler Way to use Code Apps</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 16 Mar 2026 07:13:12 +0000</pubDate>
      <link>https://dev.to/wyattdave/power-apps-a-cooler-way-to-use-code-apps-3nb6</link>
      <guid>https://dev.to/wyattdave/power-apps-a-cooler-way-to-use-code-apps-3nb6</guid>
      <description>&lt;p&gt;If you don't know about Code Apps in the Power Platform let me quickly fill you in.&lt;/p&gt;

&lt;p&gt;They are full React apps that are packaged and deployed through the Power Platform.&lt;/p&gt;

&lt;p&gt;Because they are piggy backing off the platform infrastructure rather then part of it there are some callouts&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You don't build them in the platform - you use VS Code (or other coding tools)&lt;/li&gt;
&lt;li&gt;The development code is not stored in the platform (only the built code)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This means you don't user make.powerapps.com and even a unmanaged solution for development, as once in the platform you can't really edit them (without hacking open the solution file).&lt;/p&gt;




&lt;p&gt;The thing is, code apps are obviously not LowCode, you need fully trained developers to build them, so why would it be in the Power Platform?&lt;/p&gt;

&lt;p&gt;Well there will be some developers who use it purely to avoid setting everything up in Azure and avoiding the pain of auth, but i think the real answer is vibe coding.&lt;/p&gt;

&lt;p&gt;I wrote a blog already about how you can use GitHub Copilot to build Code Apps &lt;a href="https://dev.to/wyattdave/vibe-coding-a-power-app-the-pro-way-with-code-apps-56dk"&gt;vibe coding a power app the pro way with codeapps&lt;/a&gt;, but in my opinion using AI for development is best when you can read the code.&lt;/p&gt;

&lt;p&gt;So that had me thinking, I can read basic JavaScript, HTML, and CSS, React  is just compiled to this. And looking at the code app in the solution, it is just JavaScript, HTML, and CSS. So can I just build a  normal web app and deploy that instead of React.&lt;/p&gt;

&lt;p&gt;And the answer is yes 😎 &lt;/p&gt;




&lt;p&gt;The starting point to look at is the dist folder, this is where the React code is built into normal web tech.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftolg2pj261003hu0jv7o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftolg2pj261003hu0jv7o.png" alt="dist folder"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it's just a index.html file, a JavaScript file, a CSS file, and a image file.&lt;/p&gt;

&lt;p&gt;So straight away in theory we could just drop our own code in and it should work.&lt;/p&gt;

&lt;p&gt;Well not quite, and that's because we are running it inside Power Apps, so we need to communicate specifically with Power Apps.&lt;/p&gt;

&lt;p&gt;And this is where we need the the Power Apps SDK. Looking in a normal code app the code is in the Power Apps node library.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdc35gz9i2julnhlv818y.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdc35gz9i2julnhlv818y.png" alt="node"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As the code is spread across multiple files, and in TypeScript, it's not easy for use to use.&lt;/p&gt;

&lt;p&gt;We could use the built file from a test app:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F42qz51fjvz93gazhn6ig.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F42qz51fjvz93gazhn6ig.png" alt="test app js"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But it's incredibly hard to read, may not cover everything we need, and has any app specific code included.&lt;/p&gt;

&lt;p&gt;So to make sure it covered everything it's time to bring in a partner, and in my case its Opus 4.6. After a few tries I managed to get it to create a JavaScript version to use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx84fuaav6k0hdocpq3rb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx84fuaav6k0hdocpq3rb.png" alt="power-apps-data.js"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But although its fully functional, it definitely isn't readable, so this is when I decided to build bridging functions. These functions create a easy to use code that then calls the sdk.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl0vj6e2gnu7jj8kramj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxl0vj6e2gnu7jj8kramj.png" alt="codeapp.js"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Now all I need to do is import the functions I want and build my own JavaScript code.&lt;/p&gt;

&lt;p&gt;Our Index.html now looks something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight html"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;!doctype html&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;html&lt;/span&gt; &lt;span class="na"&gt;lang=&lt;/span&gt;&lt;span class="s"&gt;"en"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;head&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;charset=&lt;/span&gt;&lt;span class="s"&gt;"UTF-8"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;meta&lt;/span&gt; &lt;span class="na"&gt;name=&lt;/span&gt;&lt;span class="s"&gt;"viewport"&lt;/span&gt; &lt;span class="na"&gt;content=&lt;/span&gt;&lt;span class="s"&gt;"width=device-width, initial-scale=1.0"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;title&amp;gt;&lt;/span&gt;YOUR APP&lt;span class="nt"&gt;&amp;lt;/title&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"importmap"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;imports&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
          &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@microsoft/power-apps/data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./power-apps-data.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/head&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;body&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;div&lt;/span&gt; &lt;span class="na"&gt;id=&lt;/span&gt;&lt;span class="s"&gt;"root"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;hello world&lt;span class="nt"&gt;&amp;lt;/div&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;script &lt;/span&gt;&lt;span class="na"&gt;type=&lt;/span&gt;&lt;span class="s"&gt;"module"&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;
      &lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;createItem&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;./codeapp.js&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
      &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;//on load code&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;
      &lt;span class="c1"&gt;// code&lt;/span&gt;
      &lt;span class="nf"&gt;boot&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;/script&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/body&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/html&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;power-apps-data.js is the sdk&lt;/li&gt;
&lt;li&gt;codeapp.js is the bridging functions&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And now we have a working HTML,JavaScript, CSS app. We still need to do some more bits to make it work, and this is all around the Power Platform CLI (so we still need that installed).&lt;/p&gt;

&lt;p&gt;You need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create power-config.json file: _pac code init --displayName "" _&lt;/li&gt;
&lt;li&gt;Sign into Tenant: &lt;em&gt;pac auth create&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Select environment: &lt;em&gt;pac env select --environment "environment-id"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Create connection: &lt;em&gt;pac connection create --name "connection-name" --application-id "app-id" --client-secret "secret" --tenant-id "tenant-id"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Add data sources (for all connections): &lt;em&gt;pac code add-data-source -a "connection-name" -c "connection-id"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;Deploy to Power Platform: _pac code push --solutionName YourSolutionName
_&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And thats about it.&lt;/p&gt;




&lt;p&gt;If anyone this sounds interesting to you, I've created a couple of things to get you started.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://codeappjs.com" rel="noopener noreferrer"&gt;codeappjs.com&lt;/a&gt; is all of the files needed for you to build your own JavaScript Code App. It also goes into a lot more detail around functions, and provides working demos.&lt;/p&gt;

&lt;p&gt;Currently it has 5 connectors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Dataverse&lt;/li&gt;
&lt;li&gt;SharePoint&lt;/li&gt;
&lt;li&gt;Office 365 User&lt;/li&gt;
&lt;li&gt;Office 365 Outlook&lt;/li&gt;
&lt;li&gt;Office 365 Groups&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it's fully open source, so hopefully everyone can add more.&lt;/p&gt;

&lt;p&gt;To use it yourself you can either:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Download simple zip file with all the files&lt;/li&gt;
&lt;li&gt;Clone the GitHub repo&lt;/li&gt;
&lt;li&gt;Install from NPM&lt;/li&gt;
&lt;li&gt;Use CodeAppJS Plus&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What's CodeAppJS Plus, well I'm glad you asked, it's a AI Coding Agent built specifically for JavaScript Code Apps. It runs as a VS Code extension, with a chat interface for prompting your Code App, it also has CLI commands set as buttons for easier use.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx0xaenrhobn4nwvmt3uk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx0xaenrhobn4nwvmt3uk.png" alt="codeappjs screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmx00lks79urqlajvna4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwmx00lks79urqlajvna4.png" alt="codeappjs screenshot"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It still requires the Power Platform CLI, and GitHub Copilot, and obviously VS Code to run it.&lt;/p&gt;

&lt;p&gt;Install it &lt;a href="https://marketplace.visualstudio.com/items?itemName=PowerDevBox.codeappjsplus" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;So why did I convert React to Vanilla JavaScript, well a few reasons:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If you have read some of my previous blogs you will know I'm a little crazy&lt;/li&gt;
&lt;li&gt;I can code in JavaScript and I wanted to code my own Code App&lt;/li&gt;
&lt;li&gt;In spirit of LowCode I wanted to make it a little more simple&lt;/li&gt;
&lt;li&gt;Believe it or not AI seems to deliver better results then React&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqik9zn7bvmr8stcqqcwo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqik9zn7bvmr8stcqqcwo.png" alt="kanban example"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Example Kanban app created in CodeAppJS Plus&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;I never did quite understand why Microsoft has gone with React as the vibe coming language.&lt;/p&gt;

&lt;p&gt;React has 3 main advantages&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its declarative (desired outcome) vs JavaScripts imperative approach (sequence of tasks)&lt;/li&gt;
&lt;li&gt;Great for reusability&lt;/li&gt;
&lt;li&gt;Handles complex state management better&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But here's the thing:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Prompts by their very nature are declarative&lt;/li&gt;
&lt;li&gt;Reuse is less important when agent is doing all the work&lt;/li&gt;
&lt;li&gt;Power Apps are very very rarely that complex that they need better state management&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So why use React when its a lot more verbose, wasting tokens, and buld step adds more tool calls.&lt;/p&gt;

&lt;p&gt;If you want to see how I made my own AI Coding Agent, check out my next blog.&lt;/p&gt;



&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=pacodejs" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerapps</category>
      <category>powerplatform</category>
      <category>ai</category>
      <category>cli</category>
    </item>
    <item>
      <title>From Low-Code to AI Development</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 09 Mar 2026 07:18:23 +0000</pubDate>
      <link>https://dev.to/wyattdave/from-low-code-to-ai-development-12lk</link>
      <guid>https://dev.to/wyattdave/from-low-code-to-ai-development-12lk</guid>
      <description>&lt;p&gt;There doesn't seem to be a day that goes by without a post or article stating that "Low-code is dead", and while this isn't true, with AI development things are definitely changing.&lt;/p&gt;

&lt;p&gt;Although working in low-code tools like the Power Platform is my job, in my spare time I like to pretend to be a pro-coder, and with AI tools now at a level that I can almost not pretend.&lt;/p&gt;

&lt;p&gt;So this blog is all about how I do AI development, its probably not the right way, or the best way, but it works for me.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;My Skill Base&lt;/li&gt;
&lt;li&gt;My Setup&lt;/li&gt;
&lt;li&gt;How I Build&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. My Skill Base
&lt;/h2&gt;

&lt;p&gt;As I said, I'm not a pro-code developer, but I know a few things. And I think it's important to understand that using AI tools with no understanding only leads to deferred pain. I think there are big differences between AI Development and Vibe coding.&lt;/p&gt;

&lt;p&gt;So what do I know:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Basics of HTML, CSS&lt;/li&gt;
&lt;li&gt;A little more than the basics of JavaScript (I may not be able to write all of it but I can read it)&lt;/li&gt;
&lt;li&gt;GitHub (barely)&lt;/li&gt;
&lt;li&gt;Git Bash, wrangler (barely)&lt;/li&gt;
&lt;li&gt;Cloudflare workers and Pages&lt;/li&gt;
&lt;li&gt;Cloudflare Database and Keyvaults&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But I don't&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Understand React&lt;/li&gt;
&lt;li&gt;Use TypeScript (but I could as do use it in OfficeScripts)&lt;/li&gt;
&lt;li&gt;Bother with any sort of build process&lt;/li&gt;
&lt;li&gt;Work on the main branch(unless I want a non-prod instance)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But my mind is like this, React gets built to Html/CSS/JavaScript, so why not skip a stage and get the AI to just build it direct.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. My Setup
&lt;/h2&gt;

&lt;p&gt;I'm not into CLI's that much, so no Claude Code, and Cursor is expensive, so that leaves good old VS Code (plus I get GitHub Pro as an MVP reward 😎). The output window is ok, but I don't just read the agents outputs, I like to see the code, so it works for me.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zh33vku7doc9negi846.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F4zh33vku7doc9negi846.png" alt="vs code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I'm a Opus man, infact Opus 4.5 was when I felt confident to move beyond AI Assisted Development to full AI Development. 4.6 is better but not significantly. If Opus is having a bad day I will get Codex 5.3 ago (looking forward to testing 5.4), and Gemini 3/3.1 is worth a go when you want something more visually creative. But 9 times out of 10 its Opus for me, but that's more of a personal preference, as most of the top models and some open weight are perfectly good enough.&lt;/p&gt;

&lt;p&gt;One of the most important things I think you need before you start AI development is an instruction file. This is like a custom prompt that you use to ensure the agent works the way you want. It shouldn't be too big, and I personally don't let the agent write its own.&lt;/p&gt;

&lt;p&gt;My instruction file covers a few things but the main ones are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Naming convention&lt;/li&gt;
&lt;li&gt;File structure&lt;/li&gt;
&lt;li&gt;Language preferences (as example Opus like JavaScript var's, where I'm a let guy)&lt;/li&gt;
&lt;li&gt;Coding preferences&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one is the big one, I like my the LLM to work in small units, building in function blocks. That way changes are often contained, it's easier to read, and everything is reusable.&lt;/p&gt;

&lt;p&gt;This is my current instruction.md file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight markdown"&gt;&lt;code&gt;&lt;span class="gh"&gt;# Copilot Instructions for AutoReview Pro&lt;/span&gt;

These instructions guide AI coding agents working in this repository to be immediately productive and consistent with project conventions.

&lt;span class="gu"&gt;## Project Overview&lt;/span&gt;
&lt;span class="p"&gt;-&lt;/span&gt; standard web technologies: HTML, CSS, JavaScript (ES6+).
&lt;span class="p"&gt;-&lt;/span&gt; Core files:
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`index.html`&lt;/span&gt;: Structure, assets, and script/style inclusions.
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`styles.css`&lt;/span&gt;: responsive and built to light/dark themes using CSS custom properties.
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`script.js`&lt;/span&gt;: key functionality of the site
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`dom.js`&lt;/span&gt;: dom manipulation functions
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`imgs/`&lt;/span&gt;: image files for UI icons.
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`README.md`&lt;/span&gt;: Features, usage, and future enhancements.
&lt;span class="p"&gt;  -&lt;/span&gt; &lt;span class="sb"&gt;`Sitemap.xml`&lt;/span&gt;: for search engine indexing.
&lt;span class="p"&gt;-&lt;/span&gt; No build step.
&lt;span class="p"&gt;-&lt;/span&gt; Create as a Progressive Web App (PWA) with service worker for offline support and caching, but with always fetching latest data when online.
&lt;span class="p"&gt;-&lt;/span&gt; cloudflare hosting
&lt;span class="p"&gt;
-&lt;/span&gt; Follow these naming conventions:
&lt;span class="p"&gt;  -&lt;/span&gt; Use camelCase for variables and functions.
&lt;span class="p"&gt;  -&lt;/span&gt; Prefix variable names: &lt;span class="sb"&gt;`b`&lt;/span&gt; boolean, &lt;span class="sb"&gt;`i`&lt;/span&gt; number, &lt;span class="sb"&gt;`s`&lt;/span&gt; string, &lt;span class="sb"&gt;`a`&lt;/span&gt; array, &lt;span class="sb"&gt;`o`&lt;/span&gt; object, &lt;span class="sb"&gt;`e`&lt;/span&gt; element.
&lt;span class="p"&gt;-&lt;/span&gt; Ensure variables are type consistent and avoid implicit type coercion by using naming conventions.
&lt;span class="p"&gt;-&lt;/span&gt; CSS should be in a separate file, avoid inline styles unless for dynamic styling.
&lt;span class="p"&gt;-&lt;/span&gt; JavaScript should be in a separate file, avoid inline event handlers and scripts in html.
&lt;span class="p"&gt;-&lt;/span&gt; JavaScript files should follow: script.js for main logic, dom.js for dom manipulation functions, specific js files for large logic, and per html page for page-specific logic.
&lt;span class="p"&gt;-&lt;/span&gt; Function-first approach; avoid classes unless necessary.
&lt;span class="p"&gt;-&lt;/span&gt; Build functions for reusability and testability.
&lt;span class="p"&gt;-&lt;/span&gt; Use descriptive names for variables and functions, avoiding abbreviations.
&lt;span class="p"&gt;-&lt;/span&gt; Use let and const, avoid var.
&lt;span class="p"&gt;-&lt;/span&gt; Use const for dom elements where possible.
&lt;span class="p"&gt;-&lt;/span&gt; Use &lt;span class="sb"&gt;`//`&lt;/span&gt; for single-line comments and &lt;span class="sb"&gt;`/* */`&lt;/span&gt; for multi-line comments.
&lt;span class="p"&gt;-&lt;/span&gt; Use forEach, map, filter, reduce for array operations instead of for loops where appropriate.
&lt;span class="p"&gt;-&lt;/span&gt; Use arrow functions for anonymous functions and callbacks.
&lt;span class="p"&gt;-&lt;/span&gt; Use " for html attributes and ' for js strings, &lt;span class="sb"&gt;` for template literals.
- Use `&lt;/span&gt;new RegExp("pattern","flags")&lt;span class="sb"&gt;` (avoid literal `&lt;/span&gt;/.../flags&lt;span class="sb"&gt;`).
- Use `&lt;/span&gt;fetch&lt;span class="err"&gt;`&lt;/span&gt; for API calls, with async/await syntax.
&lt;span class="p"&gt;-&lt;/span&gt; Handle errors gracefully with try/catch and user-friendly messages. 
&lt;span class="p"&gt;-&lt;/span&gt; Follow the existing code style and conventions in the project for consistency.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I also have a few skill.md files for specific tasks (skills are similar to instructions but the LLM uses them when necessary), my favourite example is frontend-design skill from Anthropic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvj60ajbycvcifve9z0m3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvj60ajbycvcifve9z0m3.png" alt="anthropic skill"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md" rel="noopener noreferrer"&gt;https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md &lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is an example of a prompt I will use to help start:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;create me 5 landing pages for my website. the site provides training, consultancy, and custom builds. Each site should be creative and unique, they should follow a modern design. To aid review create a way to navigate between the 5 pages. Make sure you use the frontend-design skill.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24l429oxnnn5xtn349l1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F24l429oxnnn5xtn349l1.png" alt="vs code creating ideass"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8p341ga3e0kwgxdxa16u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F8p341ga3e0kwgxdxa16u.png" alt="designs"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can see them all live &lt;a href="https://wyattdave.github.io/Power-Platform/ai%20site%20examples/index.html" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. How I Build
&lt;/h2&gt;

&lt;p&gt;My approach to using AI is to use it very much like a tool, I want it to do a specific thing. This means the scope and outcome if focused and generally small. Over time and with improvements of the models I've felt more confident in increasing the size and complexity of the thing. &lt;/p&gt;

&lt;p&gt;In my mind this evolution can be broken them into 2 categories, AI Assisted development and AI Development. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1prjhi0tqglkz9xraaj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs1prjhi0tqglkz9xraaj.png" alt="development styles"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;AI Assisted&lt;/strong&gt; means that I lead the agent a lot more, I normally prompt at a function level, and then I review the output and then link everything together by hand. The reason I like this is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The context is small for the LLM so its normally better results&lt;/li&gt;
&lt;li&gt;Its contained so easier for me to review&lt;/li&gt;
&lt;li&gt;As I'm doing the linking and using I still understand everything&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A good example was when I was building my code review tool &lt;a href="Https://autoreview-pro.dev"&gt;AutoReview-Pro&lt;/a&gt;, I had a lot of JSON data that I wanted represented as HTML tables, so I used this prompt&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create me a function for converting JSON to HTML, I will pass in 2 arrays. The first will be the array of data, the second will be configuration. Each item in the configuration will represent the columns in the output, each item will have these keys: Name - field from the data array, Display name - name of the column in the header, Width - width % for the column, Link - field to use when clicked, this is optional and if not included it should not include a link&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;After reviewing the function and testing it I then used it in my code where I wanted it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19q6w8onerssxim375vo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F19q6w8onerssxim375vo.png" alt="AI Assisted"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But as the models have become more powerful I have felt more and more confident moving to &lt;strong&gt;AI Developed&lt;/strong&gt;. You can think of this as the next level up, where the scope of work increases and the detail in the prompt decreases. I now want to create a piece of functionality/value in the project. A good example would be:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;I want the users to be able to download the entire collection. The button should be next to the edit collection button. The output should be a postman collection file and be downloaded to the users device. Use the toast function to update user with success/fail messages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;As you can see the piece of work is now:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Larger scope - updates 3 files: JavaScript, HTML and CSS&lt;/li&gt;
&lt;li&gt;Less involvement by myself - it links everything together&lt;/li&gt;
&lt;li&gt;Simpler prompt - half the length&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is trade off that it's harder for me to review the output, and I'm more inclined to be lazy and just trust it. So there is potential for some tech debt in there and missed dege cases, but it moves me from being 5x faster to 20x faster, so I would say it's worth it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstm1bm2qh4r1u9m5j8qh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fstm1bm2qh4r1u9m5j8qh.png" alt="AI developed"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In both use cases I have a golden rule, which is "I do small updates". If I need to update a colour of an item, I go into the CSS and edit it, if I want a button moving, I moved it. This is because there is minimum time saving, it removes the risk of double code and it forces me to understand the code based.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Double code&lt;/strong&gt; - this is one of the biggest issues I see with agent generated code, the agent solves a problem in 2 different ways (e.g uses CSS and JavaScript when solution only needs one), this makes it hard to read, really hard to debug, and can generate bugs when the 2 different ways clash.&lt;/p&gt;

&lt;p&gt;There is also the elephant in the room with AI development, Vibe coding. Do I vibe code, yes, but do I do it for anything important no.&lt;/p&gt;

&lt;p&gt;In my view the main difference between AI development and Vibe coding is scope and understanding.&lt;/p&gt;

&lt;p&gt;Whn vibe coding I scope everything to the agent, and I don't understand the output. If I was to ask a agent to create me a app that did x, it would most likely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create a React App - I can't develop in React&lt;/li&gt;
&lt;li&gt;Design/architect in a way that I'm not use to&lt;/li&gt;
&lt;li&gt;Build to its training, so generally make something that looks AI generated&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So when I do vibe code I ensure my instruction.md file is used, that at least means it builds in something I can develop in and generally the way I like it.&lt;/p&gt;

&lt;p&gt;I also don't do it for anything important, anything where if it broke I would be in trouble if I could not fix it.&lt;/p&gt;




&lt;p&gt;And that's how I now build, when I look back at the last year and some of my projects and the level of AI involvement, its crazy.&lt;/p&gt;

&lt;p&gt;&lt;a href="Https://flow.powerdevbox.com"&gt;Flow Utilizer&lt;/a&gt; - 100% me&lt;br&gt;
&lt;a href="Https://appreview-pro.dev"&gt;AppReview-Pro&lt;/a&gt; - 80% me&lt;br&gt;
&lt;a href="Https://autoreview-pro.dev"&gt;AutoReview-Pro&lt;/a&gt; - 50% me&lt;br&gt;
&lt;a href="Https://ppundoc.com"&gt;Power Platform Undoc&lt;/a&gt; - 20% me&lt;/p&gt;

&lt;p&gt;And look at those sites, it's hard to argue against the agent being a lot better at building then me.&lt;/p&gt;



&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=lctoai" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>lowcode</category>
      <category>ai</category>
      <category>vibecoding</category>
      <category>powerplatform</category>
    </item>
    <item>
      <title>Power Automate - Why You Should Love Coalesce</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 23 Feb 2026 08:04:33 +0000</pubDate>
      <link>https://dev.to/wyattdave/power-automate-why-you-should-love-coalesce-3bl2</link>
      <guid>https://dev.to/wyattdave/power-automate-why-you-should-love-coalesce-3bl2</guid>
      <description>&lt;p&gt;One of my early blogs I spoke about how I love Do Unitil loops, and Im sure some people thought I was a little crazy, and now I'm talking about loving a expression, and I think everyone now knows Im crazy. But trust me, after a read you might be joining me on the coalesce side 😎&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fre80qxorxsnz6uds2ivr.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fre80qxorxsnz6uds2ivr.png" alt="meme"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What is coalesce&lt;/li&gt;
&lt;li&gt;Simple uses&lt;/li&gt;
&lt;li&gt;Cool uses&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. What is coalesce
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfalebvqb933n5qws8yd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fkfalebvqb933n5qws8yd.png" alt="ms learn"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well in a nutshell coalesce is designed to handle null/undefined values. So if you have a optional field in a action response you can use coalesce as a kind of if statement:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If value-is-not-null
  use-value
else
  use-this-value-instead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can also stack more then one value, so it could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;If value-is-not-null
  use-value
else If value-is-not-null
  use-value
else If value-is-not-null
  use-value
else If value-is-not-null
  use-value
else
  use-this-value-instead
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key things to remember is it will run sequentially, so the first valid will be returned, and if there is no match the last one will be returned (so always make the last is valid).&lt;/p&gt;

&lt;p&gt;Coalesce also requires one type, so you cant have the first value a integer and the second a string, they would all have to be the same.&lt;/p&gt;

&lt;p&gt;The last thing to call out is this is not a replacement for empty(), as blank strings and empty arrays will be classified as valid.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Input&lt;/th&gt;
&lt;th&gt;Coalesce&lt;/th&gt;
&lt;th&gt;Empty&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;undefined&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;null&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;"" (empty string)&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;{}&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;[]&lt;/td&gt;
&lt;td&gt;false&lt;/td&gt;
&lt;td&gt;true&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Full MS Docs here: &lt;a href="https://learn.microsoft.com/en-us/azure/logic-apps/expression-functions-reference#coalesce" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/azure/logic-apps/expression-functions-reference#coalesc&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Simple uses
&lt;/h2&gt;

&lt;p&gt;The out of the box use for coalesce is when you are working with unstructured/inconsistent data. Actions will often have optional fields, which will mean if you reference those fiels you get a null value. Null values could break the action, or show unpleasant value to the end user.&lt;/p&gt;

&lt;p&gt;So in the below example, how would you get the powerAutomate year for all users, when not all users have the certificate?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;value&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;David&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;location&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Nottingham&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;certificates&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;powerAutomate&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;year&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2020&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;powerApps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;year&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2022&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copiltoStudio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;year&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2024&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;],&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;John&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;location&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Timbuktu&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;certificates&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;powerApps&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;year&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2024&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;copiltoStudio&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:{&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;year&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2024&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is where you would use a coalesce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;coalesce(
  items("For_each_User")?['user']?['certificates']?['powerApps']?['year']
,
  'Has Not Completed Certificate'
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Likewise this can also be used for manual flows with optional inputs.&lt;/p&gt;

&lt;p&gt;You could do it with a empty() expression and some if()s, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;if(
  empty(items("For_each_User")?['user']?['certificates']?['powerApps']?['year'])
,
  'Has Not Complete Certificate'
,
  items("For_each_User")?['user']?['certificates']?['powerApps']?['year']
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But doing nested if()'s would be a lot more complicated, compared to a coalesce():&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;coalesce(
  items("For_each_User")?['user']?['certificates']?['powerApps']?['year']
,
  items("For_each_User")?['user']?['certificates']?['powerAutomate']?['year']
,
  items("For_each_User")?['user']?['certificates']?['copilotStudio']?['year']
,
  'Has Not Completed Certificate'
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Cool uses
&lt;/h2&gt;

&lt;p&gt;We will all agree, that although super useful, the above scenarios are not that common, so why would I love coalesce, well its because of another cool way to use it.&lt;/p&gt;

&lt;p&gt;If you have read some of my previous blogs I want my flows to be optimised and efficient, no unnecessary actions (I deep dive more into it here &lt;a href="https://dev.to/wyattdave/power-automate-the-direct-methodology-32mf"&gt;The Direct Methodology&lt;/a&gt;). And coalesce will be your best friend for removing unnecessary actions, and that's because it's brilliant for conditions and switches.&lt;/p&gt;

&lt;p&gt;Here's an example I see often:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0j869el39ohj845m3t8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fv0j869el39ohj845m3t8.png" alt="condition with variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The output from either branch is needed after, so its stored in a variable, makes sense right. But with a coalesce you don't need that variable, simple use the outputs where you would normally use the variable&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;coalesce(
  outputs('Get_a_row_by_ID')?['body/fullname']
,
  outputs('Get_a_row_by_ID_2')?['body/fullname']
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And because you can have multiple inputs this can also be used on a switch.&lt;/p&gt;

&lt;p&gt;There are some challenging situations, but again these can be done with a  little creativity.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;First Item&lt;/strong&gt;&lt;br&gt;
First is great when you want to grab just one row from an array (if only there was a real lookup expression), but that can break the coalesce, as the first throws an error not a null because a null has no length. But you can fix it like this&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;coalesce(
  first(
    coalesce(
      outputs('Get_rows')?['body/value']
    ,
      createArray()
    )
  )
,
  {"fallback":"hello world"}
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So we first check if the array is null, if it is then we create empty array. Then we check to see if first item is null, if it is we fallback.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Array or Object&lt;/strong&gt;&lt;br&gt;
What happens if we wanted if a Get_item or Get_items, we know coalesce has to have the same type so it shouldn't work. Well again a little bit of creativity we can do it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;coalesce(
  outputs('Get_rows')?['body/value']
,
  array(outputs('Get_a_row')?['body'])
) 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The reason this works is because our conditon means we always know either the Get_rows or Get_a_row will return a value. As the create array() will throw an error if Get_a_row is null, we do that second, ensuring it is never null.&lt;/p&gt;




&lt;p&gt;As you can see coalesce has the power to remove multiple actions, a flow easier to read and saving API calls (remember a standard license only has 6k API per day and every call has a carbon footprint). &lt;/p&gt;

&lt;p&gt;And that's why I love it, and there are over 140 expressions in total, so when building your next flow, try an expression before an action 😎. &lt;/p&gt;

&lt;p&gt;I did a list of &lt;a href="https://dev.to/wyattdave/power-automate-top-10-cool-under-used-expressions-739"&gt;my favourite expressions&lt;/a&gt; to give you a head start.&lt;/p&gt;

&lt;p&gt;Also I created a quick reference page with all the expressions and a Excel file you can download here &lt;a href="https://powerdevbox.com/subs/Power%20Automate%20Expressions" rel="noopener noreferrer"&gt;Power DevBox Expressions&lt;/a&gt;&lt;/p&gt;




&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=coalesce" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerautomate</category>
      <category>logicapps</category>
      <category>lowcode</category>
      <category>powerplatform</category>
    </item>
    <item>
      <title>Power Automate - Building Readable Flows</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 09 Feb 2026 06:49:58 +0000</pubDate>
      <link>https://dev.to/wyattdave/power-automate-building-readable-flows-dkd</link>
      <guid>https://dev.to/wyattdave/power-automate-building-readable-flows-dkd</guid>
      <description>&lt;p&gt;They say the best code is written in a way that you don't need to add  comments, just good naming and design, and that had me thinking about Power Automate.&lt;/p&gt;

&lt;p&gt;Power Automate is a literal flow chart, flow charts were created to make processes easier to read. So why can't I understand what the hell some flows do!&lt;/p&gt;

&lt;p&gt;And that's what this blog is all about, how with a few small changes you can build your flows in a way that anyone can open and understand 😎&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Planning&lt;/li&gt;
&lt;li&gt;Naming&lt;/li&gt;
&lt;li&gt;Notes&lt;/li&gt;
&lt;li&gt;Design&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Planning
&lt;/h2&gt;

&lt;p&gt;This one is kind of obvious but still very important. The biggest reason flows become hard to read is lack of planning. If the developer takes a "figure it out as i go", then the end result is disjointed and confusing.&lt;/p&gt;

&lt;p&gt;So for every flow you should plan out a couple of key things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's the start state of the flow&lt;/li&gt;
&lt;li&gt;What's the end state of the flow&lt;/li&gt;
&lt;li&gt;What pieces of value happen within the flow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I recommend a lot more planning personally (&lt;a href="https://dev.to/wyattdave/power-automate-4-steps-to-building-a-flow-36c0"&gt;Power Automate - 4 Steps to Building a Flow&lt;/a&gt;), but if you have these basic ones it will really help make the flow structured and consistent.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Naming
&lt;/h2&gt;

&lt;p&gt;Naming things right will have probably the biggest impact on the readability of your flow, there are 2 golden rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Describe in clear language (no abbreviations)&lt;/li&gt;
&lt;li&gt;Be consistent&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I have 2 patterns I follow:&lt;/p&gt;

&lt;h3&gt;
  
  
  Variables
&lt;/h3&gt;

&lt;p&gt;Variables need to clearly explain what data they are going to hold and the type of variable.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Variable&lt;/th&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Example&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;sVariable&lt;/td&gt;
&lt;td&gt;string&lt;/td&gt;
&lt;td&gt;sEmailSubject&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;iVariable&lt;/td&gt;
&lt;td&gt;integer&lt;/td&gt;
&lt;td&gt;iRowCount&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;bVariable&lt;/td&gt;
&lt;td&gt;boolean&lt;/td&gt;
&lt;td&gt;bFoundEntry&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;oVariable&lt;/td&gt;
&lt;td&gt;object&lt;/td&gt;
&lt;td&gt;oUserRecord&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;aVariable&lt;/td&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;aAllMatchedUsers&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Actions
&lt;/h3&gt;

&lt;p&gt;Actions have an additional requirement, what action it is. As all actions share the same connector image, if you remove the action type it can be really hard to read.&lt;/p&gt;

&lt;p&gt;As example, how easy is it to read the below flow, how about can you tell me what the 2 actions do?&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6k4sylufrq1cjbnp5ka.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp6k4sylufrq1cjbnp5ka.png" alt="actions with no description"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Guess what i do is create item, Guess what i do2 is delete item, quite a lot to get wrong lol&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;So actions must keep the original name of what they do. How much easier is below to read.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhkanma6874it306r0bm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fuhkanma6874it306r0bm.png" alt="actions with descriptionb"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Again with consistency, all mine are Action - description. I also ensure the description is detailed enough. I could just put Get Items - records, but by adding the filter query of over 10 days old I can get a lot better understanding of what the flow is trying to do.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Notes
&lt;/h2&gt;

&lt;p&gt;Yes I know my first sentence made out that you dont need notes when you create clear solutions, but its not true. Notes are such an under utilized feature in Power Automate. You don't need them everywhere, but there are a couple of times they can be really useful.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expressions
&lt;/h3&gt;

&lt;p&gt;If you have one of those beautiful expressions that use multiple functions to come up with an amazing solution (you know the ones 😎), without the developers insight and understanding these can be incredibly hard to understand let alone edit. Dropping in a comment that explains what the expression does and can make everything make sense (including for future you who has forgotten what the flow does too).&lt;/p&gt;

&lt;h3&gt;
  
  
  Solutions Through Pain
&lt;/h3&gt;

&lt;p&gt;Again another one that we all experience. When something that should work just doesn't and you have no idea why (lets be honest its normally Power Automates fault but anyway). Through blood, swet, tears, repeated trial and error you come up with a solution. This where a note is so important, not only does it explain what its doing, but it also explains why the expected way doesn't. I've done it before where I refractored a flow, thought the original developer was mad and rebuilt the "right way", only to find it didn't work. I then had to suffer the same pain as the original developer to get it working again.  &lt;/p&gt;

&lt;h2&gt;
  
  
  4. Design
&lt;/h2&gt;

&lt;p&gt;Design is the probably the most difficult to nail, as it's more of interition. But there are a couple of key call outs that good design should have to make the flow easy to read.&lt;/p&gt;

&lt;h3&gt;
  
  
  Keep It Short
&lt;/h3&gt;

&lt;p&gt;This is kind of obvious but often the most common not done. Keeping your flows short makes understanding your flow so much easier. And there are 2 main ways to do this.&lt;/p&gt;

&lt;p&gt;The obvious is to use less actions, and this can be done by:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Removing unnecessary actions like variables and composes&lt;/li&gt;
&lt;li&gt;Using right actions like filters instead of conditions&lt;/li&gt;
&lt;li&gt;Ordering your actions before and after branches&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The last one is probably the most under utilised but can add make a flow so much easier to understand.&lt;br&gt;
If you duplicate actions in branches it easy to think they could be very different paths, but if they are the same except for inputs, then moving to after the branch and using a coalesce() ensures everyone understands its the same.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5n79bgpd0xzx6s1trl4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj5n79bgpd0xzx6s1trl4.png" alt="move action"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The other way is to split the flow into childflows. That way we make the actions more relatable. Though this can only be done when the actions are related and/or complete a specific piece of value. This rolls in nicely to the next design principle...&lt;/p&gt;
&lt;h3&gt;
  
  
  Grouping Actions
&lt;/h3&gt;

&lt;p&gt;Actions that are directly related or complete a specific task should be grouped together. When you create your flow don't think of it as one flow full of actions, think of it as stages, and each stage should have actions. This design principle has 4 levels:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ensure related actions are next to each other&lt;/li&gt;
&lt;li&gt;Name the actions in a related way&lt;/li&gt;
&lt;li&gt;Add the actions into a scope&lt;/li&gt;
&lt;li&gt;Move the actions to a childflow&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The scope is the most common used but in my opinion should be the least used. It adds nesting (see later), and api calls, and in most cases naming in related way is just as good.&lt;/p&gt;
&lt;h3&gt;
  
  
  Simple Paths
&lt;/h3&gt;

&lt;p&gt;And this is the big one, you need to keep your paths simple, and the 2 biggest impacts to flow paths are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Branching&lt;/li&gt;
&lt;li&gt;Nesting&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Adding branches means that you are now trying to understand each decision on its own, losing focus on the overarching point of the flow. It also forces duplication of actions which again can mislead the developer in to thinking its differences are bigger.&lt;/p&gt;

&lt;p&gt;Nesting is similar, with how Power Automate is displayed it is easy to lose what level you are in and the impact of each of those containers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F458q421u52cxmhjuj3yh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F458q421u52cxmhjuj3yh.png" alt="high nesting"&gt;&lt;/a&gt;&lt;br&gt;
Understanding what each of those nesting boxes means and how it impacts values can be incredibly difficult.&lt;/p&gt;

&lt;p&gt;I strongly recommend you check out my previous blog about '&lt;a href="https://dev.to/wyattdave/power-automate-the-direct-methodology-32mf"&gt;The Direct Methodology&lt;/a&gt;' which deep dives into how the other benefits of simple paths and techniques to enable it.&lt;/p&gt;
&lt;h3&gt;
  
  
  Think Like a Human
&lt;/h3&gt;

&lt;p&gt;I see far to many flows that follow a very unnatural process path. I'm not saying you should copy the human process, but you need to follow the same logical steps a human would. My best example for this is handling 2 different outcomes in a loop.&lt;/p&gt;

&lt;p&gt;Nearly everyone would make a flow like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiybqk17o60gawjsea4f9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fiybqk17o60gawjsea4f9.png" alt="pass fail loop"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You loop over every interview form, if passed then send passed, if failed then send rejected. But is this how you would do it in real life? I suspect you would sort into 2 piles by pass and fail. Then work through the passed, then work through the failed.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxn83ez701yqgbg4j5nd3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxn83ez701yqgbg4j5nd3.png" alt="pass fail stack"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Easier to read ✅&lt;/li&gt;
&lt;li&gt;Easier to read logs (i can find nth passed so much easier) ✅&lt;/li&gt;
&lt;li&gt;Uses less api calls so maybe a ✅&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you make your process follow those human 'common sense' steps, then it is instinctively easier to understand.&lt;/p&gt;



&lt;p&gt;As you can see there are some simple steps that add little development time that can make your flows so much easier to read, and trust me, future you will be so happy when debugging a critical issue 😎&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=pa-red" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerautomate</category>
      <category>powerplatform</category>
      <category>lowcode</category>
      <category>rpa</category>
    </item>
    <item>
      <title>Power Platform - Dealing With Tech Debt</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 26 Jan 2026 07:01:21 +0000</pubDate>
      <link>https://dev.to/wyattdave/power-platform-dealing-with-tech-debt-1gim</link>
      <guid>https://dev.to/wyattdave/power-platform-dealing-with-tech-debt-1gim</guid>
      <description>&lt;p&gt;In my opinion, one of the biggest dangers to any Power Platform setup is technical debt.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Technical debt is the implied future cost of reworking software caused by choosing an easy, fast, or suboptimal solution today instead of a better, more robust approach. It acts like a financial loan; while it speeds up initial development, it accumulates "interest" in the form of harder maintenance, increased bugs, and slower future development. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Reading the above definition its easy to think that low-code tools like the Power Platform decrease the impact of technical debt, and that's kind of true:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;It's easy and fast, but robust&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;but the risk of tech debt in low-code tools is there, just in a different format&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The Risk&lt;/li&gt;
&lt;li&gt;How To Manage It&lt;/li&gt;
&lt;li&gt;Low-Code and AI&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. The Risk
&lt;/h2&gt;

&lt;p&gt;Low-Code technology builds on a foundation of re-use. Components are standardised, so custom code is minimalized and the risk of tech debt is drastically diminished. &lt;/p&gt;

&lt;p&gt;The problem is there are 2 sides to tech debt, code and implementation.&lt;/p&gt;

&lt;p&gt;Reading the code is one part of it, working through the choice of structure, functions, libraries etc, most of which is pre-created in the Power Platform.&lt;/p&gt;

&lt;p&gt;But then we have implementation, its the next level up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why use an action in a loop instead of a filter&lt;/li&gt;
&lt;li&gt;Why use a variable there&lt;/li&gt;
&lt;li&gt;Why chose a flow instead of in app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;and although implementation has less impact then code Low-code introduces 3 magnifiers:&lt;/p&gt;

&lt;h3&gt;
  
  
  Quantity
&lt;/h3&gt;

&lt;p&gt;What's great about the Power Platform is its free (excluding premium functionality) for E3 and F3 licenses, so it's available to almost everyone, and that means volume.&lt;/p&gt;

&lt;p&gt;Each flow or app maybe simple, and have minimum complexity, but the sheer number can break any CoE team. Just figuring out what something does takes effort, and dealing with so many diverse solutions can be tsunami.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxl7sz95ucb2bh1kzcy1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fqxl7sz95ucb2bh1kzcy1.png" alt="tsunami of apps"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Lifecycle
&lt;/h3&gt;

&lt;p&gt;This is the real kicker, Power Platform solutions generally start as personal or small scale, so there is no plan for the life of it. And in the life of every Power Platform solution you are going to have 2 potential big life events:&lt;/p&gt;

&lt;p&gt;Growth - adoption grows, new features are needed&lt;br&gt;
Ownership - the developer moves on&lt;/p&gt;

&lt;p&gt;Both mean implementation goes "wonky", as growth means building on top of something that wasn't planned to be built on (imagine a house with single story foundations having a second story added). And ownership changes often means that any updates are done in a totally different way. With design patterns/styles mashed together, making understanding even harder.&lt;/p&gt;
&lt;h3&gt;
  
  
  Engineering Mindset
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;An engineering mindset refers to the values, attitudes, and thinking skills associated with engineering. Engineers solve problems using systematic, iterative processes.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Low-Code allows people who don't have the time or opportunities to learn the deep technical knowledge to be a developer, and that's a massive pool of talent which makes Low-Code so valuable. But it also allows people who, without being rude, maybe shouldn't be developing. &lt;/p&gt;

&lt;p&gt;The engineering mindset is key to being a good developer, and generally that ensures a foundation of design decisions that allows others with the same mindset to gain a quicker understanding.&lt;/p&gt;

&lt;p&gt;So you will often find solutions that are even harder to understand, as although they solve the problem, it maybe in a very unique/unconventional way.&lt;/p&gt;

&lt;p&gt;As the risk is still there, what is the possible negative outcomes. If you don't manage technical debt then your Power Platform will run great for a couple of years or so, but in that time 2 things will happen:&lt;/p&gt;

&lt;p&gt;The solutions will become critical - roles taken on extra responsibility so can't handle the manual workload anymore. They also scale from personal/team to broader departments.&lt;/p&gt;

&lt;p&gt;The original developer moves away, they get promoted or leave the business. The solution gets handed over a couple of times, but each transition is to someone less interested and knowledge is lost.&lt;/p&gt;

&lt;p&gt;It starts off as one or two, but soon the CoE is undated, solutions that are too big to fail, with no team available to own it anymore, they are what we called orphaned.&lt;/p&gt;

&lt;p&gt;And now you are desperately trying to figure out how they work, the issues that were manually handled, and how to make them stable and scalable.&lt;/p&gt;

&lt;p&gt;And trust me when I say this, it will be a tsunami, and every solution you take on means less time to support new, often more critical, solutions being delivered.&lt;/p&gt;
&lt;h2&gt;
  
  
  2. How To Manage It
&lt;/h2&gt;

&lt;p&gt;As a CoE you need to get ahead of this risk, and ensure that there is no technical debt. As no matter how hard you try and how many agreements you have, that orphaned solution will keep going up the leadership pyramid and until there is someone high enough to override all your agreements.&lt;/p&gt;
&lt;h3&gt;
  
  
  Standard Operating Procedures (SOP)
&lt;/h3&gt;

&lt;p&gt;Every Power Platform CoE team should set up their standard operating procedures, these are the agreed way to do things. Often there are many different "right" ways to solve a problem, but to ensure easier understanding and less tech debt one right way should be agreed. This is your SOP, it should cover things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Naming Convention&lt;/li&gt;
&lt;li&gt;Design Styles&lt;/li&gt;
&lt;li&gt;Integrations/Connections&lt;/li&gt;
&lt;li&gt;Environment Variable design&lt;/li&gt;
&lt;li&gt;Solution Setup&lt;/li&gt;
&lt;li&gt;Access Management&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Having this documented ensures that every developer can start on the right path (if they decide too that is).&lt;/p&gt;
&lt;h3&gt;
  
  
  Training and Certification
&lt;/h3&gt;

&lt;p&gt;MS Learn is great, and has some fantastic modules, but it's not enough. YOu need you own foundation training process. It should cover the nuances of your setup, your SOP's, and broader governance. Ideally you will mix in some MS Learn modules (but be warned Microsoft loves to change them with new features that you may not have enabled, I got burnt by a rogue Power Automate Desktop module in middle of a Power Automate Cloud module).&lt;/p&gt;
&lt;h3&gt;
  
  
  Lock Down The Default
&lt;/h3&gt;

&lt;p&gt;Unfortunately Microsoft created the Default environment which means you can't easily get involved with the developer before they start building. But what you can do is limit the scope. The DLP policy should be very limited, only unblockable connectors, Dataverse should be moved to the non-business group so that it can't be used with anything else. No credits should be assigned and premium user licenses only given to makers who have completed training.&lt;/p&gt;

&lt;p&gt;If you are able to make in a managed environment then do it, limit app shares to max 5 and flows should not be shared with security groups.&lt;/p&gt;

&lt;p&gt;You should add what I call "Platform Flows", these are Power Automate flows that retrospectively fix issues that managed environments cant (and what you should use if you don't have managed environments). Examples I have include deleting Copilot Studio Agents and Agent Flows, and limit the number of flows a developer can have, any more they get turned off.&lt;/p&gt;
&lt;h3&gt;
  
  
  Automated Process to Prod
&lt;/h3&gt;

&lt;p&gt;Now you have limited the risk in Default you need a pipeline to scale, and I don't mean automated deployments. You need a process where developers can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Submit idea and CoE validate it (Intake Review)&lt;/li&gt;
&lt;li&gt;Arch &amp;amp; Security Review&lt;/li&gt;
&lt;li&gt;Review proposed design (Design and Impact Review)&lt;/li&gt;
&lt;li&gt;Review code to ensue meets Arch/Sec/Design suggestions and SOPs&lt;/li&gt;
&lt;li&gt;Document Solution&lt;/li&gt;
&lt;li&gt;User Acceptance test Solution&lt;/li&gt;
&lt;li&gt;Deploy to Prod (Separation of duty and change control)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1aolyki47ctqvj220sq4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F1aolyki47ctqvj220sq4.png" alt="full managed delivery process"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There are lots of out of box solutions for this, but you also have one of the most powerful development platforms at your disposal, so a custom app, automation, and database to handle this is at your fingertips.&lt;/p&gt;
&lt;h3&gt;
  
  
  Documentation
&lt;/h3&gt;

&lt;p&gt;Linked to the above and a necessary evil, but so important. Solutions need to be documented, the should include at least a Simple Design Doc and Simple Design Goal to help explain what the solution does. Additional information about NPROD environments, environment variables, and access is also key.&lt;/p&gt;
&lt;h3&gt;
  
  
  Monitoring
&lt;/h3&gt;

&lt;p&gt;The final thing we need to do is keep close eye on our platform (not that easy with the Power Platform), we should be looking for solutions that are scaling or growing beyond our controls. Identifying them early and moving them through the process is key, as no matter how good your setup, new unique scenarios will emerge.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97ixrdqz7w7daumgekif.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F97ixrdqz7w7daumgekif.png" alt="control pillars"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Low-Code and AI
&lt;/h2&gt;

&lt;p&gt;Now here is the big picture, AI tech debt is Low-Code on steroids. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You think the volume of Low-Code solutions is high, wait till developers make 10 apps/automations per day&lt;/li&gt;
&lt;li&gt;You think the volume of Low-Code developers is high, wait till there are 10x more developers&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then the real kicker, the foundation of reusable components that Low-Code is built on is gone, now layers of spaghetti code trained on non-quality controlled code.&lt;/p&gt;

&lt;p&gt;So the volumes are higher and the code harder to understand. And I know the expectation is that AI can fix tean create documentation, but:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;There will always be outline requirements/bugs that AI just can' solve&lt;/li&gt;
&lt;li&gt;AI lacks the understanding of the solution, so it's docs are always skin deep.&lt;/li&gt;
&lt;/ul&gt;



&lt;p&gt;Tech debt isn't a Pro-Code problem, it's not a Code problem, it's a development problem, everything developed creates tech debt, you just need to manage and mitigate it.&lt;/p&gt;



&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=pptechdebt" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerplatform</category>
      <category>powerapps</category>
      <category>powerautomate</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>Power Apps- Moving Away From Inline Code</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 12 Jan 2026 07:02:32 +0000</pubDate>
      <link>https://dev.to/wyattdave/power-apps-moving-away-from-inline-code-11ma</link>
      <guid>https://dev.to/wyattdave/power-apps-moving-away-from-inline-code-11ma</guid>
      <description>&lt;p&gt;Its the age old question, where do you put your code? Now I suspect you are saying never heard that question before, but it's a choice we actually make.&lt;/p&gt;

&lt;p&gt;Everyone knows the client and server choice, as we can run our code in the browser or get the server to do it and send it back through an api. But there is also a more fundamental choice, inline or block.&lt;/p&gt;

&lt;p&gt;See you can just add your JavaScript in the element, like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;button&lt;/span&gt; &lt;span class="nx"&gt;onclick&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;alert('Hello World')&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="nx"&gt;Click&lt;/span&gt; &lt;span class="nx"&gt;Me&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/button&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and I do occasionally see this, but the vast majority of JavaScript has now moved out of inline into consolidate blocks, either in a script tag *(for single page sites) or dedicated JS files:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;script&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;
  &lt;span class="nb"&gt;document&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getElementById&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;demo&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;innerHTML&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Hello World&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="sr"&gt;/script&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So the question we should be asking is why, and bigger question is should we do the same in Power Apps.&lt;/p&gt;

&lt;p&gt;In case you missed it Power Apps now has the app formulas properties, that can be used to run reusable code, they are called:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;User Defined Functions (UDF)&lt;/li&gt;
&lt;li&gt;Behaviour UDF's&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So let's dive in and explain each&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;When to use Inline&lt;/li&gt;
&lt;li&gt;UDF &amp;amp; Behaviour UDF's&lt;/li&gt;
&lt;li&gt;When to use UDF/UDS's&lt;/li&gt;
&lt;li&gt;Functions in Dataveres &amp;amp; Flows&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. When to use Inline
&lt;/h2&gt;

&lt;p&gt;We all know Inline, with each component having 2 main types of properties:&lt;br&gt;
&lt;strong&gt;Data&lt;/strong&gt; - characteristics of the component, like X/Y co-ordinates or font colour&lt;br&gt;
&lt;strong&gt;Event&lt;/strong&gt; - triggered code based on an interaction with the component, like OnClick or OnChange&lt;/p&gt;

&lt;p&gt;&lt;em&gt;There are also Function and Action, though these are for custom components or locked code so Im skipping them here&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Both Data and Event can run run Power FX code, like setting colour based on a condition or variable, or Patching a table on a OnClick. Code here has one main advantage, it's easy to understand as it is related directly to the component. I can quickly see that &lt;code&gt;If(vsText="Hello World",RGBA(189, 178, 176, 1),Color.Red)&lt;/code&gt; will set the fill depending on a  variable. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvybeavp8o1qchuuht2xo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvybeavp8o1qchuuht2xo.png" alt="colour variable"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;There is also the added advantage of being able to copy and paste the component between apps, as all of the code is self contained.&lt;/p&gt;

&lt;p&gt;But there are also trade offs, in particular:&lt;/p&gt;
&lt;h3&gt;
  
  
  Reviewing Code
&lt;/h3&gt;

&lt;p&gt;Trying to review the code of a Canvas App for either code reviews or debugging is painful when all of the code is inline. There is no one global view of all code, so you have to search and click throughout the app, only ever seeing a small snippet of the code. That advantage of being related to the component falls away when you are tracing interactions across components.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;FYI this was such a pain I created a Web App that extracts all of a apps code and displays in one document, check it out at &lt;a href="https://appreview-pro.dev" rel="noopener noreferrer"&gt;https://appreview-pro.dev&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Reusing the Code
&lt;/h3&gt;

&lt;p&gt;A fundamental to writing good code is to reuse your code, that way we our code base is smaller/easier to read, and we maintain code in one place (one version of the truth). With inline code that is simply not possible, so we have to duplicate code. &lt;/p&gt;

&lt;p&gt;A good example of this was a app I built a few years back that queried a SQL database, I had to call a custom connector in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;New Search&lt;/li&gt;
&lt;li&gt;Next Page&lt;/li&gt;
&lt;li&gt;Previous Page&lt;/li&gt;
&lt;li&gt;Jump to Page&lt;/li&gt;
&lt;li&gt;Filter&lt;/li&gt;
&lt;li&gt;Reset filter&lt;/li&gt;
&lt;li&gt;Sort&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each button used the same code but different inputs, but I had to copy and paste the code across all 7 buttons.&lt;/p&gt;

&lt;p&gt;So when should we use inline code, well I have 2 rules:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The Code will never be reused&lt;/li&gt;
&lt;li&gt;One action&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first one is self explanatory, but what about the second. Well its around the code complexity. If the code is doing one action, like logic or maybe a patch, then it can be inline, but if its patching, reseting, and updating, then it should be moved to Source (formulas parameter and called as a function).&lt;/p&gt;
&lt;h2&gt;
  
  
  2. UDF &amp;amp; Behaviour UDF's
&lt;/h2&gt;

&lt;p&gt;User Defined Functions are exactly what they say on the &lt;a href="https://www.youtube.com/watch?v=e7dx2Z9G7Mk" rel="noopener noreferrer"&gt;tin&lt;/a&gt;, they are custom functions that you create to run Power FX code. The difference between a standard UDF and a behaviour (not a fan of that name but Microsoft use it, I prefer User Defined Subroutine from my VBA days), are 3 fold:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scope&lt;/li&gt;
&lt;li&gt;Trigger&lt;/li&gt;
&lt;li&gt;Outputs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;UDF's are scoped to the function, meaning they can interact with variables and components. They are also declarative, which means that the system decides when it wants to recalculate it. Finally UDF's return a value, where as behaviour does not.&lt;/p&gt;

&lt;p&gt;Here's a simple example of a UDF&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AddOne(num:Number):Number=(
    num+1
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and heres a simple UDS, sorry i mean Behaviour UDF&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AddToVar(num:Number):Void ={
    Set(viNum,viNum+num)
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first returns the passed in value incremented by 1, the second increments a variable by the passed in value. &lt;/p&gt;

&lt;p&gt;You create both in the same way:&lt;/p&gt;

&lt;p&gt;App-Formulas&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhs6j4f3mrx55oz33heep.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fhs6j4f3mrx55oz33heep.png" alt="formula parameter"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But the structure is a little different, with UDF's using () and&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;functionName( inputName:inputType ) : OutputType (
&amp;lt;Your Code&amp;gt;
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;sorry I'm going to call the UDS now, and UDS using {}&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SubroutinenName( inputName:inputType ) : Void {
&amp;lt;Your Code&amp;gt;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But call out here, inputs are optional for both and there can be multiple&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AddTogether(num:Number,num2:Number):Number=(
    num+num2
);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AddOneToVar():Void ={
    Set(viNum,viNum+1)
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see although UDF's are super useful, they are not really going to change the way we code our apps, as the use case is relatively small. But UDS are much more useful as we can follow the path the Web Developers pioneered.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. When to use &lt;del&gt;UDF/&lt;/del&gt;UDS
&lt;/h2&gt;

&lt;p&gt;And this is my hot take, we really should be using UDS's a lot more, in fact looking at our 2 conditions when to use inline, means everything else should be moved to the formulas bar and called as a UDS.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyra0wvdpfvqagqdxdts.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fpyra0wvdpfvqagqdxdts.png" alt="code"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you plan to reuse the code, then it should be a UDS, if the event property is doing multiple Power FX functions, then it should be a UDS. Now like everything in life there are shades of grey, in particular for the last one, would this have to be moved?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UDS() : Void = {
    Patch(dummyData,{ID:1},{Title:"test1"});
    ResetForm(Form1);
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Its actioning multiple Power FX functions, but its only 2 lines of code. And this is where you decide, but for me to create a clear standard and to improve readability I would move it.&lt;/p&gt;

&lt;p&gt;But I have the following key caveats:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Naming must be good, I normally include the component name in it if its not reusable&lt;/li&gt;
&lt;li&gt;If it is reusable include which components use it in comments&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Functions in Dataveres &amp;amp; Flows
&lt;/h2&gt;

&lt;p&gt;Back at the start I also talked about client and server, so thought it would be good to also bring them into my decision matrix.&lt;/p&gt;

&lt;p&gt;Functions in Dataverse use Power FX, but they run on the server (I've done a lot more in-depth into these in a full blog here: &lt;a href="https://dev.to/wyattdave/instant-dataverse-functions-low-code-plug-ins-2l20"&gt;Instant Dataverse Functions &amp;amp; Low-Code Plug-ins&lt;/a&gt;). The main reason to use Functions in Dataverse is for reusability, as the code is behind a simple API url, so can be called from other apps, flows and even pro-code solutions. But even for those use cases you have to consider:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;At time of print its still very buggy and Microsoft's seems to have lost focus&lt;/li&gt;
&lt;li&gt;Requires Premium license&lt;/li&gt;
&lt;li&gt;Max run time is 2 minutes&lt;/li&gt;
&lt;li&gt;It is synchronous, so you have to wait for the function to finish&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So these would purely be used for those niche cases where the code needs to be run across multiple platforms.&lt;/p&gt;

&lt;p&gt;The other server side is calling a flow, this adds the complexity of another tech (not Power FX), but if we are honest every Power App Developer can use Power Automate. And the bigger issue, is its slow. &lt;/p&gt;

&lt;p&gt;But it has the benefits of being able to use more connectors, a non-user connection, and can be delegated, leaving the app to continue while the flow runs in the background.&lt;/p&gt;

&lt;p&gt;So the big use cases are normally long running jobs that I don't want to block the UI with.&lt;/p&gt;

&lt;p&gt;If you do want to know more I've done a blog already about it here &lt;a href="https://dev.to/wyattdave/power-apps-client-or-server-side-2kh1"&gt;Power Apps - Client or Server Side?&lt;/a&gt;, and an example of delegating to a flow here &lt;a href="https://dev.to/wyattdave/how-to-power-apps-getting-polling-update-from-file-upload-547g"&gt;How to - Power Apps Getting Polling Update from File Upload&lt;/a&gt;. &lt;/p&gt;




&lt;p&gt;So the hot take is, move your code to the block, away from inline. Now I know I will get a lot of push back on this (rightfully too), but I would say:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Its shades of grey, I'm not saying everything in block&lt;/li&gt;
&lt;li&gt;Change takes time, but when you get use to it&lt;/li&gt;
&lt;li&gt;Pro-Code is often the way to follow, as they have done all the learning for us&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=painline" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerapps</category>
      <category>powerplatform</category>
      <category>powerfx</category>
      <category>lowcode</category>
    </item>
    <item>
      <title>The Future of the Power Platform</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 15 Dec 2025 07:12:38 +0000</pubDate>
      <link>https://dev.to/wyattdave/the-future-of-the-power-platform-4ocj</link>
      <guid>https://dev.to/wyattdave/the-future-of-the-power-platform-4ocj</guid>
      <description>&lt;p&gt;I've read a lot, and written a little, about how AI Vibe Coding will impact low-code platforms like the Power Platform. It's quite clear where Microsoft wants it to go, as someone said "they want natural language to be the language of the platform". Microsoft are all in on this, because a natural language UI future:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is a world where they could lose their legacy dominance&lt;/li&gt;
&lt;li&gt;They can profit from the infrastructure needed&lt;/li&gt;
&lt;li&gt;It moves to the new cash flow model- PAYG&lt;/li&gt;
&lt;li&gt;It "in theory" opens up new users&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first one is the big one for them, they missed the mobile revolution and now they are full FOMO (fear Of Missing Out). At least mobile had limited impact on enterprises, but AI could create the first real break that encourages organisations to invest in a big infra move.&lt;/p&gt;

&lt;p&gt;Nvidia is a big winner, as in a gold rush don't dig for gold, sell shovels. And the infrastructure to use all those shovels/graphic cards are large data centers, and Microsoft with Azure has that. So they are in a good position to have the economies of scale to be cheaper and profit from competition (worked well for AWS).&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgpytyg0ezej0sw0cdtz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frgpytyg0ezej0sw0cdtz.png" alt="selling shovels"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When everyone moved to the cloud companies like Adobe figured out very quickly the peaks and troughs of sales through direct purchases could be replaced with steady dependable and often sticky cash flow with subscriptions. It feels that Microsoft has drained that cash cow now, there are no new licenses to sell, additionally they are no easy way to track ROI, making keeping existing licenses harder. Pay As You Go could be the answer, linking a ROI to direct consumption, now organisations are incentivised to spend more, as every dollar spent with Microsoft is 2 dollars saved.&lt;/p&gt;

&lt;p&gt;And the final one is that there is a whole new market. Currently Power Platform makers have to have a combination of skills and drive to create solutions. Now with AI abstracting away the skills more people can make solutions. I think this one is the weakest, because I would expect for every new user you will lose (or at least decrease the output) of a current maker.&lt;/p&gt;

&lt;p&gt;With this in mind we should always be taking what Microsoft says with a small pinch of salt, they need their AI offerings to be your future, even if they (in my opinion) don't quite live up to the hype.&lt;/p&gt;

&lt;p&gt;So we know Microsoft is going all in, so how will that impact the Power Platform, and what will it look like in a years time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00urb1eq6llkue55jzd5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F00urb1eq6llkue55jzd5.png" alt="power platform"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Years Time
&lt;/h2&gt;

&lt;p&gt;This one is controversial, but I suspect in a years time very little will have changed. There will many (many) new AI features, and although these will be talked about a lot, they will not have trickled down to large organisations.&lt;/p&gt;

&lt;p&gt;Large orgs are like oil tankers, they take miles to turn. All the new AI features will need to go through legal, governance, and most importantly security. Smaller agile companies will risk it, but large orgs with lots to lose wont.&lt;/p&gt;

&lt;p&gt;I would also expect a little swing back, more investment back in core features like PPAC and less forced on AI features (it's amazing how the threat from large paying customers can have on Microsoft).&lt;/p&gt;

&lt;p&gt;Don't forget in most cases these AI features are not solving a problem, they are improvements, and although organisations want that productivity boost to help their bottoms lines, they are happy to let someone else be the first adopter and take the risks.&lt;/p&gt;

&lt;h2&gt;
  
  
  After Next Year
&lt;/h2&gt;

&lt;p&gt;The truth is AI is not going away, it is the future, so the way we work will change.&lt;/p&gt;

&lt;p&gt;And this is where I think there are 2 possible paths we could end up down.&lt;/p&gt;

&lt;h3&gt;
  
  
  Path One - Microsoft's Happy Path
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fhxufypgvfootx9i3h4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F5fhxufypgvfootx9i3h4.png" alt="microsoft sunny skys"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The AI tools start delivering what was promised, the following key things happen:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vibe coding delivers robust solutions&lt;/li&gt;
&lt;li&gt;LLM token costs drop significantly&lt;/li&gt;
&lt;li&gt;Users switch from visual to text base UI&lt;/li&gt;
&lt;li&gt;Security gets ahead in the arms race&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now Power Apps looks very different, Canvas Apps are still here, but now you start with a prompt, and after a few rounds of prompting the app is available to be updated in the UI. That's right, prompting will get you so far very quickly but th 80/20 rule strikes, and the last 20% is so much easier to do in the UI with a simple click/drag/type (My favourite example of this is car production lines, robots will do most of the work but there will always be a human on the production line to do the fiddly bits).&lt;/p&gt;

&lt;p&gt;Flows will leverage the simplicity of prompts to create automations, but then gain the core requirement of deterministic outcomes. If you put a and b in, you always get c out.&lt;/p&gt;

&lt;p&gt;Copilot Studio will be just like Power Apps, vibe coded. So you start with prompts and it creates all of the topics and connections. Again the UI will come at the end so you can do the last 20% targeted.&lt;/p&gt;

&lt;p&gt;Power Pages is the interesting one, as its in a very difficult situation with Power Apps taking on React. So my guess would be that they unify Power Apps and Power Pages (going full circle back to Power Apps Portal). The developer builds the same and then at point of deployment decides if its external or internal.&lt;/p&gt;

&lt;p&gt;Dataverse won't change much, its benefits are not just UI deep so I can see still being the AI database of choice.&lt;/p&gt;

&lt;p&gt;Dataverse Low-Code plugins will disappear, and I vibe coded version of standard plugins will be created (Im kind excited by this, as the terrible buggy nature of Low-Code plugins ruined the opportunity).&lt;/p&gt;

&lt;p&gt;Although AI has taken over the platform, there are still a plethora of legacy apps and flows, all of which continue to run, generating value, (as if its not broken why fix it).&lt;/p&gt;

&lt;h3&gt;
  
  
  Path Two - Microsoft's Unhappy Path
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujaaccsjkyvemao3qfqe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fujaaccsjkyvemao3qfqe.png" alt="microsoft grey clouds"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you saw in the happy path, ther 4 key requirements are not easy. So I could quite easily see&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Vibe coding still delivers spaghetti and unreadable solutions&lt;/li&gt;
&lt;li&gt;The continued investment in larger LLM models means token costs staginate/rise&lt;/li&gt;
&lt;li&gt;Users push back and want to stay visual&lt;/li&gt;
&lt;li&gt;Prompt injections are not beaten and new vulnerabilities are discovered&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this world organisations simply don't pay for the AI features. They go the other way, forcing them off. The current crop of Low-Code tools deliver all the value they need, and security win the PR war with the senior leaders.&lt;/p&gt;

&lt;p&gt;Microsoft is stuck as its invested heavily and needs to double down or pivot. They pivot, splitting all the AI features out into their own area.&lt;/p&gt;

&lt;p&gt;Power Apps keeps the visual UI with a little bit of AI on the side. Special AI components and/or a way to use AI to create PCF components. Deep down I suspect this will happen even on the happy path, as vibe coding as a premise isn't right for organisations. They need understanding and stability, nothing of scale has ever been made vibe coding (well maybe &lt;a href="https://fly.pieter.com" rel="noopener noreferrer"&gt;fly.peter.com&lt;/a&gt; is an exception lol). The real value is AI assisted development, where the developer already has the skills and supervisors the AI, AI a tool not a delegation. &lt;/p&gt;

&lt;p&gt;Power Automate doesn't change, the sprinkle of AI stays in certain connectors like now. The truth is Power Automate built on the very established Logic Apps, for me it's kind of at peak evolution (especially when inline UI launched properly, hurry up Microsoft).&lt;/p&gt;

&lt;p&gt;Copilot Studio leaves the Power Platform going on to join M365 Copilot and other Agents that are designed to compete with the og Office suite. &lt;/p&gt;

&lt;p&gt;Power Pages becomes the vibe coded part of the platform. It takes on the React code instead of Canvas Apps, but the code is visible and editable. It becomes more of the Low-Code to Pro-Code bridge, not used by citizen developers, just accelerating pro devs.&lt;/p&gt;

&lt;p&gt;Dataverse starts appearing more and more outside of the Power Platform.&lt;/p&gt;

&lt;p&gt;Dataverse Low-Code plugins start to work 😎&lt;/p&gt;

&lt;p&gt;The current tools all get a blast of investment, all those features put on hold suddenly start being delivered. &lt;/p&gt;

&lt;p&gt;Microsoft is also ironically in a good position, as even though they invested heavily in AI, so did their competition. And they are able to fallback om existing venue streams to steady the ship.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Take Away
&lt;/h2&gt;

&lt;p&gt;Although AI is the future, the future is not tomorrow, and no one knows exactly what the future looks like. It could be everything, or it could be a niche, it could be the new Smartphone or the new Blockchain. &lt;/p&gt;

&lt;p&gt;Either way the Power Platform will still be here, bigger and better, and for me that's super exciting 😎&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=pp-future" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerplatform</category>
      <category>powerapps</category>
      <category>powerautomate</category>
      <category>copilotstudio</category>
    </item>
    <item>
      <title>Fixing Power Platform Pipelines</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 01 Dec 2025 07:19:22 +0000</pubDate>
      <link>https://dev.to/wyattdave/fixing-power-platform-pipelines-4b0o</link>
      <guid>https://dev.to/wyattdave/fixing-power-platform-pipelines-4b0o</guid>
      <description>&lt;p&gt;Although Microsoft really didn't plan (or probably want you to) most organisations understood the benefits of application lifecycles and instigated a Dev / Test / Prod environment strategy.&lt;/p&gt;

&lt;p&gt;With all of the benefits unfortunately came a big negative, and that is the overhead of deploying solutions.&lt;/p&gt;

&lt;p&gt;This lead the the launch of Power Platform pipelines, but back to the first sentence, this was implemented quite right. And that's because a big part of lifecycle management includes segregation of duty, ago the developer should not have access to test or prod. The standard pipeline requires that the developer has full maker access to test and prod, which in the real world leads to developers editing in prod.&lt;/p&gt;

&lt;p&gt;Microsoft again listened and released delegated deployments, using either a application account (SPN) or a normal but non-human account (Service Account). But again there were issues:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;SPN Issues&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Requires the developer who creates the pipeline to own the SPN in Azure, not good security practice&lt;/li&gt;
&lt;li&gt;Uses the developers connections, so although they don't have access to test/prod environment, they have access to test/prod data&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Service Account&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cant deploy connectors (yep you heard me, only solutions with no connections!)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Luckily there is a workaround to the issues, to get Power Platform Pipelines fit for use.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Design&lt;/li&gt;
&lt;li&gt;Implementation&lt;/li&gt;
&lt;li&gt;Flows&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. Design
&lt;/h2&gt;

&lt;p&gt;The workaround works on 3 key facts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Delegated Service Accounts can create their own connections&lt;/li&gt;
&lt;li&gt;SPNs can have connections shared with them&lt;/li&gt;
&lt;li&gt;Solutions have a config json included&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So the workaround is a little bit of hot potato, with the connections being passed around.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mxkngr6nkoiyffghnvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0mxkngr6nkoiyffghnvc.png" alt="design"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First we update the config json with the Service Accounts connections&lt;/li&gt;
&lt;li&gt;The Pipeline then deploys using the Service Accounts connections&lt;/li&gt;
&lt;li&gt;After deployment the SPN swaps the connections (and the components) to the new owner&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  2. Implementation
&lt;/h2&gt;

&lt;p&gt;Unfortunately then implementation is a little more complex, as we need to have some prior setup and extra admin.&lt;/p&gt;

&lt;h3&gt;
  
  
  Extra Setup
&lt;/h3&gt;

&lt;p&gt;What's great about the pipeline is it allows you to create the connection in the target environment when you trigger the run. But that can't be done if not using the developers connections, so we have to set them up before.&lt;/p&gt;

&lt;p&gt;In every target environment we need to create all possible connections that the Service Account could use.&lt;br&gt;
Additionally we have to setup the solutions new owners connections, and share them with the SPN.&lt;/p&gt;
&lt;h3&gt;
  
  
  Extra Admin
&lt;/h3&gt;

&lt;p&gt;As we have add extra complexity we need a way to administer this, and the key data we need is:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Solution&lt;/li&gt;
&lt;li&gt;New Owning Service Account&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;as without that data we wont know which account to change to after import.&lt;/p&gt;

&lt;p&gt;The easy way is to create a Dataverse table and Model Driven app (I call it the Pipeline Register), and while we are doing all that work we might as well add in some useful data like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Approval&lt;/li&gt;
&lt;li&gt;Documentation Link&lt;/li&gt;
&lt;li&gt;Change Number&lt;/li&gt;
&lt;li&gt;Developer team (so we can share read only access)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And once all that is done we end up with something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5zu9aicq4tv5nk9h3mz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fu5zu9aicq4tv5nk9h3mz.png" alt="full design"&gt;&lt;/a&gt;&lt;br&gt;
&lt;em&gt;Better resolution version &lt;a href="https://powerdevbox.com/subs/PipelineV2.pdf" rel="noopener noreferrer"&gt;here&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  3. Flows
&lt;/h2&gt;

&lt;p&gt;Power Platform Pipelines have a very important feature, &lt;a href="https://learn.microsoft.com/en-us/power-platform/alm/extend-pipelines" rel="noopener noreferrer"&gt;Gated Extensions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjz2oyaby37jo6swhdv42.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjz2oyaby37jo6swhdv42.png" alt="gated extensions"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So we going to leverage these gates to run flows to action our required updates.&lt;/p&gt;
&lt;h3&gt;
  
  
  OnApprovalStarted
&lt;/h3&gt;

&lt;p&gt;These flow will create the Solution config json file which will update the connection references to use the delegated deployment service account.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;First we get the deployment stage run details
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx7teae75gflhv181cmfe.png" alt="run stage info"&gt;
&lt;/li&gt;
&lt;li&gt;Next we parse the json config from the table (&lt;code&gt;@{outputs('Get_a_row_by_ID')?['body/deploymentsettingsjson']}&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Then we need to find the connections for the Service Account in the target environment using Get Connections as Admin and filtering&lt;/li&gt;
&lt;li&gt;Then from the parse we loop over each connection reference and find the exact connection in the target environment
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;and(
  contains(item()?['id']
,
  split(items('For_each')?['ConnectorId'],'/apis/')[1])
,
  equals(
    item()?['properties/displayName']
  ,
    parameters('Pipeline-DelegatedAccount (ia_PipelineDelegatedAccount)')
  )
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt; Next is to set the property of a holding array variable to the new connection reference
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;setProperty(
  items('For_each')
,
  'ConnectionId'
, 
  body('Filter_array_connections')[0]?['name']
)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;Finally we update the deployment stage run detail item will found at the beginning
&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0li8b4wsurqhngat9a4m.png" alt="update run item"&gt;
&lt;em&gt;We get the environment variables from the parse JSON so not to wipe them&lt;/em&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry2hmwq2jrpnnwslalqz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fry2hmwq2jrpnnwslalqz.png" alt="full flow"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As this is also prior to import this is where I would add additional checks and approvals:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Is it in the Pipeline Register&lt;/li&gt;
&lt;li&gt;If its to prod is it approved&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  OnDeploymentCompleted
&lt;/h3&gt;

&lt;p&gt;After the solution is imported we need to change everything over from the delegated service account to the owning account.&lt;/p&gt;

&lt;p&gt;The 2 key steps are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Changing connections - I've done a deep dive how to here: &lt;a href="https://dev.to/wyattdave/power-automate-how-to-change-connection-owners-oid"&gt;Power Automate - How to Change Connection Owners&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Changing component owner - again deep dive already done here: &lt;a href="https://dev.to/wyattdave/automating-changing-solution-owner-155p"&gt;Automating Changing Solution Owner in the Power Platform&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You must do it in above order as the new owner must have access to the connection used&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;And like pre approval there are other actions you can take:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Share any flows with dev team&lt;/li&gt;
&lt;li&gt;Back up solution to external repository&lt;/li&gt;
&lt;li&gt;Share App url's&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyg4bvygqdqmshbimgema.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fyg4bvygqdqmshbimgema.png" alt="process"&gt;&lt;/a&gt;&lt;/p&gt;



&lt;p&gt;As you can see there is definitely added complexity, especially around pre setting up connections. I tried the Power Automate Management action, &lt;a href="https://learn.microsoft.com/en-gb/connectors/flowmanagement/#create-connection" rel="noopener noreferrer"&gt;Create Connection&lt;/a&gt; but always get errors. The other option is our trust Power Automate Desktop to do it through the UI, but I really wish there was some sort of credential bank for admins to manage them.&lt;/p&gt;

&lt;p&gt;But if your org follows good practice like true separation of duty and application lifecycle management, then you can at least now use the inbuild Pipelines.&lt;/p&gt;



&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=ppPipel" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerplatform</category>
      <category>powerautomate</category>
      <category>powerapps</category>
      <category>copilotstudio</category>
    </item>
    <item>
      <title>Dev.to Tag Hacking</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 24 Nov 2025 11:44:52 +0000</pubDate>
      <link>https://dev.to/wyattdave/devto-tag-hacking-2ogf</link>
      <guid>https://dev.to/wyattdave/devto-tag-hacking-2ogf</guid>
      <description>&lt;p&gt;I was digging around some of my old blogs recently and spotted something interesting, well not interesting, but unexplained.&lt;/p&gt;

&lt;p&gt;I blog about the Power Platform, a lot, and one of the things I don't blog about is crypto, so I was surprised to see that a few on my blogs had these tags:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;#crypto&lt;/li&gt;
&lt;li&gt;#cryptocurrency&lt;/li&gt;
&lt;li&gt;#bitcoin&lt;/li&gt;
&lt;li&gt;#offers&lt;/li&gt;
&lt;li&gt;#web3&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Yep it looks like someone hacked my tags, most likely in conjunction with spam comments to push something dodgy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54t68apw5rsxm5k1b5ko.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F54t68apw5rsxm5k1b5ko.png" alt="hacked tags" width="800" height="609"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I wanted a quick way to check all of my blogs and fix any, and luckily there is a API for that.&lt;/p&gt;

&lt;p&gt;As Dev.to is built on &lt;a href="https://forem.com/" rel="noopener noreferrer"&gt;Forem&lt;/a&gt; it has a robust and open api (No known rate limits and auth only for personal permissions like creating a blog). The docs are great as well,  &lt;a href="https://developers.forem.com/api/" rel="noopener noreferrer"&gt;https://developers.forem.com/api/&lt;/a&gt;, so it's easy to use.&lt;/p&gt;

&lt;p&gt;I used the &lt;code&gt;https://dev.to/api/articles?username=&lt;/code&gt; endpoint, with an increased page size using &lt;code&gt;?per_page=1000&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/api/articles?username=wyatt&amp;amp;per_page=1000"&gt;https://dev.to/api/articles?username=wyatt&amp;amp;per_page=1000&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This returned the following info per blog:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"type_of"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"article"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2997601&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"title"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Vibe Coding a Power App the Pro way with Code Apps"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"In a world of new AI tools and rebranding its hard to keep track of everything Microsoft has..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"readable_publish_date"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Nov 17"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"slug"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"vibe-coding-a-power-app-the-pro-way-with-code-apps-56dk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"path"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"/wyattdave/vibe-coding-a-power-app-the-pro-way-with-code-apps-56dk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://dev.to/wyattdave/vibe-coding-a-power-app-the-pro-way-with-code-apps-56dk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"comments_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"public_reactions_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"collection_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;19972&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"published_timestamp"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-17T06:56:28Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"language"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"en"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"subforem_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"positive_reactions_count"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;20&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"cover_image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://media2.dev.to/dynamic/image/width=1000,height=420,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgris6a1itt7aydpnzsl3.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"social_image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://media2.dev.to/dynamic/image/width=1000,height=500,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fgris6a1itt7aydpnzsl3.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"canonical_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://dev.to/wyattdave/vibe-coding-a-power-app-the-pro-way-with-code-apps-56dk"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"created_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-06T10:59:19Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"edited_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-17T06:58:56Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"crossposted_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;null&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"published_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-17T06:56:28Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"last_comment_at"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2025-11-17T06:56:28Z"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"reading_time_minutes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"tag_list"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"powerapps"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"powerplatform"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"vibecoding"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="s2"&gt;"lowcode"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"tags"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"powerapps, powerplatform, vibecoding, lowcode"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="nl"&gt;"user"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"david wyatt"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wyattdave"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"twitter_username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wyattDaveDev"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"github_username"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"wyattdave"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"user_id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;653003&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"website_url"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://powerdevbox.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"profile_image"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://media2.dev.to/dynamic/image/width=640,height=640,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F653003%2Ff6da9df7-019e-4189-ab7f-c5c527fe1db6.png"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
            &lt;/span&gt;&lt;span class="nl"&gt;"profile_image_90"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F653003%2Ff6da9df7-019e-4189-ab7f-c5c527fe1db6.png"&lt;/span&gt;&lt;span class="w"&gt;
        &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So it was relatively easy to throw together a quick site that listed all of my tags from the tag key in the response, and create quick links to them so I can fix them.&lt;/p&gt;

&lt;p&gt;The site shows counts of all tags with quick links to a table with the blogs using that tag.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xktgvvhy3f55gzv127k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0xktgvvhy3f55gzv127k.png" alt="Top Tags" width="800" height="444"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazcbuca4cgxiqvt1o1un.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fazcbuca4cgxiqvt1o1un.png" alt="sites with tags" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I also chucked in some extra fluff, like a csv download and a couple of charts provided by my favourite chart library &lt;a href="https://www.chartjs.org/" rel="noopener noreferrer"&gt;chart.js&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5h1j3amo80wqv8utaqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw5h1j3amo80wqv8utaqp.png" alt="charts" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So if you want a quick way to check for any hacked tags or just to see what you blog about the most (and maybe spot a typo or 2 🤦‍♂️) you can try the site here: &lt;a href="https://powerdevbox.com/subs/devto" rel="noopener noreferrer"&gt;https://powerdevbox.com/subs/devto&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;You can also throw on a author parameter for quick loading: &lt;a href="https://powerdevbox.com/subs/devto?author=wyattdave" rel="noopener noreferrer"&gt;https://powerdevbox.com/subs/devto?author=wyattdave&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've also raised the issue with dev.to support, but the constant battle against spammers is no easy task.&lt;/p&gt;

</description>
      <category>devto</category>
      <category>watercooler</category>
      <category>security</category>
      <category>writing</category>
    </item>
    <item>
      <title>Vibe Coding a Power App the Pro way with Code Apps</title>
      <dc:creator>david wyatt</dc:creator>
      <pubDate>Mon, 17 Nov 2025 06:56:28 +0000</pubDate>
      <link>https://dev.to/wyattdave/vibe-coding-a-power-app-the-pro-way-with-code-apps-56dk</link>
      <guid>https://dev.to/wyattdave/vibe-coding-a-power-app-the-pro-way-with-code-apps-56dk</guid>
      <description>&lt;p&gt;In a world of new AI tools and rebranding its hard to keep track of everything Microsoft has launched, but there is one kind of cool one that never got as much attention as I think it should and with the influx of new it probably wont.&lt;/p&gt;

&lt;p&gt;We are all talking about App Builder, and Generative Pages in Model Driven Apps, but there are also Code Apps.&lt;/p&gt;

&lt;p&gt;Code Apps only launched a few months ago, pitched as a way for Pro-Developers to build full React Apps in the Power Platform. But in my humble opinion that wasn't what they were created for, they were actually created so that the current crop of vibe coding tools could be used in the Power Platform.&lt;/p&gt;

&lt;p&gt;I'm not a React developer so I won't talk about actually building in React, so I will talk about:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What They Are&lt;/li&gt;
&lt;li&gt;Basic Setup&lt;/li&gt;
&lt;li&gt;Vibe Coding Experience&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  1. What They Are
&lt;/h2&gt;

&lt;p&gt;Canvas apps take config files generated by the maker studio and compile them into a web app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75yfh4hzcjvnefqsztb2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F75yfh4hzcjvnefqsztb2.png" alt="pcf"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So looking at the process Microsoft had 2 options where to insert AI, at the beginning, generating the maker studio inputs, or the second replacing the rendering engine. The latter had the benefit of using any web library, and the most popular being React, which was so prevalent all the existing models were good at creating.&lt;/p&gt;

&lt;p&gt;So this meant a new process, something like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frknessf3vo28tdvmgzhq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frknessf3vo28tdvmgzhq.png" alt="react"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And that's what Code Apps are, they are apps with a different build process. As you can see the value USP of Canvas Apps is PCF rendering engine that allows Low-Code inputs, and although the environment is a big USP, it's nothing without those inputs. I can't see many React developers wanting to build in the Power Platform just for the environment, but I can imagine Low-Code developers wanting to vibe code a React app with the benefits of the environment.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Basic Setup
&lt;/h2&gt;

&lt;p&gt;As always Microsoft learn provides some great documentation on how to setup everything up (&lt;a href="https://learn.microsoft.com/en-us/power-apps/developer/code-apps/overview" rel="noopener noreferrer"&gt;https://learn.microsoft.com/en-us/power-apps/developer/code-apps/overview&lt;/a&gt;), but the headline prerequisites are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Code App environment setting turned on&lt;/li&gt;
&lt;li&gt;A code editor like VS Code&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/power-platform/developer/cli/introduction?tabs=windows" rel="noopener noreferrer"&gt;Power Platform CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://nodejs.org/en" rel="noopener noreferrer"&gt;Node.js&lt;/a&gt; - make sure you have an up to date version&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Git is recommended but you can always download the zip file from GitHub.&lt;/p&gt;

&lt;p&gt;Once everything is setup and you have download/cloned a template app (I recommend the &lt;a href="https://learn.microsoft.com/en-us/power-apps/developer/code-apps/quickstart" rel="noopener noreferrer"&gt;Hello World App&lt;/a&gt; as the from Scratch kept having build errors for me), you need to use the CLI to sign into the Power Platform.&lt;/p&gt;

&lt;p&gt;Like I said the docs provided by Microsoft a great so I don't want to duplicate for the sake of it, but in a nutshell you:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Sign into an environment &lt;/li&gt;
&lt;li&gt;Install/update libraries&lt;/li&gt;
&lt;li&gt;Initialise app &lt;/li&gt;
&lt;li&gt;Build the app&lt;/li&gt;
&lt;li&gt;Deploy the app&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;You can also build and run a local version of the app, though I often found this more pain then its worth&lt;/em&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Install/update libraries
&lt;/h3&gt;

&lt;p&gt;Most of the web is now built on libraries and dependencies, that way you do not need to build functionality from scratch, you can use what others have made. The package.json file lists all of the libraries and is used to install them (the package-lock.json file is also used but this is to stop newer versions being installed so that you don't need to worry about regression testing etc). These libraries are stored in the node_modules file.&lt;/p&gt;

&lt;h3&gt;
  
  
  Initialise app
&lt;/h3&gt;

&lt;p&gt;This adds the additional information need specifically for Power Apps. It creates the power.config.json file, which includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Appid&lt;/li&gt;
&lt;li&gt;Display Name&lt;/li&gt;
&lt;li&gt;Description&lt;/li&gt;
&lt;li&gt;Environment&lt;/li&gt;
&lt;li&gt;Icon/logo&lt;/li&gt;
&lt;li&gt;Connection References&lt;/li&gt;
&lt;li&gt;Data References&lt;/li&gt;
&lt;li&gt;Environment Variables&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The CLI will create most of these but you can update at anytime, and some are not done in the CLI like icon and description.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build the app
&lt;/h3&gt;

&lt;p&gt;As you saw in the top diagram, React is not an end product, but a developer tool. So React is used to create standard HTML/JavaScript/CSS that your web browser can use. To turn your React into HTML/JavaScript/CSS we use a build tool, in this case Vite. Running the build will use Vite to convert all of the TypeScript and JSX into simple HTML/JavaScript/CSS.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy the app
&lt;/h3&gt;

&lt;p&gt;The CLI will now deploy the HTML/JavaScript/CSS files that were created in the dist folder. After the app will appear in the environment ready to use. Note that there is version control but remember that the React code is not stored in the Power Platform, so if you do rollback, the code you are editing in VS Code etc will not rollback (I would highly recommend using a repo like GitHub and creating a pull request for every deployment to the Power Platform).&lt;/p&gt;

&lt;p&gt;And that's it you now can deploy your code app to the Power Platform.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp96c86emxzcuddzyh07u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp96c86emxzcuddzyh07u.png" alt="app in solution"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Connections
&lt;/h3&gt;

&lt;p&gt;We all know Power Apps have no power without connections, and the good news is Code Apps have that power. There are 3 types of connections, &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Standard (&lt;a href="https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/connect-to-data" rel="noopener noreferrer"&gt;data&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/connect-to-dataverse" rel="noopener noreferrer"&gt;Dataverse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/power-apps/developer/code-apps/how-to/connect-to-azure-sql" rel="noopener noreferrer"&gt;SQL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again the documentation is great and gives a simple step by step guide to add the connections. For standard connections you use one of your connections (just need connection type and connection id) to create the connection, but it doesn't actual use your connection but still uses the App users when they log in (same for Dataverse, so security roles will still be needed).&lt;/p&gt;

&lt;p&gt;The CLI updates the power.config.json with the connection and creates some TypeScript files (src/models for schemas and src/service for functions).&lt;/p&gt;

&lt;p&gt;You can then use the connections in a very similar way to within a normal Canva App&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;me&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;Office365UsersService&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nc"&gt;MyProfile_V2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;id,displayName,userPrincipalName&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Vibe Coding Experience
&lt;/h2&gt;

&lt;p&gt;As I said, I don't think many React developers will use Code Apps, but vibe coders maybe, so how was the vibe coding experience.&lt;/p&gt;

&lt;p&gt;Well my idea was to build a Agile Planning Poker App. I am fortunate enough to have paid for GitHub Copilot license that I used, I tried both claude 4.5 Sonnet and ChatGPT 5 and found the latter the best for me. The below is my prompt I used:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Objective:
Transform the existing Power App into a fully functional Agile Planning Poker application with a modern, minimalistic UI. Ensure all data is stored in the Dataverse table cr69a_planningpoker.

Functional Requirements
1. Welcome Screen (On Load):
- Display a welcome message and the user's profile image.
- Provide two options:
- Join an existing session (via input field).
- Create a new session (auto-generate a GUID).
- On session creation, navigate to the Round Screen.
- If new session the user should have the sessionOwner field set to true in the dataverse table
2. Round Screen Behaviour:
- Automatically add the current user to the round.
- Display all active participants to every user in the session.
3. Scoring Mechanism:
- Each participant selects a score by clicking a card.
- Reveal scores when:
- All users have submitted their score, or
- The session creator clicks Complete.
- Show: Each user's score and the most popular score.
4. Round Management:
- Include a Start New Round button that only the session owner can see (use sessionOwner field).
- Retain the same users across rounds.
- Reset users only when a new session is created.
- Indicate when other users have submitted score to all users but do not show score
- Show scores to all users when round finished
- If a new user joins they should join the latest round

 Data &amp;amp; Storage
- Use Dataverse table: wd_planningpoker for all session and round data.

 Design Guidelines
- Apply a modern, minimalistic theme.
- Avoid clutter; favor negative space and clean geometric elements.

 Cleanup Instructions
- Remove all Vite template boilerplate from the codebase.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And this was the result:&lt;/p&gt;

&lt;p&gt;Welcome Screen&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwg87gl3e2dj7gw3pip2p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwg87gl3e2dj7gw3pip2p.png" alt="welcome Screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Round Screen&lt;br&gt;
&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykoiwlj4jlz89aujfk25.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fykoiwlj4jlz89aujfk25.png" alt="round screen"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Well that's not entirely true, it took a few extra prompts (about 20), and they were for these issues like this:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Wanted the UI to be centered horizontal and vertical&lt;/li&gt;
&lt;li&gt;The polling didn't work so other users didn't see when round finished&lt;/li&gt;
&lt;li&gt;Often duplicated users in round&lt;/li&gt;
&lt;li&gt;Change popular score to average&lt;/li&gt;
&lt;li&gt;Make UI more modern and professional&lt;/li&gt;
&lt;li&gt;Expand Join a session card so input box does not overflow&lt;/li&gt;
&lt;li&gt;Make round card and point select card same size&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see I never did get the UI centered and I wouldn't call it modern and professional, and most took a couple of attempts.&lt;/p&gt;

&lt;p&gt;I also spotted that the polling to check was using a batch api call, but the batch was just one api call, so not sure if Copilot is being super clever and smarter than me, or over engineering.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;--batch_23479c3e-a81b-4e2e-88cb-4444444444
Content-Type: application/http
Content-Transfer-Encoding: binary

GET cr69a_planningpokers?$select=wd_round&amp;amp;$filter=wd_session+eq+%27e0e9f042-4444-4444-a440-a5f362c33013%27&amp;amp;$top=500 HTTP/1.1
Accept: application/json
Prefer: odata.maxpagesize=500,odata.include-annotations=*

--batch_23479c3e-a81b-4e2e-88cb-4444444444--

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;In the end my demo app was super simple and I was able to get it working with a few prompts, although not exactly how I wanted. The beauty of Code Apps is obvious, React, and the breadth of training material available for LLM's. As new models become available I see them getting better and better, and once you figure out I see them becoming so much better then Generative Pages and App Builder, I just hope Microsoft doesn't give up on them because of that complex setup. &lt;/p&gt;

&lt;p&gt;I also hope they open it up to more then just React, and I did the vibe code approach because I'm not a React developer, and that's not as enjoyable as doing some of it yourself.&lt;/p&gt;

&lt;p&gt; &lt;br&gt;
&lt;a href="https://powerdevbox.com/blogs/subscribe?tracker=pa-code" class="crayons-btn crayons-btn--primary" rel="noopener noreferrer"&gt;😎 Subscribe to David Wyatt&lt;/a&gt;
&lt;/p&gt;

</description>
      <category>powerapps</category>
      <category>powerplatform</category>
      <category>vibecoding</category>
      <category>lowcode</category>
    </item>
  </channel>
</rss>
