π °οΈ Angular Framework Architecture
Angular is not just a library β it's a complete, opinionated platform for building large single-page apps in TypeScript. This lesson maps its architecture end to end: the standalone components you compose views from, the signals that keep the screen in sync with your data, and the dependency injection that wires services together.
π― Learning Objectives
By the end of this lesson, you will be able to:
- Explain what makes Angular a framework rather than a library, and when that trade-off pays off
- Identify Angular's core building blocks β components, templates, services, and dependency injection
- Describe how modern Angular uses standalone components and signals instead of NgModules and Zone-based change detection
- Compare Angular with Vue and React and pick the right tool for a project
- Scaffold and run a project with the Angular CLI
Estimated Time: 30β40 minutes β’ Difficulty: Intermediate
Hands-on: Sketch the architecture of a small Angular app and write your first standalone component.
In This Lesson
What Is Angular?
Angular is a platform and framework for building single-page client applications using HTML and TypeScript. It is developed and maintained by Google and is a complete reimagining of the original AngularJS (1.x). Where a library like React hands you one piece of the puzzle and lets you assemble the rest, a framework like Angular gives you the whole box β routing, forms, HTTP, testing, and build tooling β all designed to fit together.
π‘ A useful analogy: If web development were construction, Angular is a full building system with standardized, prefabricated parts, its own tools, and detailed blueprints. You get everything to go from foundation to roof, with clear rules for how the pieces snap together. That structure is a burden on a tiny project and a lifesaver on a huge one.
π Key Terms
Framework: a complete, opinionated toolkit that calls your code (inversion of control), providing built-in answers for common problems.
Single-Page Application (SPA): a web app that loads one HTML shell and then rewrites the page in the browser as the user navigates, instead of fetching a fresh page from the server each time.
TypeScript-first: Angular is authored in TypeScript and expects you to use it, giving you static types, autocompletion, and safer refactors out of the box.
Angular is deliberately opinionated. It ships a recommended way to structure code, fetch data, handle forms, and route between screens. On a solo weekend project that can feel like overkill. On a 40-person enterprise app that must stay maintainable for a decade, those shared conventions are exactly what keep the codebase coherent.
How Angular Got Here
Understanding a little history explains why Angular looks the way it does today β and why some tutorials you find online are dangerously out of date.
Two changes matter most for a learner in 2026:
- Standalone components (Angular 14β17): components no longer need to be registered in an
NgModule. You can build entire apps without writing a single module. This is now the default when you generate a new project. - Signals (Angular 16+): a new, fine-grained reactivity system that tracks exactly which values a template reads, so Angular can update only what actually changed instead of re-checking the whole component tree.
β οΈ Beware of old tutorials
A great deal of Angular content still teaches the "Tour of Heroes" style with @NgModule, *ngIf, and Zone-based change detection. That code still works, but this course teaches the modern path: standalone components, signals, and the new @if/@for control flow. When you copy code from the web, check the Angular version first.
Angular vs Vue vs React
All three tools solve the same problem β keeping a user interface in sync with changing data β but they make different trade-offs. Knowing where each shines helps you choose (and helps you answer the interview question).
| Dimension | Angular | Vue | React |
|---|---|---|---|
| Type | Full framework | Progressive framework | Library |
| Language | TypeScript-first | Optional TypeScript | JavaScript / JSX |
| Templating | HTML + template syntax | HTML + template syntax | JSX in JavaScript |
| Built-in tooling | Router, forms, HTTP, testing | Router & store as official add-ons | Pick your own for everything |
| Opinionation | High | Medium | Low |
| Sweet spot | Large enterprise apps | Fast-moving small/medium apps | Anything, with a chosen stack |
β When to reach for Angular
Choose Angular when you have a large team, a long-lived codebase, and a preference for strong typing and shared conventions. The batteries-included design means less time arguing about which router or form library to use β the answer is already in the box.
Crucially, the concepts transfer. Once you understand components, one-way data flow, reactive state, and dependency injection here, you will recognize the same ideas β under different names β in Vue and React.
The Core Building Blocks
An Angular application is a tree of components that lean on services for shared work, all wired together by dependency injection. Here is how the pieces relate:
Components
A component controls a patch of screen called a view. It bundles three things: a template (the HTML), styles (the CSS), and a class (the TypeScript that holds state and behavior). Modern Angular components are standalone β they declare their own dependencies through imports and need no surrounding module.
import { Component, signal } from '@angular/core';
@Component({
selector: 'app-hero-detail',
standalone: true,
template: `
<h2>{{ hero().name }} details</h2>
<button (click)="rename()">Rename</button>
`,
})
export class HeroDetailComponent {
// signal() creates a reactive value the template tracks automatically
hero = signal({ id: 1, name: 'Windstorm' });
rename(): void {
this.hero.update(h => ({ ...h, name: 'Magneta' }));
}
}
π‘ Analogy: A component is a specialized worker at a station. The template is the blueprint it follows, the styles are its uniform, and the class is the know-how that tells it what to do.
Templates
A template is HTML enhanced with Angular's binding syntax and the new built-in control flow. It is the declarative description of what the view should look like for the current state.
<div class="hero-detail">
<h2>{{ hero().name | uppercase }} Details</h2>
<label>
Name:
<input [value]="hero().name" (input)="onNameInput($event)" />
</label>
@if (hero().active) {
<p>This hero is on active duty.</p>
} @else {
<p>This hero is resting.</p>
}
</div>
We cover binding and control flow in depth in the next two lessons. For now, notice the shape: {{ }} shows data, [value] pushes data into an element, (input) listens for events, and @if conditionally renders markup.
Services
A service is a plain class with a focused job β fetching data, logging, caching β that is not tied to any one view. Marking it @Injectable({ providedIn: 'root' }) makes it a singleton available anywhere in the app.
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
export interface Hero { id: number; name: string; }
@Injectable({ providedIn: 'root' })
export class HeroService {
private http = inject(HttpClient);
private heroesUrl = '/api/heroes';
getHeroes(): Observable<Hero[]> {
return this.http.get<Hero[]>(this.heroesUrl);
}
}
π‘ Analogy: Services are the utility companies of your app β water, power, waste collection. Any building (component) can plug into them without having to generate its own electricity.
Signals & Reactivity
The heart of a modern Angular app is reactivity: when a value changes, the view that depends on it updates automatically. Angular's newest answer to this is the signal β a wrapper around a value that remembers who is reading it.
signal() feeds derived computed() values, which feed the template. Update the source and Angular refreshes only the readers, not the whole page.There are three pieces to the signals toolkit:
signal(value)β a writable reactive value. Read it withcount(); change it withcount.set(5)orcount.update(n => n + 1).computed(fn)β a read-only value derived from other signals, recalculated lazily when its inputs change.effect(fn)β a side effect that re-runs whenever the signals it reads change (for logging, syncing to storage, etc.).
import { Component, signal, computed } from '@angular/core';
@Component({
selector: 'app-cart',
standalone: true,
template: `
<p>Items: {{ count() }}</p>
<p>Total: {{ total() | currency }}</p>
<button (click)="add()">Add item</button>
`,
})
export class CartComponent {
count = signal(0);
price = signal(9.99);
// Recomputes automatically whenever count() or price() changes
total = computed(() => this.count() * this.price());
add(): void {
this.count.update(n => n + 1);
}
}
π‘ Why signals matter
Older Angular relied on Zone.js to guess when data might have changed and then re-check the whole component tree. Signals flip that around: because a signal knows exactly which templates read it, Angular can update precisely those spots. The result is faster, more predictable rendering β and code that reads like plain values.
Services & Dependency Injection
Dependency Injection (DI) is a design pattern where a class asks for what it needs instead of building it itself. Angular's DI system creates each dependency once and hands the same instance to everyone who requests it.
The modern way to receive a dependency is the inject() function:
import { Component, inject, signal } from '@angular/core';
import { HeroService, Hero } from './hero.service';
@Component({
selector: 'app-hero-list',
standalone: true,
template: `
<ul>
@for (hero of heroes(); track hero.id) {
<li>{{ hero.name }}</li>
}
</ul>
`,
})
export class HeroListComponent {
private heroService = inject(HeroService);
heroes = signal<Hero[]>([]);
constructor() {
this.heroService.getHeroes()
.subscribe(list => this.heroes.set(list));
}
}
π‘ Analogy: DI is like the hospitality desk at a conference. Instead of every speaker bringing their own projector, microphone, and water, the organizer provides those resources on request β one shared set for everyone.
π Why DI is worth the ceremony
Because components receive their dependencies rather than construct them, you can swap a real service for a fake one in tests, share a single cache across the app, and change an implementation in one place. It is the seam that keeps a large Angular app testable and loosely coupled.
The Angular CLI
The Angular CLI is the command-line tool that scaffolds, builds, serves, and tests your app. It enforces a consistent structure so every Angular project feels familiar.
# Install the CLI once, globally
npm install -g @angular/cli
# Create a new standalone app
ng new my-app
# Move in and start the dev server (opens http://localhost:4200)
cd my-app
ng serve
# Generate a standalone component
ng generate component hero-detail # or: ng g c hero-detail
# Generate a service
ng generate service hero
# Produce an optimized production build
ng build
A freshly generated app has a lean, module-free shape:
my-app/
βββ src/
β βββ app/
β β βββ app.component.ts # root standalone component
β β βββ app.component.html
β β βββ app.config.ts # providers (router, HTTP, ...)
β β βββ app.routes.ts # route definitions
β βββ main.ts # bootstrapApplication(AppComponent)
β βββ index.html
β βββ styles.css
βββ angular.json
βββ package.json
βββ tsconfig.json
The app boots from main.ts with a single call β no root module required:
import { bootstrapApplication } from '@angular/platform-browser';
import { provideHttpClient } from '@angular/common/http';
import { provideRouter } from '@angular/router';
import { AppComponent } from './app/app.component';
import { routes } from './app/app.routes';
bootstrapApplication(AppComponent, {
providers: [
provideRouter(routes),
provideHttpClient(),
],
});
β CLI habits worth forming
- Generate components and services with
ng gso they follow the standard layout. - Keep
ng serverunning while you work β it live-reloads on every save. - Run
ng buildbefore deploying to catch template and type errors ahead of time.
Hands-on Exercise
ποΈ Architect a Small App, Then Build a Component
Objective: Translate the architecture in this lesson into a concrete plan and a working standalone component.
Instructions:
- Imagine a tiny "Bookmarks" app. On paper, list the components you'd need (e.g. a list, an item, an add-form) and the service that would hold the bookmark data.
- Draw the arrows: which component injects the service? Which components pass data to which?
- Now write a standalone
BookmarkListComponent. It should hold asignalof bookmark objects and render them with@for. - Add a
computedsignal that reports how many bookmarks there are, and show it above the list.
π‘ Hint
Start from the CartComponent pattern above. A bookmark can be as simple as { id: number; title: string; url: string }. Use track bookmark.id inside @for so Angular can reuse DOM nodes efficiently.
β Example solution
import { Component, signal, computed } from '@angular/core';
interface Bookmark { id: number; title: string; url: string; }
@Component({
selector: 'app-bookmark-list',
standalone: true,
template: `
<h2>My Bookmarks ({{ count() }})</h2>
<ul>
@for (b of bookmarks(); track b.id) {
<li><a [href]="b.url">{{ b.title }}</a></li>
} @empty {
<li>No bookmarks yet.</li>
}
</ul>
`,
})
export class BookmarkListComponent {
bookmarks = signal<Bookmark[]>([
{ id: 1, title: 'Angular Docs', url: 'https://angular.dev' },
{ id: 2, title: 'MDN', url: 'https://developer.mozilla.org' },
]);
count = computed(() => this.bookmarks().length);
}
Notice how count() stays correct forever: add or remove a bookmark and the header updates itself, because it is derived from the same signal.
π― Quick Quiz
Question 1: What best distinguishes Angular from React?
Question 2: In modern Angular, how do you create a reactive value that a template tracks automatically?
Question 3: What does @Injectable({ providedIn: 'root' }) accomplish?
Summary & Quiz
π Key Takeaways
- Angular is a full framework β routing, forms, HTTP, and testing all come in the box, which pays off on large, long-lived apps.
- Apps are built from standalone components (template + styles + class) that lean on services wired by dependency injection.
- Signals β
signal,computed,effectβ are the modern reactivity system, replacing Zone-based full-tree checks with precise updates. - The Angular CLI scaffolds, serves, and builds projects; new apps boot with
bootstrapApplication, no root NgModule required.
π Further Reading
- Angular β What is Angular?
- Angular β Signals guide
- Angular β Components overview
- Angular CLI documentation
π What's Next?
Now that you have the map, we'll zoom into how Angular apps are organized β the roles of modules and components, standalone imports, lifecycle hooks, and how components pass data to one another.
π Great start!
You can now describe Angular's architecture from the CLI all the way down to a single signal. Let's build on it.