next.jstailwindCSStypescriptpayload-cmsmongodbs3vercelbooking-systemcalendar-integration

Advanced Vacation Rental Platform with Real-Time Booking System

Duration
2 Months
Role
Full-Stack Developer, System Architect, UI/UX Designer
Happy am Meer vacation rental platform
Happy am Meer vacation rental platform
Real-time booking calendar system
Real-time booking calendar system
Payload CMS admin panel with property management
Payload CMS admin panel with property management
Lighthouse performance scores
Lighthouse performance scores

Happy am Meer Vacation Rental Platform

The Happy am Meer platform represents a sophisticated vacation rental management system built for a German vacation rental company expanding into vacation rentals. This production-ready platform features a comprehensive booking system with real-time availability, external calendar integration, and advanced property management capabilities.

The system is designed for scalability and performance, handling complex booking scenarios with automated external calendar synchronization (Airbnb, Booking.com, VRBO) every 2 hours. The mobile-first design provides an exceptional user experience with a sticky booking bar and full-screen modal calendar interface.

This platform demonstrates advanced headless CMS architecture with real-time booking capabilities, achieving 92-95 Lighthouse performance scores while maintaining complex functionality.

The implementation showcases modern web development practices with Payload CMS, Next.js 15, and React 19, delivering a vacation rental experience that significantly exceeds industry standards.

Key Features

  • Advanced real-time booking calendar with multi-mode interface
  • Automated external calendar synchronization (Airbnb, Booking.com, VRBO)
  • Mobile-optimized booking experience with sticky bar and modal calendar
  • Comprehensive property management with seasonal pricing
  • Block-based content management system with 13 flexible blocks
  • Advanced caching system with LRU eviction for optimal performance
  • Background job processing with Vercel cron jobs
  • Cross-page session persistence for booking data
  • Email automation for booking inquiries and notifications
  • SEO optimization with vacation rental structured data

Tech Stack Overview

This project leverages a modern, production-ready technology stack:

  • Next.js 15: App Router with server-side rendering for optimal SEO
  • React 19.1.0: Latest React with server components and enhanced performance
  • TypeScript 5.6.3: Strict type checking throughout the codebase
  • Payload CMS 3.36.0: Headless CMS with block-based content architecture
  • MongoDB Atlas: Document database for flexible content and booking data
  • S3 Storage: Media asset management with automatic optimization
  • TailwindCSS 3.4.3: Utility-first CSS with custom design system
  • Shadcn UI: Radix UI-based component library for accessibility
  • Vercel: Deployment platform with cron job support for background processing
  • Framer Motion 12.9.2: Performance-optimized animations
  • React Hook Form 7.45.4: Form handling with validation
  • Sharp 0.32.6: Image optimization and processing
  • Nodemailer: Email automation for booking notifications

Project Structure

The project follows a sophisticated, scalable architecture:

.
├── public/                 # Static assets and media
│   ├── media/             # Uploaded content via Payload CMS
│   └── favicon.ico        # Site favicon
├── src/                   # Source code
│   ├── app/              # Next.js app router
│   │   ├── (frontend)/   # Public-facing pages
│   │   │   ├── ferienhaeuser/  # Vacation rental pages
│   │   │   ├── verfuegbarkeit/ # Availability calendar
│   │   │   └── ...       # Other public pages
│   │   ├── (payload)/    # Payload CMS admin panel
│   │   └── api/          # API routes
│   │       ├── ferienhaeuser-api/  # Property management APIs
│   │       ├── booking-inquiry/    # Booking system APIs
│   │       ├── ical-sync/          # External calendar sync
│   │       └── ...       # Other API endpoints
│   ├── blocks/           # Content blocks for CMS
│   │   ├── ArchiveBlock/ # Content listings
│   │   ├── Banner/       # Promotional content
│   │   ├── CallToAction/ # Conversion elements
│   │   └── ...           # 13 total content blocks
│   ├── collections/      # Payload CMS collections
│   │   ├── Ferienhaeuser/    # Property management
│   │   ├── Availability/     # Booking availability
│   │   ├── BookingInquiries/ # Guest inquiries
│   │   └── ...           # 10 total collections
│   ├── components/       # React components
│   │   ├── booking-calendar/ # Booking system components
│   │   ├── ui/           # UI components (Shadcn)
│   │   └── ...           # Feature components
│   ├── lib/              # Utility functions and configurations
│   │   ├── booking-data.ts      # Booking data types
│   │   ├── calendar-cache.ts    # Advanced caching system
│   │   └── ...           # Other utilities
│   └── payload.config.ts # Payload CMS configuration

Advanced Booking System Architecture

The booking system features a sophisticated multi-layered architecture:

  1. Real-Time Availability Checking

    • Live availability queries with < 200ms response times
    • Conflict detection with external booking platforms
    • Advanced caching with LRU eviction for optimal performance
    • 5-minute availability cache, 30-minute pricing cache
  2. External Calendar Integration

    • Automated synchronization with Airbnb, Booking.com, VRBO
    • iCal parsing and processing with conflict resolution
    • Background sync every 2 hours via Vercel cron jobs
    • Smart scheduling based on sync frequency settings
  3. Mobile Booking Experience

    • Sticky booking bar appearing after 400px scroll
    • Full-screen modal calendar with comprehensive scroll prevention
    • Touch-optimized interactions for mobile devices
    • Cross-page session persistence for booking data
  4. Property Management System

    • Complete property listings with detailed information
    • Seasonal pricing with "highest price wins" logic
    • Image galleries and amenity management
    • German localization for vacation rental market

