I'm rebuilding Flickr!
Well, maybe not, but here’s a description of my recently created photo-sharing webapp. And I have many more ideas to improve this.
Photo Sharing WebApp - Feature Overview
A modern, full-stack travel photo gallery built with Next.js 15, featuring intelligent photo management, interactive maps, and seamless cloud storage integration.
๐ Highlights
- Zero-Database Architecture: Uses Vercel Blob for photos and Redis (via Vercel KV) for metadata
- Privacy Controls: Public, unlisted, and private album visibility options
- Interactive World Map: Displays photo locations extracted from EXIF GPS data
- Responsive Design: Optimized for all devices from mobile to desktop
- Admin Panel: Complete photo management without leaving the browser
๐จ Public Gallery Features
Album Management
- Collapsible Albums: Each travel album can be expanded or collapsed independently
- Smart Defaults: Most recent album automatically expands on page load
- Album Metadata: Title, description, and date for each collection
- Privacy Levels:
- Public: Visible to everyone on the homepage
- Unlisted: Only accessible via direct link
- Private: Visible only to authenticated admins
Photo Display
- Grid Layout Options: Three display modes to suit your preference
- Comfortable: Spacious 2-5 column grid with square thumbnails
- Compact: Dense 3-6 column grid for maximum photos per screen
- Masonry: Pinterest-style layout preserving original aspect ratios
- Layout Persistence: Grid preference saved in browser localStorage
- Newest First: Photos automatically sorted by upload date (newest at top-left)
- Rounded Thumbnails: Modern, elegant aesthetic with subtle shadows
- Hover Effects: Smooth scale and brightness animations on interaction
- Upload Date Display: Shows when each photo was added (in comfortable/masonry modes)
Lightbox Viewer
- Full-Screen Experience: Distraction-free photo viewing
- Navigation Controls:
- Keyboard arrows (โ โ) for previous/next
- On-screen navigation buttons
- ESC key to close
- Photo Captions: Optional descriptions displayed below photos
- Smooth Transitions: Animated photo changes with loading states
- Mobile Optimized: Touch-friendly controls and responsive sizing
Interactive Features
- World Map Integration:
- Leaflet-based interactive map
- Clustered markers for photos with GPS coordinates
- Click markers to view photos from that location
- Automatic bounds fitting to show all locations
- Album information in marker popups
- Random Featured Photo:
- Displays a random photo from all albums on homepage
- Changes on each page load
- Shows caption if available
- Mini Thumbnails:
- Collapsed albums show preview of first 5 photos
- Smooth animation on expand/collapse
- Photo count badge for albums with 6+ photos
Content Syndication
- RSS Feed: Subscribe to new photo uploads at
/feed.xml - Analytics: Vercel Analytics integration for visitor tracking
๐ Admin Panel Features
Authentication
- Vercel Authentication: Secure login using your Vercel account
- Protected Routes:
/adminand sub-routes require authentication - Session Management: Logout functionality with redirect
Album Management
- Create Albums:
- Title (required)
- Description (optional)
- Date (optional, ISO format)
- Privacy setting (public/unlisted/private)
- Edit Albums:
- Update all metadata including privacy settings
- Inline editing interface
- Cancel without saving
- Delete Albums:
- Confirmation dialog before deletion
- Automatically deletes all photos in album
- Removes both metadata and blob files
Photo Management
- Bulk Upload:
- Multi-file selection support
- Drag-and-drop interface
- Progress tracking for each file
- Batch processing with individual status indicators
- Total size calculation before upload
- Upload Features:
- Automatic EXIF extraction (GPS, camera, capture settings)
- Optional captions (for single photo uploads)
- Format support: JPG, PNG, WebP, and more
- Visual upload progress bar
- Success/error status for each file
- Photo Organization:
- Clickable photo count badges link to management page
- Grid view of all photos in an album
- Displays metadata: upload date, GPS, camera info
- Empty state with call-to-action
- Delete Photos:
- Individual photo deletion from management page
- Confirmation dialog with photo caption
- Removes both Vercel Blob file and metadata
- Instant UI update on successful deletion
Admin Dashboard
- Album Overview:
- List of all albums (sorted by date, newest first)
- Photo count for each album
- Privacy status indicators with icons
- Quick access buttons (Edit, Upload, Manage, Delete)
- Status Indicators:
- ๐ Public: Green badge with globe icon
- ๐ Unlisted: Yellow badge with link icon
- ๐ Private: Red badge with lock icon
- Responsive Layout: Optimized for tablet and mobile management
๐ ๏ธ Technical Architecture
Frontend
- Framework: Next.js 15 with App Router
- Language: TypeScript for type safety
- Styling: Tailwind CSS with custom configurations
- Icons: Lucide React for consistent iconography
- Image Optimization: Next.js Image component with automatic optimization
- State Management: React hooks (useState, useEffect)
- Client-Side Rendering: Dynamic imports for map components (SSR bypass)
Backend
- API Routes: Next.js server-side API endpoints
- File Upload: FormData with multipart handling
- EXIF Parsing:
exif-parserlibrary for metadata extraction - Image Processing: Automatic format conversion and compression
Storage & Database
- Photo Storage: Vercel Blob (CDN-backed object storage)
- Metadata Storage: Redis via Vercel KV Marketplace integration
- Database Client:
ioredisfor Redis connections - Data Structure:
- Albums stored as JSON array in
albumskey - Photos stored per album in
photos:{albumId}keys - No SQL database required
- Albums stored as JSON array in
Deployment
- Platform: Vercel
- Environment:
BLOB_READ_WRITE_TOKEN: Vercel Blob accessKV_REDIS_URL: Redis connection string
- CDN: Automatic edge caching for photos and pages
- Domain: Custom domain support with automatic SSL
๐ Data Models
Album
{
id: string; // album_timestamp_random
title: string; // "Japan 2025"
description: string; // Trip description
date: string; // ISO date "2025-01-15"
createdAt: number; // Unix timestamp
visibility: "public" | "unlisted" | "private";
}
Photo
{
id: string; // photo_timestamp_random
albumId: string; // Reference to album
blobUrl: string; // Vercel Blob URL
caption?: string; // Optional description
uploadedAt: number; // Unix timestamp
metadata?: {
gps?: {
latitude: number;
longitude: number;
altitude?: number;
};
camera?: {
make?: string; // "Canon"
model?: string; // "EOS R5"
lens?: string;
};
capture?: {
dateTaken?: string; // When photo was taken
exposureTime?: string; // "1/1000"
fNumber?: number; // 2.8
iso?: number; // 100
focalLength?: number; // 50mm
};
dimensions?: {
width: number;
height: number;
};
orientation?: number;
};
}
๐ฏ User Flows
Visitor Journey
- Land on homepage โ See random featured photo
- View interactive world map with photo locations
- Browse albums (newest expanded by default)
- Click photo โ Open lightbox viewer
- Navigate with arrows or keyboard
- Subscribe to RSS feed for updates
Admin Journey
- Navigate to
/adminโ Vercel auth redirect - View dashboard with all albums and photo counts
- Create new album: Click “Create Album” โ Fill form โ Set privacy
- Upload photos: Click “Upload Photos” โ Drag files โ Add captions โ Upload
- Manage photos: Click photo count badge โ View grid โ Delete unwanted photos
- Edit album: Click “Edit” โ Update metadata/privacy โ Save
- Delete album: Click “Delete” โ Confirm โ Album and all photos removed
๐ Performance Optimizations
- Image Optimization: Next.js automatic WebP conversion and lazy loading
- CDN Caching: Vercel Edge Network caches photos globally
- Code Splitting: Dynamic imports for heavy components (map)
- Responsive Images: Multiple sizes served based on viewport
- Minimal JavaScript: Client-side JS only where needed
- Fast Page Loads: Static generation where possible
- Efficient Queries: Single Redis calls for album/photo lists
- LocalStorage: Grid layout preference cached client-side
๐จ Design Philosophy
Visual Design
- Color Palette: Blue gradient accents with dark mode support
- Typography: Clear hierarchy with responsive font sizes
- Spacing: Generous whitespace for comfortable reading
- Shadows: Layered depth with hover elevations
- Animations: Subtle 300ms transitions throughout
- Icons: Consistent Lucide icon library
User Experience
- Progressive Disclosure: Collapsed albums reduce cognitive load
- Keyboard Navigation: Full keyboard support in lightbox
- Touch Optimization: Tap targets sized for mobile
- Loading States: Spinners and skeletons during data fetches
- Error Handling: User-friendly error messages
- Confirmation Dialogs: Prevent accidental deletions
Accessibility
- Semantic HTML: Proper heading hierarchy
- Focus States: Visible keyboard focus indicators
- Alt Text: Image descriptions for screen readers
- Color Contrast: WCAG AA compliance
- Responsive Design: Works on all screen sizes
๐ Use Cases
Personal Travel Blog
- Document trips with organized photo albums
- Share adventures with family and friends
- Keep private memories secure with privacy controls
Photography Portfolio
- Showcase work by location or project
- Professional presentation with grid layouts
- Metadata display for technical details
Family Photo Sharing
- Create unlisted albums for family-only access
- Easy upload from mobile devices
- No complicated software required
Educational Projects
- Demonstrate modern web development practices
- Showcase Next.js 15 App Router patterns
- Example of cloud storage integration
๐ฎ Future Enhancement Ideas
Photo Features
- Bulk photo deletion (select multiple)
- Photo reordering (drag-and-drop)
- Photo editing (crop, rotate, filters)
- Download full-resolution images
- Print/photo book export
Search & Discovery
- Full-text search across captions
- Tag system for categorization
- Timeline view (chronological)
- Favorites/highlights collection
Social Features
- Photo comments system
- Social media share buttons
- Individual photo permalinks
- Public photo embeds
Analytics
- View count tracking
- Popular photos dashboard
- Storage usage metrics
- Visitor analytics
Mobile App
- Native iOS/Android apps
- Offline photo viewing (PWA)
- Camera integration for uploads
- Push notifications for new albums
๐ก Why This Architecture?
Serverless-First
- No server maintenance: Vercel handles infrastructure
- Auto-scaling: Handles traffic spikes automatically
- Global CDN: Photos served from edge locations
- Cost-effective: Pay only for usage
Modern Stack
- Type Safety: TypeScript catches bugs at compile time
- React 19: Latest React features and optimizations
- Next.js 15: App Router for improved performance
- Tailwind CSS: Utility-first styling for rapid development
Cloud Storage
- Vercel Blob: Purpose-built for media storage
- Redis: Fast key-value storage for metadata
- No database: Simpler architecture, fewer failure points
- Atomic operations: Redis ensures data consistency
๐ Technical Decisions
Why ioredis instead of @vercel/kv?
The Vercel KV Marketplace integration provides a standard Redis URL, which works better with the ioredis package. This offers more flexibility and standard Redis features.
Why client-side rendering for the homepage?
The random featured photo and map interactions require JavaScript. Client-side rendering provides the most interactive experience while keeping the codebase simple.
Why separate manage page instead of edit-in-place?
Separating photo management from display keeps each view focused and performant. The upload page stays lightweight for quick uploads, while the manage page provides detailed controls.
Why not use a traditional database?
For a photo gallery, the access patterns are simple (list albums, list photos). Redis provides sub-millisecond reads and sufficient storage for metadata, while Vercel Blob handles the large files. This eliminates the need for PostgreSQL/MySQL.
๐๏ธ Project Structure
voyages-photo-gallery/
โโโ app/
โ โโโ admin/
โ โ โโโ manage/[albumId]/ # Photo management page
โ โ โโโ upload/[albumId]/ # Photo upload page
โ โ โโโ page.tsx # Admin dashboard
โ โโโ api/
โ โ โโโ admin/
โ โ โ โโโ albums/
โ โ โ โ โโโ [albumId]/ # Update/delete album
โ โ โ โ โโโ route.ts # Create album
โ โ โ โโโ photos/
โ โ โ โ โโโ route.ts # Delete photo
โ โ โ โโโ upload/
โ โ โ โโโ route.ts # Upload photos
โ โ โโโ albums/
โ โ โ โโโ route.ts # Get all albums (public)
โ โ โโโ photos/
โ โ โ โโโ route.ts # Get all photos (public)
โ โ โโโ auth/ # Login/logout
โ โโโ feed.xml/
โ โ โโโ route.ts # RSS feed generation
โ โโโ layout.tsx # Root layout with Analytics
โ โโโ page.tsx # Public gallery homepage
โ โโโ globals.css # Global styles
โโโ components/
โ โโโ AlbumSection.tsx # Collapsible album component
โ โโโ GridLayoutToggle.tsx # Layout switcher
โ โโโ Lightbox.tsx # Photo viewer
โ โโโ WorldMap.tsx # Interactive map
โโโ lib/
โ โโโ db.ts # Redis database functions
โโโ types/
โ โโโ index.ts # TypeScript type definitions
โโโ middleware.ts # Auth protection
โโโ package.json # Dependencies
๐ Learning Resources
This project demonstrates:
- Next.js 15 App Router patterns
- TypeScript in React applications
- Tailwind CSS utility-first styling
- Vercel deployment and storage
- Redis data modeling
- EXIF metadata extraction
- Responsive design principles
- File upload handling
- Authentication middleware
- Dynamic routing
- Client/server component separation
Perfect for developers learning modern full-stack web development!
๐ License
MIT License - Feel free to use this as a learning resource or starting point for your own projects.
๐ค Contributing
Built with Claude Code - AI-assisted development for rapid prototyping and feature implementation.
Technologies: Next.js 15 โข React 19 โข TypeScript โข Tailwind CSS โข Vercel โข Redis โข Leaflet
Built by: AI enthusiasts exploring the intersection of modern web development and AI-assisted coding