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

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)
  • 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: /admin and 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-parser library 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: ioredis for Redis connections
  • Data Structure:
    • Albums stored as JSON array in albums key
    • Photos stored per album in photos:{albumId} keys
    • No SQL database required

Deployment

  • Platform: Vercel
  • Environment:
    • BLOB_READ_WRITE_TOKEN: Vercel Blob access
    • KV_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

  1. Land on homepage โ†’ See random featured photo
  2. View interactive world map with photo locations
  3. Browse albums (newest expanded by default)
  4. Click photo โ†’ Open lightbox viewer
  5. Navigate with arrows or keyboard
  6. Subscribe to RSS feed for updates

Admin Journey

  1. Navigate to /admin โ†’ Vercel auth redirect
  2. View dashboard with all albums and photo counts
  3. Create new album: Click “Create Album” โ†’ Fill form โ†’ Set privacy
  4. Upload photos: Click “Upload Photos” โ†’ Drag files โ†’ Add captions โ†’ Upload
  5. Manage photos: Click photo count badge โ†’ View grid โ†’ Delete unwanted photos
  6. Edit album: Click “Edit” โ†’ Update metadata/privacy โ†’ Save
  7. 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

โœด๏ธ Also on Micro.blog โœ๏ธ Reply by email ๐Ÿฆฃ Reply with Mastodon