<?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: Przemysław Kujda</title>
    <description>The latest articles on DEV Community by Przemysław Kujda (@przemq99).</description>
    <link>https://dev.to/przemq99</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4032091%2F9ea4f491-56e1-4ebf-8b6a-5f1cb60bb72c.jpg</url>
      <title>DEV Community: Przemysław Kujda</title>
      <link>https://dev.to/przemq99</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/przemq99"/>
    <language>en</language>
    <item>
      <title>Fabric Apps: Row-Level Security — The Silent Hero</title>
      <dc:creator>Przemysław Kujda</dc:creator>
      <pubDate>Tue, 21 Jul 2026 20:55:23 +0000</pubDate>
      <link>https://dev.to/przemq99/fabric-apps-row-level-security-the-silent-hero-5b1p</link>
      <guid>https://dev.to/przemq99/fabric-apps-row-level-security-the-silent-hero-5b1p</guid>
      <description>&lt;h1&gt;
  
  
  Row-Level Security: The Silent Hero of Fabric Apps
&lt;/h1&gt;

&lt;p&gt;In my &lt;a href="https://dev.to/przemq99/what-microsoft-fabric-apps-unlocked-for-me-and-why-i-am-writing-about-it-4nge"&gt;first article&lt;/a&gt;, I walked through the "hybrid architecture" for Fabric Apps: a custom React frontend layered on top of native Semantic Models and Power BI visuals, with an AI assistant added on top. The response was great, but it surfaced the one question every enterprise architect asks the moment they see a slick demo: &lt;em&gt;"Okay, but is it secure?"&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;Here's the uncomfortable truth: a beautiful React dashboard is worthless if it fails a security audit. You can nail every animation, every micro-interaction, every pixel, and still get shut down in week one of a compliance review because a regional sales rep can query global revenue numbers.&lt;/p&gt;

&lt;p&gt;This is where Row-Level Security (RLS) comes in. It doesn't get a keynote slot, it doesn't trend on social media, but it's the thing that actually makes a Fabric App enterprise-ready. Let's talk about why.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Nightmare of Custom Web App Security (The "Old Way")
&lt;/h2&gt;

&lt;p&gt;If you've ever built a custom analytics app from scratch (Node backend, React frontend, some flavor of SQL warehouse), you know the drill. Security isn't a feature, it's a project unto itself:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;You build a user-mapping table that ties application logins to business dimensions (region, department, cost center).&lt;/li&gt;
&lt;li&gt;You write middleware that intercepts every query and injects a &lt;code&gt;WHERE&lt;/code&gt; clause based on that mapping.&lt;/li&gt;
&lt;li&gt;You maintain a token/session layer that has to stay perfectly in sync with your identity provider.&lt;/li&gt;
&lt;li&gt;You duplicate this filtering logic in every downstream service that touches the data: API, exports, scheduled jobs, the AI chatbot someone added in month six.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The real risk isn't that this is hard to build once. It's that it's hard to keep &lt;em&gt;consistent&lt;/em&gt;. Every time someone adds a new endpoint or a new report, they have to remember to re-implement the filter. Miss one spot (a debug endpoint, a CSV export, a cached query) and you've got a data leak. Security logic that lives in application code is security logic that will drift from the source of truth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Fabric App Paradigm Shift (Entra ID &amp;amp; Semantic Models)
&lt;/h2&gt;

&lt;p&gt;Fabric Apps flip this model entirely. Instead of building authorization from scratch, you inherit it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Identity is native.&lt;/strong&gt; The app runs inside the Microsoft ecosystem, so every user is already a known identity in Microsoft Entra ID. No shadow user table, no custom login flow to maintain.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The frontend stays dumb (on purpose).&lt;/strong&gt; The React layer doesn't carry any filtering logic. It simply passes the authenticated user's context along when it queries the Semantic Model via Fabric REST APIs, or hits a Lakehouse SQL endpoint directly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The engine does the enforcing.&lt;/strong&gt; RLS rules defined once in the Semantic Model are applied server-side, before a single row of data leaves Fabric. The frontend never sees data it isn't entitled to, so there's nothing to accidentally expose.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This gives you what I'd call "one version of the truth, one version of security." The same RLS rule that governs a native Power BI report also governs your custom React dashboard, your export job, and your AI assistant. No duplication, no drift.&lt;/p&gt;

