Asking Claude Code to suggest new features and improvements for my photo-sharing app is a lot of fun. Reviewing the list, I see several valid suggestions. However, as a “product manager”, I must decide what gets implemented and what does not. It’s kind of a power trip. You know “A thousand no for each yes”? ๐
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
This weekend, I wanted to work on my next YouTube video, but I fell into this “photo-sharing website for my close family and friends” rabbit hole. It took most of the day to refine that I completely forgot about my video. ๐คฆ๐ปโโ๏ธ
Miniroll: what a great idea, and a well-designed one above all. Is it for me? I don’t know. I barely update my blogroll on Micro.blog. I’ll certainly keep an eye on the changelog to see where it’s going, and who knows…
Looking at my Micro.blog timeline summary I see this bad interpretation of my words in a recent post about updating my Nikon camera firmware from 1.21 to 3.0. ๐คท๐ปโโ๏ธ๐คฆ๐ปโโ๏ธ
“Please, add a map of all the places I visited based on photo metadata”. “Add animation across the site to make it more dynamic, nothing too fancy”. “Please, add support for progressive web app and make sure to set the favicon with the provided image”. “Add support for swipe gestures (ledt and right) while glancing at individual image”. “Add a counter of how many images are stored in each album”.
Are you getting it?
This is simple web app development in 2026 built using Claude Code, Vercel, Next.js and Tailwind CSS. ๐คฏ
Out of curiosity, yesterday I asked ChatGPT what the latest firmware release was for my Nikon Z f camera: 3.0 (it was at 1.21)! I applied the 110 mb binary update right on time for my upcoming trip. Yes, I know, my camera needs a little cleanup, too.
Building A Dedicated Photo-Sharing Website in Claude Code
Thinking about the upcoming trip to Egypt, I realized I still didn’t have a good solution for sharing photos and comments beyond the usual social networks. Drawing on my experience from the past few weeks deploying web applications on Vercel, I decided to try the same by building a website for sharing and viewing photos. The additional complexity here is that the viewing portion is separate from the photo upload section. Therefore, I need to protect this feature with a password. Additionally, image storage must be optimized to minimize costs and provide a pleasant, flexible viewing experience. I’m using Vercel-only blog storage and Redis for metadata store.
In less than 2 hours, I built a fully functional application with Claude Code and Vercel. Impressive.
How long will it take Apple to fix the Apple Watch setup process involving restoring from previous backups? It’s been an issue for many people for years! My setup process when I upgraded from Series 6 to Series 8 was hindered by this issue. Same when I upgraded from Series 8 to Series 10. Either the backup found wasn’t recent, or there was no backup to restore from. Michael Tsai is one such person. Anyone at Apple is setting up a new watch? ๐ค
First visit to the new Ste-Catherine Apple Store in downtown Montreal. It’s quite a different vibe than the previous store. More to come in a short article.