This is the third post in my "My Open-Source Projects" series, where I go through some of the OSS projects I started or maintain and tell you the story behind them. First up was AngleSharp, then MAGES. This time: Piral, a framework for micro frontends - and the first project in this series that came out of a client engagement rather than a plane ride or a game studio's grant.
What Is Piral, Actually?
Piral lets you build a frontend application as a stable app shell that gets extended at runtime by independently developed, independently deployed modules called pilets. A pilet ships its own code and assets, can register pages, extend other pilets' extension points, and can be built, tested, and released completely on its own team's schedule - without anyone needing to touch or even redeploy the shell.
If that sounds like "micro frontends," that's because it is. Piral was one of the earlier dedicated frameworks in that space, built specifically around the idea that a single main framework (usually React) drives the shell, while individual pilets are free to bring something else entirely if they need to - Vue, Angular, even something short-lived and purpose-built. The shell doesn't care. It only cares about the contract.
I've written a more detailed technical introduction to the concepts before, if you want the deep dive: Introduction to Microfrontends with Piral. This post is more about where it came from and how it's grown.
Where It Actually Started: A German Energy Company, Then ZEISS
Piral wasn't born as "let's make a framework." It was born as "let's actually ship this customer portal, for real this time."
I'd just come off a large rewrite of the smart-home portal for a large German energy company, where a micro-service-backed, loosely-coupled-frontend approach worked far better than anyone expected. The backend teams had already gone the micro-services route for their own reasons - scaling, ownership, independent release cycles - and it seemed almost wasteful to let all of that independence evaporate the moment it hit the frontend, where everything got welded back together into one shared codebase anyway. So we didn't. Multiple teams could ship independently without stepping on each other - which, if you've ever worked on a large frontend monolith with a dozen teams committing to the same App.tsx, is not a sentence you get to say often.
Then I became the main architect for a new digital customer portal at ZEISS - a large German company that had, by that point, tried and failed to pull off exactly this kind of portal for years. Not for lack of trying, and not for lack of good engineers - it's the kind of project that accumulates false starts simply because "let many teams contribute to one coherent customer-facing app" is a genuinely hard organizational and technical problem, and prior attempts had all run into the same wall: a single frontend codebase that every team had to touch, coordinate around, and eventually avoid touching at all costs.
I noticed the parallels to what had just worked at the RWE SmartHome project and leaned into the same approach: micro-service backends paired with what we'd now call micro frontends, even though nobody was calling it that yet - the term hadn't really entered common usage. It worked. Multiple teams contributing at what genuinely felt like the speed of thought, instead of the speed of "please rebase your branch against the shared frontend repo again, and also here's a merge conflict in a file six people touched this week."
At that point the obvious question was: why keep reinventing this per client? Why not generalize the approach into an actual framework?
Naming It (And Accidentally Foreshadowing Something)
I joined smapiot in February 2019, and the direction was clear from day one: alongside the regular consulting work, there'd be dedicated time to build a framework for micro frontends. By March 2019 we'd settled on a name: Piral, short for "Portals that can go viral." A year later, the "viral" part of that name aged in a way absolutely nobody could have planned for. We still bring it up.
We officially revealed Piral at the O'Reilly Software Architecture Conference Berlin in November 2019. In hindsight, that conference turned out to be the last one O'Reilly ran in that series - it never picked back up after COVID hit, at least as far as I know. So Piral's public debut happened at what turned out to be the end of an era for that particular conference. The response at the time, though, was genuinely great - people wanted to try it immediately, which is not always guaranteed when you show up with "yet another frontend framework" at a software architecture conference. We'd braced ourselves for the usual round of "how is this different from an iframe" questions, and got a refreshing number of "can we pilot this next quarter" ones instead.
Here's the whole arc at a glance, from that first month at smapiot to where things stand now:
Seven years is a long time for a framework built around one client project's success to still be actively developed, still picking up new adopters, and still running its own annual conference. None of that was guaranteed back in that Berlin conference room in 2019. A couple of things worth calling out about the timeline itself: the gaps are real - not every quarter had a headline-worthy event, and I'd rather show honest quiet stretches than pad the axis with filler. And two of the dates lined up in a way I didn't plan: Piral's v1.0 release and the very first Micro Frontends Conference both landed in June 2023, on the same day, which made for a genuinely good excuse for a celebration.
A few of those milestones are worth a beat of their own. The Feed Service has its own steady release cadence running quietly alongside the framework - 1.0.0 in October 2021, 1.17.0 four years later. Piral.Blazor turned into a small ecosystem of its own, from v3 in September 2022 to a dedicated server-side variant targeting .NET 8 in February 2024. And native Module Federation support landing in Piral 1.4.0 (December 2023) was a quiet but important one - it meant Piral could sit alongside, rather than only compete with, one of the other major approaches to shipping micro frontends.
Worth calling out explicitly: the "hundreds of pilets in one app" scaling story isn't something Piral grew into over these seven years - it was a design goal from the very first version, informed directly by watching what broke at scale in that original ZEISS-style setup. What's changed since 2019 isn't the ceiling; it's how many production systems are actually pushing against it.
Not Just Theory: Real Adoption, Including Outside Piral Itself
The consulting projects that followed proved the concept held up outside of ZEISS's specific context, which is always the real test for something that started as "a good idea from one project." It's one thing to make an architecture work when you're the one who designed it and you're in the room for every decision. It's another to hand it to a different team, on a different project, with different constraints, and watch it hold up anyway. Piral did.
What surprised me more, though, was interest from teams that weren't using Piral at all. Larger projects already built on Single-SPA started reaching out for help getting Piral's loosely-coupled integration patterns into their existing workflows. They didn't want to migrate away from code that already worked - nobody sane wants a rewrite of a production system that's doing its job - but they wanted the ideas behind Piral (the decoupling model, the independent deployability, the way pilets could be updated and rolled out without a full redeploy) layered onto the micro frontend setup they already had. In practice, that meant bringing over specific mechanisms - things like our approach to shared dependencies, or the update/rollout model - without asking anyone to throw away months or years of Single-SPA work.
That's a good sign for any architecture: when people want to borrow your patterns even while keeping their own stack. It's a much stronger signal than stars or downloads, because it means the ideas are portable even when the code isn't.
An Ecosystem, Not Just a Library
From the start, Piral was meant to be more than "install a package, get a framework." Different pieces of tooling were deliberately built as their own generic, reusable things - not tightly bolted to Piral internals. That's a design choice, not an accident: a debugging tool that only understands Piral-specific concepts is a much smaller investment than one built around general primitives that Piral happens to use too, but the latter is far more likely to survive the framework's own evolution - and far more useful to anyone standing outside the Piral world entirely.
The clearest example is the Piral Inspector, a browser DevTools extension for inspecting and debugging a running Piral instance - which pilets are loaded, what routes are registered, what dependencies are shared, toggling settings like state-container logging, and even loading new pilets on the fly from a root module URL, a feed URL, or a tarball for quick local testing. It's built with an adapter pattern specifically so its core debugging plumbing (a background script talking to a content script talking to a devtools panel - the standard shape for any browser extension that needs to inspect a page) isn't locked to Piral-only scenarios. It ships for Firefox, Chrome, Opera, and Edge, which is more browser coverage than most internal dev tools ever bother with, and it's a genuinely small, focused codebase - the kind of tool you can actually read end to end in an afternoon if you're curious how it talks to a running app.
Beyond that, the ecosystem includes:
- A VS Code extension for authoring pilets and app shells with proper tooling support instead of raw text editing and hope.
- A templating system (via the CLI) to scaffold a new pilet or a whole new app shell in seconds, rather than copy-pasting a previous project and deleting things until it works.
- The Piral Cloud Feed Service - the commercial piece that ties it all together.
The Feed Service: The Giant Everything Stands On (But Isn't Required)
The Piral Cloud Feed Service is, in practice, the thing that makes rolling out and updating micro frontends at scale actually pleasant - it's how pilets get discovered, versioned, and delivered to app shells without anyone manually wiring up a deployment pipeline per team. Push a new pilet version, the feed picks it up, connected app shells get the update - no rebuild of the shell, no coordinated release train, no waiting for the next sprint's deployment window.
Here's the part I think matters most, philosophically: the Piral framework has no hard dependency on the Feed Service. We built it that way on purpose, from day one, even though it would have been the easier (and more commercially convenient) choice to couple them tightly. How you distribute and update your pilets is entirely up to you - and even if you decide a discovery/delivery service is the right call (it usually is, once you have more than a couple of teams shipping independently), it doesn't have to be ours. Any micro frontend discovery mechanism can plug into the same contract, because the contract itself is just "here's a list of pilets and where to fetch them" - deliberately unglamorous, deliberately not locked to one vendor.
Do I think the Piral Cloud Feed Service is the best option out there? Yes, obviously - I'm somewhat biased, having helped build it, and I've seen what it looks like when teams try to roll their own version of the same thing from scratch. But that's a big enough topic for its own article rather than a paragraph here. If you want to explore it yourself: the landing page has the overview, portal.piral.cloud is where you log into the free community tier, and the licensed version runs fully on-premise for anyone who needs that - a common requirement once you're talking to companies with strict data-residency rules.
Getting a Feel for It
Scaffolding a new app shell:
npx piral new my-shell
cd my-shell
npm start
And a new pilet that plugs into it:
npx pilet new --source my-shell
cd my-pilet
npm start
Inside a pilet, registering a page looks like this:
import { PiletApi } from 'my-shell';
export function setup(piral: PiletApi) {
piral.registerPage('/hello', () => <div>Hello from a pilet!</div>);
}
That's genuinely most of it for a minimal case. The PiletApi surface is where the interesting extensibility lives - registering pages, extension slots, shared state, notifications, menu items, and more, all without the shell needing to know a given pilet exists ahead of time.
Where It Shines
- Loose coupling as a first-class citizen, not an afterthought. Pilets are isolated by design - built, versioned, tested, and deployed independently. A broken pilet release doesn't take down the shell or other pilets, and a team can ship a hotfix to their one pilet at 4pm on a Friday without needing sign-off from anyone outside their own team.
- It genuinely scales to a lot of micro frontends. This is the one I'd highlight hardest: Single-SPA-style setups tend to get uncomfortable somewhere around 10 micro frontends, and Module Federation setups can typically stretch to 30-40 depending on how deep the sub-module graph gets before the shared-dependency graph turns into its own puzzle to manage. Piral is, as far as I'm aware, the only micro frontend framework built to comfortably scale into the hundreds of pilets in a single application - which matters a great deal once you're not talking about a handful of teams anymore, but dozens.
- Framework-agnostic at the pilet level. React drives most shells, but a pilet can be Vue, Angular, or something else entirely - useful for legacy migration paths (rewrite one piece at a time instead of a big-bang cutover) or short-lived experiments that shouldn't need to match the shell's stack just to get evaluated.
- It's an actual ecosystem. Devtools, editor tooling, scaffolding, and a discovery/delivery layer - all usable independently, and none of it locked behind "you must use our cloud service." That's a rarer design principle than it should be.
- Not vendor-locked to its own commercial offering. The Feed Service being fully optional, by design, is a rarer stance than you'd think for a company that also sells a feed service - it would have been easier, short-term, to make the two inseparable.
Where It Struggles
- Smaller community than the bigger names in the space. Compared to Module Federation or Single-SPA, Piral's community is meaningfully smaller - even though (or maybe partly because) it's used at some genuinely large companies who don't always talk publicly about their stack. Enterprise adoption doesn't show up as GitHub stars.
- React and React Router are still baked in, for now. Piral v1's core assumes React and React Router underneath, even though you can swap either out if you're willing to do the work (there are converter packages for Vue, Angular, and others at the pilet level, but the shell's assumptions run deeper). That's changing - Piral v2 is dropping both as hard prerequisites from the ground up - but today, going off the beaten path takes more effort than it should.
- The learning curve is real if you're new to micro frontends as a concept. Pilets, extension slots, shared dependencies, feed services - there's genuine architectural thinking required before you ship your first production app shell. This isn't a "npm install and you're basically done" kind of framework, and it was never trying to be one; the complexity it removes downstream (independent team deployments) has to be paid for somewhere, and that's mostly upfront in understanding the model.
- The commercial Feed Service, while optional, is where a lot of the "batteries included" experience lives. Rolling your own discovery/delivery mechanism is entirely possible, but you're signing up to build and maintain that piece yourself - versioning, rollout logic, health checks, the works.
Community: Smaller, But Loud in the Right Rooms
Piral has never chased npm download charts, and it shows - but it's shown up consistently where the actual micro frontends conversation happens. We've hosted numerous community talks over the years, at conferences and meetups well beyond our own events, and since 2023 we've run the Micro Frontends Conference annually - a free, one-day virtual event with 15+ speakers, several of whom are genuinely foundational names in this space (people who've built or shaped Module Federation, Single-SPA, and other tools you've likely already used).
The 2024 edition ran June 17th; sponsors across the two editions included JetBrains and several others from across the ecosystem. It's not a Piral-only event by design - the point was, and is, the micro frontends community as a whole, not just promoting our own framework. Running a conference that deliberately platforms competing approaches is a strange thing to do if your only goal is selling your own framework; it's a much more natural thing to do if your actual goal is a healthier ecosystem, which - vested interest aside - is genuinely the goal.
What's Next for Piral
The big one on the horizon is Piral v2, which drops the historical React and React Router requirements from day one instead of treating framework-agnosticism as something you bolt on with extra converters. That's a meaningful shift for a framework that's been React-first since its earliest versions - it means the core assumptions about rendering and routing get rethought rather than patched around, which is a bigger undertaking than it sounds like from one sentence.
Beyond that, the roadmap keeps circling back to making the "hundreds of pilets" scaling story even smoother as real deployments push past what we originally validated it against, and continuing to grow the ecosystem pieces (inspector, editor tooling, templates) independently of the core - the same philosophy that's been there since the beginning: build pieces that are useful even outside of a strict "you must use all of Piral" context. If the last seven years are any indication, the interesting adoption stories will keep coming from places we didn't specifically design for.
That's the Piral story - from a customer portal at ZEISS that finally worked, to a framework that scales to hundreds of independently shipped pilets, to hosting its own community conference. If you want to poke around: the website has the overview, the repository has the code, and the introduction article has the deeper technical walkthrough.
Next up in this series: another project, another origin story. Stay tuned.






Top comments (0)