Back to Blog

How I Built This Angular Microfrontend Demo with iframe (Part 1)

How I Built This Angular Microfrontend Demo with iframe (Part 1)

This post documents exactly how the project https://github.com/arkomandal/angular-microfrontend-demo was built from start to finish.

Important context: this implementation uses an iframe-based integration model. It is not a full end-to-end module federation composition yet.

The goal was simple:

  1. Create one host Angular app.
  2. Add two child Angular apps.
  3. Run all three apps locally.
  4. Integrate the children into the host in a way that is easy to demo and understand.

1. Create the base Angular workspace

The project started as a normal Angular CLI app:

ng new angular-microfrontend-demo --routing --style=scss
cd angular-microfrontend-demo

At this stage there was only one app (the future host).


2. Add child applications to the same workspace

Two additional Angular applications were added under projects/:

ng generate application child1 --routing --style=scss
ng generate application child2 --routing --style=scss

After this, the workspace structure looked like:

angular-microfrontend-demo/
|- src/                  # host app
|- projects/child1/      # first child app
`- projects/child2/      # second child app

Using one workspace keeps dependency management simple because all apps share the same node_modules.


3. Install microfrontend tooling

To support module federation style architecture, these packages were installed:

npm install @angular-architects/module-federation @angular-architects/native-federation --save

The project currently uses Angular 20, and compatible federation packages were chosen accordingly.


4. Add developer scripts for host + child apps

Before using the start:all script, install concurrently in the workspace:

npm install --save-dev concurrently

The root package.json scripts were set up so each app can run independently:

"start:host": "ng serve",
"start:child1": "ng run child1:serve --port=4300",
"start:child2": "ng run child2:serve --port=4400",
"start:all": "concurrently \"npm run start:host\" \"npm run start:child1\" \"npm run start:child2\""

This gives a clear local development model:

  • Host: http://localhost:4200
  • Child 1: http://localhost:4300
  • Child 2: http://localhost:4400

5. Configure host-level federation metadata

A federation.config.js was added in the root app to define the host name and remote endpoints:

remotes: {
  child1: 'http://localhost:4300/remoteEntry.json',
  child2: 'http://localhost:4400/remoteEntry.json',
}

This configuration establishes where remote manifests are expected when running a true federated flow.


6. Build the dashboard UI in the host

The host app was changed from the default Angular starter template into a small dashboard with:

  • Two clickable cards: Child 1 and Child 2
  • A popup window area to render selected child content
  • A close button to clear the selected view

The host component (src/app/app.ts) keeps a selected child URL, and the template (src/app/app.html) uses that URL inside an iframe.

This was the key design decision for the iframe branch: keep integration simple, visual, and easy to debug.


7. Why iframe integration was used

For demos and onboarding, iframes have practical benefits:

  1. Very low integration complexity.
  2. Strong runtime isolation between host and child apps.
  3. Easy troubleshooting because each child is still independently accessible by URL.

In short, this branch optimizes for clarity over advanced runtime composition.


8. Angular workspace configuration highlights

Inside angular.json:

  • The host (angular-microfrontend-demo) uses native federation builder settings.
  • child1 and child2 are standard Angular app targets served independently.
  • SSR support is present for host and child1 entries, but the local dashboard demo flow is primarily browser-driven.

This makes the workspace flexible: it can evolve from iframe-based composition to deeper federation composition later.


9. End-to-end run flow

From the project root:

npm install
npm run start:all

Then open http://localhost:4200.

Expected behavior:

  1. The host dashboard loads.
  2. Clicking Child 1 opens child1 inside the host window.
  3. Clicking Child 2 opens child2 inside the host window.
  4. Clicking x closes the child view.

10. Troubleshooting checklist used during setup

  • Port conflicts: ensure 4200/4300/4400 are free.
  • Blank iframe: confirm child app is running directly in browser first.
  • Dependency mismatch: align Angular and @angular-architects/* versions.
  • Config changes not reflected: stop and restart dev servers.

These were the most common blockers while assembling and validating the project.


11. What was achieved by the end

By the end of setup, the project had:

  • A functioning host dashboard
  • Two independently runnable child Angular apps
  • One-command local startup (npm run start:all)
  • A clean demonstration path for microfrontend concepts

That is the complete start-to-end story of this project in its current iframe branch shape.

In the next post, I will cover the full federation implementation end to end, including direct remote loading instead of iframe embedding.


Series Navigation