&lt;p&gt;A conceptual look at what this means on the frontend. Note there's no filtering logic here, just identity propagation:&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="c1"&gt;// Conceptual: querying a Semantic Model via Fabric REST API&lt;/span&gt;
&lt;span class="c1"&gt;// In a real React app, you'd get the userToken via @azure/msal-react&lt;/span&gt;
&lt;span class="c1"&gt;// The frontend never constructs a WHERE clause, it just forwards identity.&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;queryModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;daxQuery&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userToken&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&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;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://api.fabric.microsoft.com/v1/workspaces/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;workspaceId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/semanticModels/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;modelId&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/query`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="na"&gt;method&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;POST&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
      &lt;span class="na"&gt;headers&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Entra ID token identifies the user to the engine.&lt;/span&gt;
        &lt;span class="c1"&gt;// RLS is resolved server-side based on this identity.&lt;/span&gt;
        &lt;span class="na"&gt;Authorization&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`Bearer &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;userToken&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="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;Content-Type&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;application/json&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="na"&gt;body&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;JSON&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;stringify&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;query&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;daxQuery&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="c1"&gt;// Whatever comes back is ALREADY row-level filtered.&lt;/span&gt;
  &lt;span class="c1"&gt;// The React component just renders it.&lt;/span&gt;
  &lt;span class="k"&gt;return&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Compare that to the "old way" snippet you'd write for a custom backend: a &lt;code&gt;buildFilterClause(user.region, user.department)&lt;/code&gt; helper that you'd have to call in every single query path. That function simply doesn't exist here. It can't drift because it was never duplicated in the first place.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Is a Game-Changer for AI Copilots
&lt;/h2&gt;

&lt;p&gt;This matters even more once you bring an AI assistant into the picture, which, if you followed the first article, you already have.&lt;/p&gt;

&lt;p&gt;Text-to-SQL and natural-language Q&amp;amp;A features are notoriously risky from a security standpoint. An LLM doesn't inherently know that "show me the highest-paid employee" should be scoped to the analyst's own department. If your AI layer talks directly to raw tables and then summarizes whatever comes back, you've built a very articulate data leak.&lt;/p&gt;

&lt;p&gt;With native RLS, the sequencing changes completely:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;The AI assistant sends a query (or a generated DAX/SQL statement) to the Semantic Model on behalf of the authenticated user.&lt;/li&gt;
&lt;li&gt;The Fabric engine applies RLS first, filtering the result set down to only what that user is entitled to see.&lt;/li&gt;
&lt;li&gt;Only the already-filtered, already-safe aggregate is handed to the LLM (Gemini, OpenAI, whatever you're using) for summarization into natural language.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The LLM never touches unfiltered data. It can't leak the CEO's salary to a curious analyst because it never received it in the first place. The security boundary sits below the AI layer, not inside a prompt or a system message you're hoping the model respects. That's a structurally stronger guarantee than anything you'd get from prompt engineering alone.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion &amp;amp; Call to Action
&lt;/h2&gt;

&lt;p&gt;Put together, this is the real pitch for Fabric Apps: you get to spend your engineering time on product UX (animations, interactions, the AI assistant, the things that make an app feel good to use) without reinventing authorization, and without praying that every query path respects the same filtering rule.&lt;/p&gt;

&lt;p&gt;The frontend stays thin. The security model stays centralized. And your audit conversation gets a lot shorter.&lt;/p&gt;

&lt;p&gt;I'd love to hear how the community is handling this in other embedded or custom-app scenarios. Are you relying on native RLS, or still bridging gaps with custom middleware? Drop your approach in the comments.&lt;/p&gt;

&lt;p&gt;Code for this series (evolving as I go): &lt;a href="https://github.com/przemq99/first-fabric-app" rel="noopener noreferrer"&gt;https://github.com/przemq99/first-fabric-app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>react</category>
      <category>security</category>
    </item>
    <item>
      <title>What Microsoft Fabric Apps unlocked for me (and why I am writing about it)</title>
      <dc:creator>Przemysław Kujda</dc:creator>
      <pubDate>Thu, 16 Jul 2026 13:05:30 +0000</pubDate>
      <link>https://dev.to/przemq99/what-microsoft-fabric-apps-unlocked-for-me-and-why-i-am-writing-about-it-4nge</link>
      <guid>https://dev.to/przemq99/what-microsoft-fabric-apps-unlocked-for-me-and-why-i-am-writing-about-it-4nge</guid>
      <description>&lt;p&gt;The latest wave of Microsoft Fabric updates made a strong impression on me. Not because of another feature checkbox on a roadmap, but because it became clear that Fabric is no longer "just" a platform for warehouses, pipelines, and notebooks.&lt;/p&gt;

&lt;p&gt;It is becoming a place where you can ship &lt;strong&gt;real analytical applications&lt;/strong&gt; that feel like products, not only reports.&lt;br&gt;
That realization is why I decided to write this article, and why I started building my first &lt;strong&gt;Fabric App&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is still an early version of the work. I am learning the surface area of Fabric Apps as I go, and I am sure that with deeper exploration we will be able to build even stronger solutions. Even at this stage, though, the pattern already feels powerful enough to share.&lt;/p&gt;


&lt;h2&gt;
  
  
  What Fabric Apps give us
&lt;/h2&gt;

&lt;p&gt;For a long time, if you wanted a custom analytics experience (not only Power BI pages, but also your own UI, navigation, workflows, and AI copilots), you often ended up designing a full-stack product:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;frontend&lt;/li&gt;
&lt;li&gt;backend&lt;/li&gt;
&lt;li&gt;authentication&lt;/li&gt;
&lt;li&gt;APIs&lt;/li&gt;
&lt;li&gt;hosting&lt;/li&gt;
&lt;li&gt;permission plumbing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That path still works. It is also heavy.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Fabric Apps change the trade-off.&lt;/strong&gt;&lt;br&gt;
Because the experience lives on Fabric and can talk to your &lt;strong&gt;semantic model&lt;/strong&gt; (and other Fabric capabilities) through the platform, you can focus much more on the &lt;strong&gt;frontend layer&lt;/strong&gt;: the product surface your users actually touch. You do not need to reinvent an entire backend just to answer a business question.&lt;/p&gt;

&lt;p&gt;In practice, that means:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;one shared &lt;strong&gt;semantic model&lt;/strong&gt; as the source of truth&lt;/li&gt;
&lt;li&gt;the ability to combine &lt;strong&gt;native Power BI visuals&lt;/strong&gt; with &lt;strong&gt;custom React interfaces&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;room for UX patterns that classic report pages do not express well: guided navigation, AI chat, storytelling, interactive showcases&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This feels less like "publishing a report" and more like delivering a product: one connected experience, built on a single source of truth, tailored to the business case.&lt;/p&gt;


&lt;h2&gt;
  
  
  Why this matters for reporting
&lt;/h2&gt;

&lt;p&gt;To make that concrete, here is how I think about the split:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Situation&lt;/th&gt;
&lt;th&gt;Recommended surface&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Existing Power BI report already works well&lt;/td&gt;
&lt;td&gt;Embed native report inside the app&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Users need guided navigation or onboarding&lt;/td&gt;
&lt;td&gt;Build a custom React page&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AI Q&amp;amp;A or conversational interface&lt;/td&gt;
&lt;td&gt;Custom page with semantic model queries&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Operational briefing for non-analyst users&lt;/td&gt;
&lt;td&gt;Custom page with curated KPIs&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Ad-hoc exploration by analysts&lt;/td&gt;
&lt;td&gt;Native Power BI report&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The interesting part is the mix:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;where Power BI is already excellent → &lt;strong&gt;embed the native report&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;where the experience needs to feel more like a product → &lt;strong&gt;build a custom page&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;and everywhere → keep both sides connected to the &lt;strong&gt;same semantic model&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Depending on the business case, you choose the right surface, without splitting the truth across multiple disconnected systems.&lt;br&gt;
That is what excited me most: Fabric Apps make this hybrid model feel natural.&lt;/p&gt;


&lt;h2&gt;
  
  
  What I built (first version)
&lt;/h2&gt;

&lt;p&gt;I built a multi-page Fabric App around a Sales &amp;amp; Logistics semantic model.&lt;br&gt;
Below is a walkthrough of the modules. I will keep this high-level for now. If useful, I can go deeper on specific capabilities in follow-up posts.&lt;/p&gt;
&lt;h3&gt;
  
  
  1) Home: the entry point
&lt;/h3&gt;

&lt;p&gt;A launchpad that introduces the experience and routes users into each module.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fin9okzuu2ew951syshxf.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fin9okzuu2ew951syshxf.png" alt=" " width="800" height="379"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  2) Custom Dashboard: live semantic-model analytics
&lt;/h3&gt;

&lt;p&gt;A custom React dashboard that queries the Fabric semantic model directly:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;KPI cards&lt;/li&gt;
&lt;li&gt;monthly trends&lt;/li&gt;
&lt;li&gt;customer ranking with cross-filtering&lt;/li&gt;
&lt;li&gt;logistics views&lt;/li&gt;
&lt;li&gt;CSV export&lt;/li&gt;
&lt;li&gt;auto-generated "quick insights"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzpxkfsr1a1m3y6f2pa4b.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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fzpxkfsr1a1m3y6f2pa4b.png" alt=" " width="800" height="382"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnksta1b5elzsa2jqt6uo.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fnksta1b5elzsa2jqt6uo.gif" alt=" " width="719" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the hand-built product UI side of Fabric Apps — a custom React layer querying the semantic model directly via the Fabric REST API, but sharing the same business logic as the native reports. No duplicated measures, no separate data source.&lt;/p&gt;

&lt;p&gt;Implementation note: querying the semantic model&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;result&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;getFabricClient&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;semanticModel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;model&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="nf"&gt;query&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;dax&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="na"&gt;bypassCache&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;KPIs and charts are driven by live queries against the Fabric semantic model.&lt;/p&gt;




&lt;h3&gt;
  
  
  3) Native Power BI Reports: chromeless Power BI inside the app
&lt;/h3&gt;

&lt;p&gt;A native Power BI report embedded inside the app (without the usual chrome), with page selection for the pages we want users to see.&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0vma7pqex9dz3qzmiccn.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0vma7pqex9dz3qzmiccn.gif" alt=" " width="759" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This shows the complementary pattern: keep strong Power BI work where it already shines, and deliver it inside the same app shell.&lt;/p&gt;




&lt;h3&gt;
  
  
  4) AI Assistant: questions against real numbers
&lt;/h3&gt;

&lt;p&gt;An AI analyst that answers questions about KPIs and trends using results computed from the semantic model.&lt;br&gt;
It also adapts to the language of the question (English or Polish).&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ihaecsa7ljc70dz7gyy.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F9ihaecsa7ljc70dz7gyy.gif" alt=" " width="759" height="359"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;One design choice that shaped the whole assistant: the AI does not freely generate DAX for every question.&lt;/p&gt;

&lt;p&gt;The pattern I used instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A set of pre-defined, safe queries covers the core KPIs and trends&lt;/li&gt;
&lt;li&gt;The language model receives the computed results (not raw data) and interprets them in natural language&lt;/li&gt;
&lt;li&gt;Only for questions outside that scope does the assistant fall back to a templated response&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why does this matter? Letting an LLM generate arbitrary DAX looks impressive in a demo and breaks in production. Computed metrics first, language last — that order makes the assistant actually usable outside a controlled environment.&lt;/p&gt;

&lt;p&gt;Implementation note: keeping AI grounded in real numbers&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;metrics&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;fetchCoreMetrics&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;generateGeminiText&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;userPrompt&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;buildPrompt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;question&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;metrics&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;Safe queries first, language model only for the answer.&lt;/p&gt;




&lt;h3&gt;
  
  
  5) Product Showcase and Visual Lab: what custom UX can feel like
&lt;/h3&gt;

&lt;p&gt;Two showcase pages focused on interaction and visualization (mock data on purpose):&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;product drill-down panels&lt;/li&gt;
&lt;li&gt;animated charts&lt;/li&gt;
&lt;li&gt;KPI rings&lt;/li&gt;
&lt;li&gt;heatmaps&lt;/li&gt;
&lt;li&gt;other custom visuals&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftjov1x17qbv2epz3cnmf.gif" 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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Ftjov1x17qbv2epz3cnmf.gif" alt=" " width="719" height="340"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;These pages are a proof of concept for one idea: the UI ceiling in Fabric Apps is much higher than in classic Power BI. Animated charts, KPI rings, drill-down panels — all of it is standard React, which means you are not limited to what the Power BI visual marketplace offers.&lt;/p&gt;




&lt;h2&gt;
  
  
  A note on tools (and Cursor)
&lt;/h2&gt;

&lt;p&gt;Even with React experience, building this kind of app still involves a lot of moving parts:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;layout and navigation&lt;/li&gt;
&lt;li&gt;embedding and tokens&lt;/li&gt;
&lt;li&gt;semantic-model querying&lt;/li&gt;
&lt;li&gt;UX polish&lt;/li&gt;
&lt;li&gt;iteration speed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Cursor made a huge difference.&lt;/strong&gt;&lt;br&gt;
From shaping the report layout and page structure to implementing features and debugging edge cases, it significantly accelerated the work.&lt;br&gt;
The areas where it helped most: scaffolding the React component structure, debugging token and embedding errors, and iterating on layout without losing context across files.&lt;br&gt;
For me, it is not a replacement for understanding the stack — it is a force multiplier, especially when the platform itself is still evolving fast.&lt;/p&gt;




&lt;h2&gt;
  
  
  This is only the beginning
&lt;/h2&gt;

&lt;p&gt;Everything above is a &lt;strong&gt;first version&lt;/strong&gt;. The more I dig into Fabric Apps, the clearer it becomes that this is a foundation for richer solutions — still with the same core idea: &lt;strong&gt;frontend-first delivery on top of Fabric&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;This is still an early build. The next post will go deeper on one specific capability — most likely the semantic model querying pattern from the React side.&lt;br&gt;
If you are exploring Fabric Apps, Power BI embedding, or AI copilots on top of a semantic model — drop a comment. I would love to hear what you are building.&lt;/p&gt;

&lt;p&gt;💻 GitHub repository: &lt;a href="https://github.com/przemq99/first-fabric-app" rel="noopener noreferrer"&gt;https://github.com/przemq99/first-fabric-app&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microsoftfabric</category>
      <category>powerbi</category>
      <category>react</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
