A modern, feature-rich photo gallery built with Angular 17+, showcasing advanced frontend development concepts including signals, reactive programming, and component architecture.
A responsive photo gallery application that fetches images from an external API, with features including search, infinite scroll, favorites management, and detailed photo viewing. Built as a learning project to master modern Angular patterns and best practices.
Live Demo: Live
Repository: GitHub link
- Dynamic Photo Loading: Fetch photos from Picsum Photos API with pagination
- Infinite Scroll: Load more photos automatically as user scrolls
- Search Functionality: Real-time search with debouncing (500ms delay)
- Photo Details Modal: View full-size images with metadata and navigation
- Favorites System: Like/unlike photos with persistent storage
- Filter by Favorites: Toggle between all photos and favorites only
- Responsive Grid Layout: Adaptive CSS Grid (1-4 columns based on screen size)
- Optimistic UI Updates: Instant feedback on all interactions
- Error Handling: Graceful degradation with retry mechanisms
- Loading States: Clear indicators for data fetching
- Empty States: Helpful messages when no content available
- Keyboard Navigation: Arrow keys in modal for photo browsing
- Accessibility: Semantic HTML and ARIA labels
- LocalStorage Integration: Favorites survive browser refresh
- Merged State Management: User preferences merged with API data
- Efficient Storage: Only stores liked photo IDs (lightweight)
- Standalone Components: No NgModules, simplified architecture
- Signals API: Reactive state management without RxJS boilerplate
signal()- Writable reactive statecomputed()- Derived reactive valueseffect()- Side effects on signal changes
- New Control Flow:
@if,@for,@elsesyntax - Signal Inputs:
input.required<T>()for component inputs - Signal Outputs:
output<T>()for event emission
-
Component Architecture
- Smart vs Presentational components
- Component communication (inputs/outputs)
- Lifecycle hooks (ngOnInit, OnDestroy)
- ViewChild for DOM access
-
Services & Dependency Injection
inject()function for field-level DI- Singleton services with
providedIn: 'root' - Service composition and delegation pattern
- HTTP client integration
-
Reactive Programming
- RxJS Observables, Operators, and Subjects
- Operators:
map,tap,catchError,debounceTime,distinctUntilChanged - Signal-based reactivity vs Observable patterns
- Async pipe for template subscriptions
-
State Management
- Centralized state with PhotoService
- Immutable state updates with signals
- Computed values for derived state
- LocalStorage persistence strategy
-
Forms & User Input
- Template-driven search with reactive updates
- Input debouncing for performance
- Form state management with signals
-
HTTP & API Integration
- HttpClient for REST API calls
- Error handling with catchError
- Retry logic and timeout strategies
- Response transformation and mapping
-
Styling & Responsive Design
- SCSS/SASS with component-scoped styles
- CSS Grid and Flexbox layouts
- Media queries for responsive breakpoints
- CSS transitions and animations
-
src/app/components/ - UI Components
photo-card/- Individual photo card display componentphoto-dialog/- Modal for detailed photo viewsearch-photo/- Search input with debouncing
-
src/app/services/ - Business Logic
photo.service.ts- Photo data management and API callslike.service.ts- Favorites/likes management
-
src/app/models/ - TypeScript Interfaces
photo.interface.ts- Photo and ApiPhoto types
-
Root Components
app.component.ts- Main application componentapp.html- Main templateapp.scss- Global styles
package.json- Dependencies and scriptsangular.json- Angular CLI configurationtsconfig.json- TypeScript configuration