Page loaded: UI Architecture Notes for Angular Teams

Writing

Notes on building, architecting, and maintaining front-end systems that no longer feel new.

I write about Angular, CSS, responsive design, accessibility, rendering, and long-lived UI decisions shaped by changing requirements, shifting teams, and real business pressure.

Miguel Carino
Focus
Front-end architecture, Angular, team leadership, and stakeholder communication
Experience
25+ years turning enterprise web complexity into maintainable products

A Remote That Moves Between Environments

If a micro-frontend's URL is compiled into the shell, the artifact you tested in staging is not the artifact you ship. Move the addresses into a file you can swap.

Remote URLs differ per environment. Bake them into the bundle and you cannot promote an artifact. Native Federation reads remotes from a manifest at runtime, so one build can move between environments. read more...

One Change, Nine Pull Requests

Micro-frontends buy independent deployment. Separate repositories are one way to buy it, and the price shows up on every change that crosses more than one of them.

Splitting a frontend into micro-frontends and splitting it across repos are two different calls. Only one of them is required. The other is the one that bills you every sprint. read more...

When the Bundler Stopped Being the Point

The best argument for leaving webpack was never the build times. It was that federation stopped being a plugin, so the build tool became replaceable again.

An opinionated case for moving Angular micro-frontends onto the esbuild builder. Plus an honest account of what the migration costs, and when staying on webpack is still the right call. read more...

What Native Federation Kept, and What It Dropped

Module Federation's real contribution was a mental model, not a bundler plugin. Native Federation rebuilt that model on web standards — and gave up a few things doing it.

Move an Angular app off the webpack builder and the federation setup has nothing left to plug into. Native Federation keeps hosts, remotes and shared singletons, and rebuilds them on ES modules and import maps. read more...

Seven Repos, One Angular Upgrade

A framework bump can build green in every repo and still fail at runtime. The version contract lives between the repos, where no pipeline is looking.

A routine Angular minor upgrade became a lockstep release across seven federated repos. The shared-dependency contract was right in each build and wrong in the assembly. read more...

Your Design System's Real API Is a CSS Variable

A component's theming surface is a contract whether you designed it or not. Leave it undeclared and consumers will fork the component to get one.

A team copied a button component to change its accent color, and the copy drifted. Exposing a small set of CSS custom properties gives consumers a sanctioned way to theme without forking, without ::ng-deep, and without an input for every color. read more...

Losing the Specificity War, Then Layering Out of It

Specificity escalation has no ceiling, so every override wins until the next one. Cascade layers replace the arms race with an order you declare once.

A design-system rule and an app override kept escalating specificity until nobody could predict the winner. Cascade layers decide by declared order instead of selector weight. Two rules decide whether the migration goes well. read more...

A Route Guard With No Constructor to Inject Into

Converting a class guard to a function left no constructor to inject into. That absence turned out to be the lesson.

Functional route guards are plain functions, so there is no constructor to receive services. inject() reads from the active injector instead, which is why it works inside a guard and throws once the call leaves the injection context. read more...

A Component That Reads the Room

Threading a dark flag through three components that don't care about theming is a design smell. Some differences belong to the surroundings, not the props.

A card needed a different look inside a dark sidebar, and the obvious fix coupled three intermediate components to theming. :host-context() lets a component respond to an ancestor class with no inputs and no JavaScript — with one caveat worth knowing. read more...

A Selection That Went Stale Every Refresh

Some state is derived and writable at the same time. Forcing it into a computed or an effect is what kept breaking the detail panel.

A selected row survived a filter change and pointed at a record no longer in the list. linkedSignal fits state that is derived from a source but still writable by the user — the case computed can't hold and an effect only appears to solve. read more...