Angular Frontend Development - Photo Map MVP
Project Context
Photo Map MVP - Single Page Application (SPA) for managing photos with geolocation.
Frontend Stack:
- Angular: 18.2.0+ (standalone components, NO NgModules!)
- TypeScript: 5.5.2+ (strict mode)
- Styling: Tailwind CSS 3.4.17 (NOT v4 - Angular 18 incompatibility!)
- Map: Leaflet.js 1.9.4 + marker clustering
- State: RxJS 7.8.0 (BehaviorSubject pattern, no NgRx)
- Build: Angular CLI 18.2.0 (esbuild)
Core Features:
- Authentication: Login/Register with JWT storage, route guards
- Gallery: Responsive grid with lazy loading, rating, filtering
- Map View: Leaflet integration with GPS markers, popups, clustering
- Admin Panel: User management (ADMIN role only)
Key Constraints:
- Standalone components ONLY - NO NgModules anywhere!
- Tailwind 3.4.17 - NOT 4.x (incompatibility with Angular 18)
- inject() function - NOT constructor injection (modern Angular 18)
- Signals - reactive state (Angular 16+)
- BehaviorSubject - service state management (no NgRx)
Architecture Principles
Standalone Components
ALL components MUST be standalone (standalone: true). Explicitly import dependencies in imports array. NO @NgModule anywhere.
Check: references/angular-patterns.md for complete patterns.
State Management Strategy
Decision Tree:
- Component-local state → Use Signals (
signal(), computed(), effect())
- Shared state (cross-component) → Use BehaviorSubject in Services
Pattern: private BehaviorSubject → public Observable → Component subscribes
Check: references/state-management.md for detailed patterns.
Dependency Injection
Use inject() function (modern Angular 18), NOT constructor injection. Make all injected services readonly.
Example: private readonly photoService = inject(PhotoService);
When to Use What
Signals vs BehaviorSubject
| Use Case |
Solution |
| Component-local state (counters, UI flags, filters) |
Signals |
| Computed values (derived state) |
Signals (computed()) |
| Shared state (cross-component, services) |
BehaviorSubject |
| Async operations (HTTP, timers) |
BehaviorSubject |
| Complex RxJS pipelines |
BehaviorSubject |
Smart vs Dumb Components
| Type |
Characteristics |
| Smart (Container) |
Inject services, manage state, business logic, fetch data |
| Dumb (Presentational) |
NO service injection, @Input/@Output only, pure presentation |
Check: references/component-patterns.md for detailed examples.
Implementation Workflows
Creating Component
- Use checklist:
templates/component-template.md
- Standalone setup:
@Component({ standalone: true })
- Import dependencies:
CommonModule, RouterLink, child components
- Dependency injection: Use
inject(), make services readonly
- State: Signals for local state, BehaviorSubject consumption for shared state
- Template: Use @if, @for (NOT *ngIf, *ngFor), add
data-testid attributes
- Examples:
- Smart component →
examples/photo-gallery.component.ts
- Dumb component →
examples/photo-card.component.ts
Check: references/component-patterns.md for Smart vs Dumb patterns.
Creating Service
- Use checklist:
templates/service-template.md
- State management:
- Private:
private readonly itemsSubject = new BehaviorSubject<T>([])
- Public:
readonly items$ = itemsSubject.asObservable()
- HTTP methods: All return
Observable<T> with explicit types
- Error handling: Use
catchError, log errors, transform to user-friendly messages
- Example:
examples/photo.service.ts (BehaviorSubject + HTTP)
Check: references/service-patterns.md for HTTP patterns and interceptors.
Routing Setup
- Use checklist:
templates/route-template.md
- Configure routes:
app.routes.ts with flat Routes array
- Functional guards: Use
CanActivateFn, inject services with inject()
- Register:
provideRouter(routes) in app.config.ts
- Examples:
- Routes →
examples/app.routes.ts
- Guards →
examples/auth.guard.ts
Check: references/angular-patterns.md for routing and guards.
Patterns and Best Practices
- TypeScript quality: Check
references/typescript-quality.md (readonly, const, strict mode)
- RxJS patterns: Check
references/rxjs-patterns.md (operators, async pipe, error handling)
- Tailwind CSS: Check
references/tailwind-patterns.md (utility-first, responsive, constraints)
- Leaflet integration: Check
references/leaflet-integration.md (map setup, markers, clustering)
- SOLID principles: Check
references/solid-principles.md (when complexity justifies it)
- Testing: Check
references/testing-patterns.md (Jasmine + Karma, test IDs)
- Responsive design: Check
references/responsive-design.md (mobile-first, touch-friendly)
Key Reminders
Critical Constraints:
- ✅ ALWAYS
standalone: true (NO NgModules!)
- ✅ Use
inject() NOT constructor injection
- ✅ Tailwind 3.4.17 (NOT 4 - incompatibility!)
- ✅
data-testid on all interactive elements (kebab-case)
- ✅
readonly for services, const for variables
- ✅ Explicit return types (TypeScript strict)
State Management:
- ✅ Signals → component-local state
- ✅ BehaviorSubject → service state (shared)
- ✅ Async pipe in templates (automatic cleanup)
Component Structure:
- ✅ Smart components: inject services, manage state
- ✅ Dumb components: @Input/@Output only
- ✅ Use @if, @for, @switch (NOT *ngIf, *ngFor)
Routing:
- ✅ Functional guards (
CanActivateFn)
- ✅ Return
true | false | UrlTree
- ✅ Use
inject() in guards
Quick Reference
Pattern Lookup
| Need |
Check |
| Angular patterns (standalone, control flow, inject) |
references/angular-patterns.md |
| State management (Signals vs BehaviorSubject) |
references/state-management.md |
| TypeScript quality (readonly, const, strict) |
references/typescript-quality.md |
| RxJS patterns (operators, async pipe) |
references/rxjs-patterns.md |
| Tailwind styling (utility-first, responsive) |
references/tailwind-patterns.md |
| Leaflet maps (setup, markers, clustering) |
references/leaflet-integration.md |
| Component patterns (Smart vs Dumb) |
references/component-patterns.md |
| Service patterns (HTTP, BehaviorSubject) |
references/service-patterns.md |
| SOLID principles |
references/solid-principles.md |
| Testing (Jasmine, Karma) |
references/testing-patterns.md |
| Responsive design (mobile-first, RWD) |
references/responsive-design.md |
Example Lookup
| Need |
Check |
| Smart component (with Signals + Services) |
examples/photo-gallery.component.ts |
| Dumb component (@Input/@Output) |
examples/photo-card.component.ts |
| Service (BehaviorSubject + HTTP) |
examples/photo.service.ts |
| Filter service (state management) |
examples/filter.service.ts |
| Map component (Leaflet integration) |
examples/map.component.ts |
| Functional guards |
examples/auth.guard.ts |
| Route configuration |
examples/app.routes.ts |
| TypeScript interfaces |
examples/photo.interface.ts |
| HTTP interceptors |
examples/jwt.interceptor.ts |
Template Lookup (Checklists)
| Need |
Check |
| Creating standalone component |
templates/component-template.md |
| Creating service with state |
templates/service-template.md |
| Routing + guards setup |
templates/route-template.md |
| Writing tests (Jasmine + Karma) |
templates/test-template.md |
1---2name: angular-frontend3description: Angular Frontend Development - Photo Map MVP4---56# Angular Frontend Development - Photo Map MVP78## Project Context910**Photo Map MVP** - Single Page Application (SPA) for managing photos with geolocation.1112**Frontend Stack:**13- **Angular:** 18.2.0+ (standalone components, NO NgModules!)14- **TypeScript:** 5.5.2+ (strict mode)15- **Styling:** Tailwind CSS 3.4.17 (NOT v4 - Angular 18 incompatibility!)16- **Map:** Leaflet.js 1.9.4 + marker clustering17- **State:** RxJS 7.8.0 (BehaviorSubject pattern, no NgRx)18- **Build:** Angular CLI 18.2.0 (esbuild)1920**Core Features:**211. **Authentication:** Login/Register with JWT storage, route guards222. **Gallery:** Responsive grid with lazy loading, rating, filtering233. **Map View:** Leaflet integration with GPS markers, popups, clustering244. **Admin Panel:** User management (ADMIN role only)2526**Key Constraints:**27- **Standalone components ONLY** - NO NgModules anywhere!28- **Tailwind 3.4.17** - NOT 4.x (incompatibility with Angular 18)29- **inject() function** - NOT constructor injection (modern Angular 18)30- **Signals** - reactive state (Angular 16+)31- **BehaviorSubject** - service state management (no NgRx)3233---3435## Architecture Principles3637### Standalone Components3839ALL components MUST be standalone (`standalone: true`). Explicitly import dependencies in `imports` array. NO `@NgModule` anywhere.4041Check: `references/angular-patterns.md` for complete patterns.4243### State Management Strategy4445**Decision Tree:**46- **Component-local state** → Use Signals (`signal()`, `computed()`, `effect()`)47- **Shared state (cross-component)** → Use BehaviorSubject in Services4849**Pattern:** `private BehaviorSubject` → `public Observable` → Component subscribes5051Check: `references/state-management.md` for detailed patterns.5253### Dependency Injection5455Use `inject()` function (modern Angular 18), NOT constructor injection. Make all injected services `readonly`.5657Example: `private readonly photoService = inject(PhotoService);`5859---6061## When to Use What6263### Signals vs BehaviorSubject6465| Use Case | Solution |66|----------|----------|67| Component-local state (counters, UI flags, filters) | **Signals** |68| Computed values (derived state) | **Signals** (`computed()`) |69| Shared state (cross-component, services) | **BehaviorSubject** |70| Async operations (HTTP, timers) | **BehaviorSubject** |71| Complex RxJS pipelines | **BehaviorSubject** |7273### Smart vs Dumb Components7475| Type | Characteristics |76|------|-----------------|77| **Smart** (Container) | Inject services, manage state, business logic, fetch data |78| **Dumb** (Presentational) | NO service injection, @Input/@Output only, pure presentation |7980Check: `references/component-patterns.md` for detailed examples.8182---8384## Implementation Workflows8586### Creating Component87881. **Use checklist:** `templates/component-template.md`892. **Standalone setup:**90 - `@Component({ standalone: true })`91 - Import dependencies: `CommonModule`, `RouterLink`, child components923. **Dependency injection:** Use `inject()`, make services `readonly`934. **State:** Signals for local state, BehaviorSubject consumption for shared state945. **Template:** Use @if, @for (NOT *ngIf, *ngFor), add `data-testid` attributes956. **Examples:**96 - Smart component → `examples/photo-gallery.component.ts`97 - Dumb component → `examples/photo-card.component.ts`9899Check: `references/component-patterns.md` for Smart vs Dumb patterns.100101### Creating Service1021031. **Use checklist:** `templates/service-template.md`1042. **State management:**105 - Private: `private readonly itemsSubject = new BehaviorSubject<T>([])`106 - Public: `readonly items$ = itemsSubject.asObservable()`1073. **HTTP methods:** All return `Observable<T>` with explicit types1084. **Error handling:** Use `catchError`, log errors, transform to user-friendly messages1095. **Example:** `examples/photo.service.ts` (BehaviorSubject + HTTP)110111Check: `references/service-patterns.md` for HTTP patterns and interceptors.112113### Routing Setup1141151. **Use checklist:** `templates/route-template.md`1162. **Configure routes:** `app.routes.ts` with flat Routes array1173. **Functional guards:** Use `CanActivateFn`, inject services with `inject()`1184. **Register:** `provideRouter(routes)` in `app.config.ts`1195. **Examples:**120 - Routes → `examples/app.routes.ts`121 - Guards → `examples/auth.guard.ts`122123Check: `references/angular-patterns.md` for routing and guards.124125### Patterns and Best Practices126127- **TypeScript quality:** Check `references/typescript-quality.md` (readonly, const, strict mode)128- **RxJS patterns:** Check `references/rxjs-patterns.md` (operators, async pipe, error handling)129- **Tailwind CSS:** Check `references/tailwind-patterns.md` (utility-first, responsive, constraints)130- **Leaflet integration:** Check `references/leaflet-integration.md` (map setup, markers, clustering)131- **SOLID principles:** Check `references/solid-principles.md` (when complexity justifies it)132- **Testing:** Check `references/testing-patterns.md` (Jasmine + Karma, test IDs)133- **Responsive design:** Check `references/responsive-design.md` (mobile-first, touch-friendly)134135---136137## Key Reminders138139**Critical Constraints:**140- ✅ ALWAYS `standalone: true` (NO NgModules!)141- ✅ Use `inject()` NOT constructor injection142- ✅ Tailwind 3.4.17 (NOT 4 - incompatibility!)143- ✅ `data-testid` on all interactive elements (kebab-case)144- ✅ `readonly` for services, `const` for variables145- ✅ Explicit return types (TypeScript strict)146147**State Management:**148- ✅ Signals → component-local state149- ✅ BehaviorSubject → service state (shared)150- ✅ Async pipe in templates (automatic cleanup)151152**Component Structure:**153- ✅ Smart components: inject services, manage state154- ✅ Dumb components: @Input/@Output only155- ✅ Use @if, @for, @switch (NOT *ngIf, *ngFor)156157**Routing:**158- ✅ Functional guards (`CanActivateFn`)159- ✅ Return `true | false | UrlTree`160- ✅ Use `inject()` in guards161162---163164## Quick Reference165166### Pattern Lookup167168| Need | Check |169|------|-------|170| Angular patterns (standalone, control flow, inject) | `references/angular-patterns.md` |171| State management (Signals vs BehaviorSubject) | `references/state-management.md` |172| TypeScript quality (readonly, const, strict) | `references/typescript-quality.md` |173| RxJS patterns (operators, async pipe) | `references/rxjs-patterns.md` |174| Tailwind styling (utility-first, responsive) | `references/tailwind-patterns.md` |175| Leaflet maps (setup, markers, clustering) | `references/leaflet-integration.md` |176| Component patterns (Smart vs Dumb) | `references/component-patterns.md` |177| Service patterns (HTTP, BehaviorSubject) | `references/service-patterns.md` |178| SOLID principles | `references/solid-principles.md` |179| Testing (Jasmine, Karma) | `references/testing-patterns.md` |180| Responsive design (mobile-first, RWD) | `references/responsive-design.md` |181182### Example Lookup183184| Need | Check |185|------|-------|186| Smart component (with Signals + Services) | `examples/photo-gallery.component.ts` |187| Dumb component (@Input/@Output) | `examples/photo-card.component.ts` |188| Service (BehaviorSubject + HTTP) | `examples/photo.service.ts` |189| Filter service (state management) | `examples/filter.service.ts` |190| Map component (Leaflet integration) | `examples/map.component.ts` |191| Functional guards | `examples/auth.guard.ts` |192| Route configuration | `examples/app.routes.ts` |193| TypeScript interfaces | `examples/photo.interface.ts` |194| HTTP interceptors | `examples/jwt.interceptor.ts` |195196### Template Lookup (Checklists)197198| Need | Check |199|------|-------|200| Creating standalone component | `templates/component-template.md` |201| Creating service with state | `templates/service-template.md` |202| Routing + guards setup | `templates/route-template.md` |203| Writing tests (Jasmine + Karma) | `templates/test-template.md` |