A full-stack demo using an Nx monorepo with Angular (zoneless, signals) and a .NET 10.0 Web API backend. Deployed to Azure App Service with automated PR preview deployments via Azure Static Web Apps.
- Todos CRUD demo — the Todos feature demonstrates the canonical full-stack CRUD loop: a .NET minimal API with an in-memory repository, an NgRx SignalStore driving an
rxResource, and per-feature error banners - Authentication — register, login, and logout with JWT bearer tokens backed by ASP.NET Core Identity
- Notification center — persistent notification panel with unread count, mark-as-read, dismiss, and action support (e.g. one-click reload on SW update)
- PWA / service worker — offline support; notifies users when a new app version is available with an in-app prompt to reload
- Markdown content pages — Analog.js content feature renders pages from Markdown files with frontmatter support (see the About page for a live demo)
- Recipe browser — the repo's recipe catalog is browsable in the running app at
/recipes, served from the same files via an Analog content route - Counter micro frontend — the Counter feature runs as a separate Module Federation remote (
counter-remote), demonstrating micro-frontend architecture with shared singleton libraries - Debug page (
/debug) — trigger test notifications and inspect service worker update state during development - PR preview deployments — every pull request gets a live preview URL via Azure Static Web Apps
Frontend
- Angular 22 — zoneless change detection, standalone components, signals
- NgRx Signal Store — reactive state management
- Angular Material — UI component library
- Analog.js — Vite-native Angular meta-framework; used for file-based Markdown content pages
- Tailwind CSS v4 — utility-first styling
- Angular PWA — service worker & offline support
- Module Federation (
@module-federation/vite) — micro-frontend architecture
Backend
- .NET 10.0 Web API
- ASP.NET Core Identity — bearer token authentication
- Entity Framework Core with Azure SQL
Tooling
- Nx — monorepo build system with affected commands
- Vitest — unit tests with ~93% line coverage
- Playwright — end-to-end tests
- Husky + lint-staged — pre-commit hooks for linting, formatting, and keeping
home.mdin sync - pnpm — package manager
Live demo: https://angularclinetcorengrxstarter.azurewebsites.net/
Prerequisites
- Node 24.x+ with pnpm 10+
- .NET SDK 10.0.x — download
Install dependencies
pnpm installpnpm startStarts both the .NET API and Angular app in dev mode. Open http://localhost:4200 for the app, or https://localhost:60254/swagger for the API docs.
The Counter feature is a Module Federation micro-frontend remote. To develop with the MFE active, start both servers in separate terminals:
# Terminal 1 — remote (port 4201)
pnpm nx serve counter-remote
# Terminal 2 — host (port 4200)
pnpm nx serve web-appThe host at http://localhost:4200 will load the Counter remote automatically from http://localhost:4201/remoteEntry.js when you navigate to /mfe-counter.
| App | Role | Port | Description |
|---|---|---|---|
web-app |
MFE host | 4200 | Main application shell |
counter-remote |
MFE remote | 4201 | Counter feature exposed via Module Federation |
Shared singletons — Angular core, CDK/Material, and NgRx are configured as Module Federation singletons so both apps share a single instance. This prevents Angular's NG0912 component-ID collision warnings that occur when the same component class is registered twice.
Remote self-containment — workspace libs (@myorg/shared, @myorg/counter) are NOT in the MF shared config because Rolldown's static analysis cannot enumerate export * chains from TypeScript path aliases. Instead, the remote is designed to be self-contained: counter-remote bundles only @myorg/counter (which has no @myorg/shared dependencies), and the host bundles @myorg/shared exclusively (no duplicate registrations).
Preview deployments — in CI, counter-remote is built and served from /counter-remote/ within the same Static Web App as the host. The COUNTER_REMOTE_ENTRY environment variable is set to /counter-remote/remoteEntry.js during the host build so the baked-in import map points to the co-deployed remote instead of localhost.
pnpm lintpnpm testCoverage requires dotnet-coverage:
dotnet tool install --global dotnet-coveragepnpm e2epnpm build:prodBuilds the Angular app and publishes the .NET project to /dist, ready to deploy to Azure App Service.
A recipe catalog documents every pattern in this repo — feature libraries, SignalStore, CRUD, signal forms, error handling, notifications, route guards, HTTP interceptors, EF migrations, auth, testing, content pages, PWA, theming, MFEs, deployment, and dependency updates. Each recipe points at its canonical implementation files; the code is the source of truth.
apps/web-app/src/assets/home.md is auto-generated from this file — edit README.md only. The lint-staged hook regenerates home.md automatically whenever README.md is committed.