Introduction

A booking calendar is the heart of any scheduling or appointment system. Users expect to see availability in real-time, interact with slots, and make bookings without refreshing the page.

By combining FullCalendar.js, a powerful JavaScript library for interactive calendars, with the WordPress REST API, we can create a fully dynamic booking calendar that integrates seamlessly into WordPress.

This guide walks you through the architecture, implementation, and customization of a scalable booking calendar system.

Why Use FullCalendar with WordPress?

FullCalendar.js provides:

  • Drag-and-drop support for events.
  • Day, week, and month views.
  • Recurring events and resources.
  • AJAX-powered updates.
  • Timezone and localization support.

When paired with the WordPress REST API, you can:

  • Fetch bookings in real time.
  • Display service/staff availability dynamically.
  • Allow users to create, update, or cancel bookings without reloading.

Step 1: Setting Up a Booking Post Type

First, register a Booking Custom Post Type (CPT) in WordPress:

function register_booking_post_type() {
    register_post_type('bookings', [
        'labels' => [
            'name' => __('Bookings', 'bookwp'),
            'singular_name' => __('Booking', 'bookwp'),
        ],
        'public' => false,
        'show_ui' => true,
        'supports' => ['title'],
        'menu_icon' => 'dashicons-calendar-alt',
    ]);
}
add_action('init', 'register_booking_post_type');

Each booking will store:

  • Service
  • Staff
  • Start time
  • End time
  • Status

Step 2: Exposing Bookings via WP REST API

Use WordPress’s REST API to serve booking data:

function register_booking_rest_routes() {
    register_rest_route('bookwp/v1', '/bookings', [
        'methods' => 'GET',
        'callback' => 'get_bookings',
    ]);
}
add_action('rest_api_init', 'register_booking_rest_routes');

function get_bookings() {
    $args = [
        'post_type' => 'bookings',
        'post_status' => 'publish',
        'numberposts' => -1,
    ];
    $bookings = get_posts($args);

    $events = [];
    foreach ($bookings as $booking) {
        $events[] = [
            'id'    => $booking->ID,
            'title' => get_the_title($booking),
            'start' => get_post_meta($booking->ID, 'start_time', true),
            'end'   => get_post_meta($booking->ID, 'end_time', true),
        ];
    }
    return $events;
}

This endpoint (/wp-json/bookwp/v1/bookings) provides events for FullCalendar.

Step 3: Adding FullCalendar.js to WordPress

Enqueue the FullCalendar scripts and styles:

function enqueue_fullcalendar_assets() {
    wp_enqueue_script('fullcalendar', 'https://cdn.jsdelivr.net/npm/fullcalendar@6.1.8/index.global.min.js', [], null, true);
    wp_enqueue_style('fullcalendar-style', 'https://cdn.jsdelivr.net/npm/fullcalendar@6.1.8/index.global.min.css');
    wp_enqueue_script('booking-calendar', plugin_dir_url(__FILE__) . 'assets/js/booking-calendar.js', ['fullcalendar'], null, true);

    wp_localize_script('booking-calendar', 'bookwpData', [
        'restUrl' => esc_url(rest_url('bookwp/v1/bookings')),
    ]);
}
add_action('wp_enqueue_scripts', 'enqueue_fullcalendar_assets');

Step 4: Rendering the Calendar in JavaScript

In booking-calendar.js:

document.addEventListener('DOMContentLoaded', function() {
    const calendarEl = document.getElementById('booking-calendar');

    const calendar = new FullCalendar.Calendar(calendarEl, {
        initialView: 'timeGridWeek',
        events: bookwpData.restUrl, // Fetch from WP REST API
        selectable: true,
        editable: true,
        eventClick: function(info) {
            alert('Booking: ' + info.event.title);
        },
        select: function(info) {
            alert('Selected time: ' + info.startStr + ' to ' + info.endStr);
        }
    });

    calendar.render();
});

Add a shortcode to render the calendar container:

function booking_calendar_shortcode() {
    return '<div id="booking-calendar"></div>';
}
add_shortcode('booking_calendar', 'booking_calendar_shortcode');

Step 5: Adding Booking Creation & Updates

To allow users to create bookings:

  • Use the select callback in FullCalendar.
  • Call a custom REST endpoint (POST /bookings) to save the booking.
  • Update the calendar dynamically with calendar.addEvent().

Example select handler:

select: function(info) {
    fetch(bookwpData.restUrl, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
            title: 'New Booking',
            start: info.startStr,
            end: info.endStr,
        })
    })
    .then(res => res.json())
    .then(data => {
        calendar.addEvent(data); // Render new event
    });
}

Step 6: Customization & Advanced Features

Enhance your calendar with:

  • Color coding by service or staff.
  • Recurring availability patterns.
  • Drag-and-drop rescheduling (using eventDrop).
  • External system integration (Google Calendar, Outlook).
  • Timezone handling for global businesses.

Conclusion

By integrating FullCalendar.js with the WordPress REST API, you can create a powerful, real-time booking calendar that’s interactive, scalable, and user-friendly.