🧠 The Paradigm Shift: Why We Don’t Argue UI Anymore
There was a time (you remember it) when any client request that drifted outside the "blessed" Power Apps patterns triggered a long conversation about platform constraints. We tried to reshape requirements, push standard controls, and hope stakeholders would accept a slightly clunky interaction with the UI in the name of long-term maintainability.
That era is over.
With AI-assisted development (hello my dear friend, GitHub Copilot), it’s now faster and safer to build small, targeted customizations—PCFs or React WebResources—than to litigate UX.
You can ship exactly what the client envisions, document it properly, and make it maintainable long-term. The payoff is huge: better UX → higher adoption → stronger platform stickiness. In other words, great UI is not a "nice-to-have"—it’s a retention strategy.
When you replace “discuss why we can’t” with “deliver what delights,” you:
- Earn trust faster
- Accelerate sign-off
Anchor the customer to the platform with experiences they love
But there’s a catch…
🧱 The Problem: A Dozen PCFs/WebResources = Disk Space Meltdown
React-based PCFs and WebResources lean on Node’s ecosystem. And Node’s ecosystem leans on… node_modules—the folder that eats hard drives for breakfast.
Every project carries its own dependency tree. Multiply that across 8, 12, 20 PCFs/WebResources… and your laptop screams. It’s common to see hundreds of thousands of files and tens (or hundreds) of GB consumed across projects.
Good news: there’s a clean, robust solution that many Power Platform devs underuse:
🧩 The Hidden Gem: NPM Workspaces
NPM Workspaces let you manage multiple packages/projects (PCFs/WebResources) under one repository, sharing a single top-level node_modules whenever possible. This dramatically reduces duplication and makes dependency management more predictable and CI-friendly.
What you get:
- ✅ One central
node_modules(plus small per-package shims when needed) - ✅ Shared tooling (TypeScript config, lint rules, build scripts)
- ✅ Shared local packages (@types/xrm, @fluentui/react-components) used across PCFs/WRs via workspace:
- ✅ Unified scripts (build, test, lint) across all packages
- ✅ Faster CI with a single dependency tree and cache
🤔 How Does It Works?
It's quite straightforward. All you need is to define a package.json and a package-lock.json files at the root of your project folder, just above the folders containing PCFs and WebResources. This will make your project folder a monorepo.
📂 my-monorepo/
├─ 📄 package.json <-- workspace root
├─ 📄 package-lock.json
│
├─ 📂 Pcf/
│ ├─ 📂 pcf1/
│ │ ├─ 📄 package.json
│ │ └─ ...
│ └─ 📂 pcf2/
│ ├─ 📄 package.json
│ └─ ...
│
└─ 📂 WebResources/
├─ 📂 webresource1/
│ ├─ 📄 package.json
│ └─ ...
└─ 📂 webresource2/
├─ 📄 package.json
└─ ...
It is important that the root package.json file contains the following:
{
"name": "my-monorepo",
"private": true,
"workspaces": [
"Pcf/*",
"WebResources/*",
]
}
You can do it manually, or via:
cd my-monorepo
npm init -y
npm pkg set private=true
npm pkg set workspaces[0]="Pcf/*"
npm pkg set workspaces[1]="WebResources/*"
Then you can create your PCFs into the PCF and WebResources folder as usual... Just a tip: remember that the value of the name node of the package.json files under each of your PCFs/WRs must be unique, otherwise you'll get an error while running npm <whatever>.
When you'll run
npm install
All dependencies will be installed in a single, above all, node_modules folder created just under the my-monorepo folder.
NOTE: If two packages need different versions of the same dep, npm may place some deps locally. That’s fine; you’ll still save tons of space overall.
🗂️ A Practical Folder Structure for Power Platform Projects
Here’s a realistic example of the output folder you'll get, on a standard Power App project:
📂 project-folder
├─ 📄 .gitignore
├─ 📂 src
│ ├─ 📄 package.json
│ ├─ 📄 package-lock.json
│ ├─ 📂 node_modules
│ ├─ 📂 Pcf
│ │ ├─ 📂 NumericInputControl
│ │ │ ├─ 📄 package.json
│ │ │ ├─ 📄 package-lock.json
│ │ │ └─ ...
│ │ ├─ 📂 PurchaseOrderGrid
│ │ │ ├─ 📄 package.json
│ │ │ ├─ 📄 package-lock.json
│ │ │ └─ ...
│ │ └─ 📂 CustomTreeView
│ │ ├─ 📄 package.json
│ │ ├─ 📄 package-lock.json
│ │ └─ ...
│ └─ 📂 WebResources
│ ├─ 📂 HomePage
│ │ ├─ 📄 package.json
│ │ ├─ 📄 package-lock.json
│ │ └─ ...
│ └─ 📂 ControlDashboard
│ ├─ 📄 package.json
│ ├─ 📄 package-lock.json
│ └─ ...
└─ 📂 test
└─ ... # other stuff
📉 How Much Space Do You Actually Save?
In Power Platform solutions with 8–20 React packages, we’ve seen:
60–80% reduction in duplicated dependency files
Build times drop (less overall I/O and fewer cold installs)
Your mileage varies with library choices, but the direction is always the same: less bloat, more flow.
🪄 Conclusions
AI copilot tools make building custom, crisp UX easy. NPM Workspaces make maintaining many customizations sane. Put them together and you’ve got a Power Platform development lifecycle that’s fast, clean, and—dare I say—fun.
Give it a try, and let me know in the comments what you think about it!