A performant image gallery + image editor built with React and TypeScript that fetches and displays images from the Lorem Picsum API. Includes client-side caching (IndexedDB), pagination, and a responsive grid layout.
- React 19 - UI library with hooks and functional components
- TypeScript - Type-safe development
- Vite - Fast build tool and dev server
- React Router - Client-side routing for SPA navigation
- Context API - Global state management for database operations
- IndexedDB - Client-side database for caching image metadata
- Custom Hooks - Encapsulated business logic (
usePicsumImages,useImageDatabase)
- Material-UI (MUI) - React component library for consistent UI design
- ESLint - Code linting and quality checks
- TypeScript - Type checking
- Pre-commit Hooks - Automated code quality checks before commits
- Vitest - Unit testing framework
- React Testing Library - Component testing utilities
src/
โโโ App.tsx # Gallery route wrapper
โโโ App.css # Global styles
โโโ main.tsx # App entry point + routes + providers
โโโ constants.ts # API domains, limits, and config
โโโ components/
โ โโโ error-boundary/
โ โโโ image-grid/ # Gallery page (grid, cards, pagination)
โ โ โโโ hooks/
โ โ โโโ sequential-image.tsx # Sequential image preloading + skeleton
โ โโโ image-editor/ # Editor route
โ โโโ hooks/
โ โโโ image-editor.tsx
โโโ context/
โ โโโ image-database/ # IndexedDB provider + hook
โโโ lib/
โ โโโ database/ # IndexedDB implementation
โโโ shared/
โ โโโ hooks/
โโโ test/
โ โโโ setup.ts # Vitest setup
โโโ utils/ # URL helpers, preloading, networking
- Paginated Loading - Efficient loading with configurable page size using MUI Pagination
- Blob Storage - Automatically resolves the redirect download_url from picsum API response to CDN and stores the image blob
- Image Editor - Real-time image manipulation with blur, grayscale, and dimension controls
- MUI Card Components - Image cards with elevation and hover effects
- Loading Skeletons - MUI Skeleton components for loading states
- Responsive Grid - MUI Grid container for responsive layouts
- Pagination Controls - MUI Pagination component for navigation
- IndexedDB Caching - Stores image metadata locally for offline access and faster loads
- Bulk Insert Operations - Efficient batch database operations
- Page-based Indexing - Optimized retrieval by page number
- Request Deduplication - Cancels in-flight requests when new ones are initiated
- Background Processing - Stores data asynchronously without blocking UI updates
- MUI Tree-shaking - Optimized MUI component imports for smaller bundle size (avoid barrel imports)
- Sequential Loading - Images load in order for better perceived performance
- Debounced Settings - Prevents excessive re-renders in the editor
- Node.js 18+
- Package manager:
bun(recommended) ornpm
# Clone the repository
git clone https://github.com/alex-rantos/react-picsum.git
cd react-picsum
# Install dependencies
bun install
# Start development server
bun run dev
# (Optional) If you prefer npm
# npm install
# npm run dev# Clone the repository
git clone https://github.com/alex-rantos/react-picsum.git
cd react-picsum
# Install dependencies
bun install
# Build
bun run build
# Start Preview
bun run previewbun run dev # Start development server
bun run build # Typecheck (tsc -b) + Vite build
bun run preview # Preview production build
bun run lint # Run ESLint
bun run test # Run unit tests (Vitest)
bun run prettier # Format files/images/:pageโ paginated gallery view/edit/:imageโ image editor
The app redirects / โ /images/1.
This project uses pre-commit hooks to ensure code quality:
- Pre-commit - Runs automatically before each commit
- Formats staged files with Prettier
- Lints (and auto-fixes when possible) with ESLint
To bypass hooks in emergency situations (not recommended):
git commit --no-verifyThe application uses Vite for building.
graph TB
Start([User Opens App]) --> Router{Route?}
Router -->|"/"| Gallery[Image Gallery Page]
Router -->|"/edit/:image"| Editor[Image Editor Page]
Gallery --> CheckDB[Check IndexedDB Cache]
CheckDB -->|Cache Hit| LoadCached[Load from IndexedDB]
CheckDB -->|Cache Miss| FetchAPI[Fetch from Picsum API]
FetchAPI --> ResolveRedirect[Resolve CDN Redirects/Get Blobs]
ResolveRedirect --> StoreDB[Store in IndexedDB]
StoreDB --> RenderGrid[Render Image Grid]
LoadCached --> RenderGrid
RenderGrid --> UserAction{User Action}
UserAction -->|Click Image| NavigateEdit[Navigate to Editor]
UserAction -->|Change Page| Gallery
NavigateEdit --> Editor
Editor --> LoadImage[Load Image Data]
LoadImage --> CheckEditorDB[Check IndexedDB]
CheckEditorDB -->|Found| DisplayEditor[Display Editor UI]
CheckEditorDB -->|Not Found| FetchMeta[Fetch Metadata]
FetchMeta --> FetchBlob[Fetch Image Blob]
FetchBlob --> DisplayEditor
DisplayEditor --> EditControls[Show Controls]
EditControls --> UserEdit{User Edits}
UserEdit -->|Adjust Settings| Debounce[Debounce Changes]
Debounce --> GenerateURL[Generate New Picsum URL]
GenerateURL --> UpdatePreview[Update Preview]
UpdatePreview --> UserEdit
The app integrates with Lorem Picsum API:
- List Endpoint:
https://picsum.photos/v2/list - Image Endpoint:
https://picsum.photos/id/{id}/{width}/{height} - CDN Domain:
fastly.picsum.photos - Support for query parameters:
blur(0-10),grayscale
- E2E Testing - Add Playwright for paging + editor flows
- Theme - Add dark mode toggle (MUI theme switching)
- Backend Proxy - Add backend service for API caching and rate limiting
- Performance Monitoring - Add Web Vitals tracking
- Storybook - Component documentation and testing with MUI theme integration
- Progressive Web App - Add service worker for offline functionality
- Better Error Handling - Fallback UIs and user friendly error messages
- Client Throttling - Add client throttling matching our backend throttling
- Localization - Translation & RTL support
- Search & Filtering - Add ability to search images by author or filter by dimensions
- Better UI/UX & Accessibility - Enhanced color contrast, ARIA labels, keyboard navigation
- MUI Dark Mode - Implement theme switching with MUI's theme system
- Infinite Scroll - Replace pagination with infinite scrolling using MUI components & possibly intersection observer
- None tracked currently. If you hit something, please open an issue with steps to reproduce.
MIT