A real movie search app built with Angular 21 from scratch — not a Hello World. Search movies, view details with ratings, and save favorites. Consumes the Day 15 NestJS Movie Search API.
Part of the TechFromZero series — one new technology every day, built step by step.
# 1. Start the NestJS API (Day 15) in another terminal
cd ../nestjs-from-zero
npm run start
# 2. Install dependencies
npm install
# 3. Start Angular dev server (proxies to NestJS on port 3000)
ng serve
# 4. Open http://localhost:4200- Movie Search — search by title, filter by type (movie/series/episode) and year
- Paginated Results — browse through results 10 at a time
- Movie Details — full info with poster, ratings bars (IMDB/RT/Metacritic), plot, cast, box office
- Favorites — add movies with notes, view your list, remove when done
- Dark Theme — cinema-inspired dark UI with amber accents
- Responsive — works on mobile and desktop
- Loading/Error States — spinners, error messages, empty state guidance
Angular App (port 4200)
├── Proxy (/api/* → localhost:3000)
├── API Key Interceptor (adds x-api-key header)
│
├── Pages
│ ├── / → SearchComponent (form + movie grid)
│ ├── /movie/:id → MovieDetailComponent (full info + favorites)
│ └── /favorites → FavoritesComponent (saved movies list)
│
├── Components
│ ├── NavbarComponent (navigation + favorites count badge)
│ ├── MovieCardComponent (search result card)
│ ├── PaginationComponent (page navigation)
│ └── FavoriteCardComponent (saved movie card)
│
├── Services
│ ├── MovieService (HttpClient → /api/movies/*)
│ └── FavoritesService (HttpClient + signals → /api/favorites/*)
│
└── Models
├── movie.model.ts (MovieSearchResult, MovieDetail, SearchResponse)
└── favorite.model.ts (Favorite)
Each commit builds on the last. Clone the repo and read them in order to learn Angular concepts one at a time.
| Step | Commit | Angular Concepts |
|---|---|---|
| 1 | Project scaffold + routing | Standalone bootstrap, ApplicationConfig, router-outlet |
| 2 | Environment config + proxy | Environment files, dev proxy, angular.json config |
| 3 | TypeScript models | Interfaces for type safety, generic ApiResponse<T> |
| 4 | MovieService + interceptor | HttpClient, Observable, pipe(map()), functional interceptors |
| 5 | FavoritesService + signals | signal(), computed(), reactive state without RxJS |
| 6 | Navbar component | RouterLink, RouterLinkActive, component composition |
| 7 | Search page + movie cards | ngModel, template-driven forms, @for, @if, input(), output() |
| 8 | Pagination component | Input/Output pattern, presentation components |
| 9 | Movie detail page | ActivatedRoute, route params, paramMap.subscribe() |
| 10 | Favorites page | Signal-based reactivity in templates, track |
| 11 | Dark theme + polish | CSS custom properties, ::selection, scrollbar, @keyframes |
| 12 | README + Vercel deploy | SPA deployment, vercel.json rewrites |
- Standalone Components — no NgModules, components declare their own imports
- Signals —
signal(),computed(),.asReadonly()for reactive state - HttpClient — making HTTP requests with Observables
- Functional Interceptors — adding headers to every request automatically
- Routing —
provideRouter(), lazy loading withloadComponent - Template-Driven Forms —
ngModeltwo-way binding - Component Communication —
input(),output()signal-based API - New Control Flow —
@if,@for,@else(Angular 17+ syntax) - Dependency Injection —
inject(),providedIn: 'root' - Dev Proxy — avoiding CORS during development
- CSS Encapsulation — component-scoped styles
- Lazy Loading — route-based code splitting
- Angular 21 (standalone components, signals, new control flow)
- TypeScript (strict types for API responses)
- CSS (no frameworks — custom dark theme with CSS custom properties)
- NestJS API (Day 15 — Movie Search API with OMDB)
This app consumes the Day 15 NestJS API:
| Method | Endpoint | Description |
|---|---|---|
| GET | /api/movies/search?title=X |
Search movies (paginated) |
| GET | /api/movies/:imdbId |
Get movie details |
| GET | /api/favorites |
List all favorites |
| POST | /api/favorites |
Add to favorites |
| DELETE | /api/favorites/:id |
Remove from favorites |
All endpoints require x-api-key: dev-key-123 header (added automatically by the interceptor).