CODE SNIPPETS

Payload CMS Configuration

The Payload CMS configuration demonstrates advanced headless CMS architecture:

// Core Collections Configuration
collections: [
  // Original Collections
  Pages, Posts, Products, Media, ImageSlider, Categories, Users,

  // Vacation Rental Collections
  Ferienhaeuser, PropertyAmenities, Availability, BookingInquiries,
],

// Live Preview Configuration
livePreview: {
  breakpoints: [
    { label: 'Mobile', width: 375, height: 667 },
    { label: 'Tablet', width: 768, height: 1024 },
    { label: 'Desktop', width: 1440, height: 900 },
  ],
  url: 'https://happy-am-meer.vercel.app/',
  collections: ['pages', 'posts', 'products', 'ferienhaeuser'],
},

// Storage Configuration
storage: s3Storage({
  collections: {
    media: {
      prefix: 'media',
      bucket: process.env.S3_BUCKET,
      endpoint: process.env.S3_ENDPOINT,
      region: process.env.S3_REGION,
    },
  },
}),

Booking Calendar API Implementation

The booking system features comprehensive API endpoints:

// Availability Checking API
export async function POST(request: NextRequest) {
  try {
    const { propertyIds, checkIn, checkOut, guests } = await request.json();

    // Real-time availability checking
    const availability = await checkAvailability({
      propertyIds,
      checkIn,
      checkOut,
      guests,
    });

    // Conflict detection with external calendars
    const conflicts = await detectConflicts(availability);

    // Dynamic pricing calculation
    const pricing = await calculatePricing({
      propertyIds,
      checkIn,
      checkOut,
      guests,
    });

    return NextResponse.json({
      success: true,
      data: { availability, conflicts, pricing },
      cache: { ttl: 300, hit: true },
    });
  } catch (error) {
    return NextResponse.json(
      { success: false, error: error.message },
      { status: 500 }
    );
  }
}

Advanced Calendar Synchronization System

The platform features a sophisticated multi-layered calendar synchronization system:

// Core Calendar Sync Library - src/lib/syncCalendars.ts
interface SyncCalendarResult {
  success: boolean;
  syncedBookings: number;
  errors: number;
  message?: string;
  data?: any;
}

interface CalendarEvent {
  summary: string;
  dtstart: Date;
  dtend: Date;
  uid: string;
  description: string;
}

/**
 * Parse iCal data and extract events with robust error handling
 */
const parseICalData = (icalData: string): CalendarEvent[] => {
  const events: CalendarEvent[] = [];
  const lines = icalData.split('\n').map((line) => line.trim());

  let currentEvent: Partial<CalendarEvent> | null = null;
  let isInEvent = false;

  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];

    if (line === 'BEGIN:VEVENT') {
      isInEvent = true;
      currentEvent = {
        summary: '',
        dtstart: new Date(),
        dtend: new Date(),
        uid: '',
        description: '',
      };
    } else if (line === 'END:VEVENT' && isInEvent && currentEvent) {
      if (currentEvent.dtstart && currentEvent.dtend) {
        events.push(currentEvent as CalendarEvent);
      }
      currentEvent = null;
      isInEvent = false;
    } else if (isInEvent && currentEvent) {
      if (line.startsWith('SUMMARY:')) {
        currentEvent.summary = line.substring(8);
      } else if (line.startsWith('DTSTART')) {
        const dateValue =
          line.split(':')[1] || line.split('=')[line.split('=').length - 1];
        currentEvent.dtstart = parseICalDate(dateValue);
      } else if (line.startsWith('DTEND')) {
        const dateValue =
          line.split(':')[1] || line.split('=')[line.split('=').length - 1];
        currentEvent.dtend = parseICalDate(dateValue);
      } else if (line.startsWith('UID:')) {
        currentEvent.uid = line.substring(4);
      } else if (line.startsWith('DESCRIPTION:')) {
        currentEvent.description = line.substring(12);
      }
    }
  }

  return events;
};

/**
 * Fetch iCal data with timeout and proper error handling
 */
const fetchICalData = async (
  url: string,
  timeoutMs: number = 15000
): Promise<string> => {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeoutMs);

  try {
    const response = await fetch(url, {
      headers: {
        'User-Agent': 'Happy-am-Meer Calendar Sync/1.0',
        Accept: 'text/calendar,application/calendar,text/plain',
      },
      signal: controller.signal,
    });

    clearTimeout(timeoutId);

    if (!response.ok) {
      throw new Error(`HTTP ${response.status}: ${response.statusText}`);
    }

    const contentType = response.headers.get('content-type') || '';
    if (!contentType.includes('calendar') && !contentType.includes('text')) {
      throw new Error(`Invalid content type: ${contentType}`);
    }

    return await response.text();
  } catch (error) {
    clearTimeout(timeoutId);

    if (error instanceof Error) {
      if (error.name === 'AbortError') {
        throw new Error(`Request timeout after ${timeoutMs}ms`);
      }
      throw new Error(`Failed to fetch iCal data: ${error.message}`);
    }

    throw new Error('Failed to fetch iCal data: Unknown error');
  }
};

This implementation provides:

  • Non-intrusive booking bar appearing after user engagement
  • Full-screen modal calendar with complete booking functionality
  • Comprehensive scroll prevention for focused booking experience
  • Touch-optimized interactions for mobile devices