# Build a Booking.com-Style Availability Calendar in SwiftUI

> By Lawrence Arya, Founder & CEO of VP0. Published 2026-06-08. 8 min read.
> Source: https://vp0.com/blogs/booking-com-calendar-availability-picker-swiftui-free-ios-template-vibe-coding-g

SwiftUI's date picker is a single date, not availability. Here is how to build a real check-in to check-out availability calendar.

**TL;DR.** A Booking.com-style availability calendar is not SwiftUI's date picker. It is a custom month grid that marks each date as available, booked, or blocked, supports a check-in to check-out range with the nights between highlighted, and shows a price per night, all bound to real availability from your server. The hard part is honesty: a date shown as available that is actually booked causes double bookings. A free VP0 availability-calendar template gives an agent the grid, the range selection, and the states to extend, while you bind the real availability.

## Why a date picker is not an availability calendar

SwiftUI ships a [DatePicker](https://developer.apple.com/documentation/swiftui/datepicker), and it is the wrong tool for a booking calendar. A date picker chooses one date with no notion of whether that date is open, booked, or blocked, and it does not express a stay from a check-in date to a check-out date. A Booking.com-style availability calendar is a different thing: a custom month grid where every date carries a state, the user selects a range rather than a point, and the whole thing reflects real availability from your server. So the project is not configuring a control; it is building a calendar that knows what is bookable.

Naming that distinction early avoids a common dead end, where people try to bend the date picker into an availability grid and end up rebuilding it anyway. The grid, the states, and the range are the work.

## What an availability calendar actually shows

A real availability calendar communicates several things at a glance. Each date has a state: available, unavailable because it is booked or blocked, or in the past and therefore disabled. Available dates often show a price per night, say $120, because price is part of the booking decision. Selecting a stay means picking a check-in date and a check-out date, with the nights in between highlighted as a continuous range, and the calendar has to handle the rules that come with that, a minimum stay, blocked dates inside a desired range, and a check-out that cannot precede check-in. The month grid itself is built with SwiftUI's [layout tools](https://developer.apple.com/documentation/swiftui), and the interaction follows Apple's [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/) for selection.

The range selection is the interaction people judge it by. A calendar that only picks single dates feels broken for booking, because a stay is two dates and everything between them, and the highlight has to make that span obvious.

## The honesty problem: stale availability causes double bookings

The most important rule in an availability calendar is not visual, it is truthful. A date shown as available that is actually booked leads to a double booking, which is the worst outcome a booking product can produce, so the calendar must reflect current availability rather than a stale snapshot. That means binding the grid to live data, refreshing it when the user changes months or returns to the screen, and confirming availability again at the moment of booking rather than trusting what was painted minutes ago. Availability is also often per-property and per-night, so the calendar shows one property's real openings, not a generic month.

This is where the FINANCIAL framing matters: the calendar presents availability and price, and the actual reservation and payment happen against a backend that holds the source of truth. The screen should never imply a date is held or paid for until the system confirms it.

## How to build it: the realistic options

There are three ways to get an availability calendar, and they differ in how much of the state and range logic you build yourself.

| Option | Availability-aware | Range selection | Effort |
| --- | --- | --- | --- |
| SwiftUI DatePicker | No, a single date with no states | No, one date at a time | Low, but the wrong tool |
| Generic calendar library | Sometimes, varies by library | Often, but you wire availability and rules | Medium |
| Free availability-calendar template | Available, booked, and blocked states built in | Check-in to check-out with nights highlighted | Low, extend it and bind data |

The DatePicker route looks like a shortcut and produces a single-date control that cannot express a stay. A generic calendar library gets you a grid, but you still build the availability states, the range highlight, the price display, and the booking rules on top. A free [VP0](https://vp0.com) availability-calendar template starts you on the whole thing, with the month grid, the available, booked, and blocked states, the check-in to check-out range, and the price-per-night slot already shaped, exposed through a machine-readable source page. When you hand it to Cursor or Claude Code, the agent extends a real availability calendar and you bind it to your live data, instead of reinventing range selection and state handling. The booking-calendar pattern also appears in an [Airbnb-style booking calendar](/blogs/airbnb-booking-calendar-map-clone/) and a [salon appointment calendar](/blogs/beauty-salon-appointment-booking-calendar-ui/).

## The states that make a booking calendar trustworthy

A booking calendar feels reliable when its states are complete and honest. Past dates are disabled, not just styled differently, so they cannot be tapped. Booked and blocked dates are visibly unavailable, and a range that would cross one is prevented rather than silently allowed. A loading state covers the moment availability is being fetched, so the user does not select against stale data, and an empty state handles a property with no openings in view. The selected range shows its check-in, its check-out, and the total nights and price clearly, so the user knows exactly what they are about to book. The same date-range and ticket-state thinking appears in a [cinema ticket booking UI](/blogs/cinema-movie-ticket-booking-ui-react-native/).

These states are not polish; they are what prevents a bad booking. A calendar that lets a user select an unavailable range, or that shows availability it cannot honor, fails at the one job that matters.

## Key takeaways: a SwiftUI availability calendar

- **A date picker is not an availability calendar.** You build a custom month grid with per-date states and a range, not a single-date control.
- **Every date carries a state.** Available with a price, booked or blocked, or past and disabled.
- **Range selection is the core interaction.** Check-in to check-out with the nights between highlighted.
- **Availability must be live.** Stale data causes double bookings, so bind to current data and re-confirm at booking.
- **Start from an availability template.** A free VP0 template gives an agent the grid, the range, and the states to bind to data.

## What to choose

For a booking app, build the availability calendar from a template designed for it rather than from SwiftUI's date picker, because the per-date states, the check-in to check-out range, and the booking rules are most of the work and are easy to get wrong. A free VP0 availability-calendar template gives you the grid, the states, the range, and the price slot, so an agent extends a real calendar and you bind it to live availability and re-confirm at booking, keeping the backend as the source of truth. A generic calendar library is a reasonable middle path if you want to wire the states yourself, but the date picker alone cannot express a stay.

## Frequently asked questions

**How do I build a Booking.com-style availability calendar in SwiftUI?** Build a custom month grid rather than using SwiftUI's DatePicker, because a booking calendar needs per-date states and a range, not a single date. Mark each date as available with a price, booked or blocked, or past and disabled, support a check-in to check-out selection with the nights between highlighted, and enforce rules like a minimum stay and no range crossing a blocked date. Bind the grid to live availability and re-confirm at booking so stale data cannot cause a double booking. A free availability-calendar template gives you the grid, the range, and the states to start from.

**Can I use SwiftUI's DatePicker for a booking calendar?** Not really. DatePicker selects a single date with no concept of availability, pricing, or a stay from check-in to check-out, so it cannot express what a booking calendar needs. You can use it for a simple one-off date field, but for availability you build a custom month grid with per-date states and range selection. Trying to bend the date picker into a booking calendar usually ends in rebuilding it as a custom grid anyway, so starting from an availability template saves that detour.

**Where can I get a SwiftUI availability calendar template?** The most useful option is a template built for availability, not a generic date control. A free VP0 availability-calendar template provides the month grid, the available, booked, and blocked states, the check-in to check-out range, and the price-per-night slot, with a machine-readable source page, so an agent like Cursor or Claude Code extends a real calendar. You then bind it to your live availability data and re-confirm at booking, since the template is the interface and the source of truth is your backend.

**How do I prevent double bookings in an availability calendar?** Treat availability as live data, not a painted snapshot. Bind the calendar to current availability, refresh it when the user changes months or returns to the screen, and confirm availability again at the moment of booking rather than trusting what was shown earlier. Visibly disable booked, blocked, and past dates so they cannot be selected, and prevent a range from crossing an unavailable date. The backend holds the source of truth, and the calendar should never imply a date is held until the system confirms it.

**What states does a booking calendar need to handle?** The ones that keep a booking valid: available dates with a price, booked and blocked dates that cannot be selected, past dates disabled, a loading state while availability is fetched, and an empty state for a property with no openings. The selected range should show its check-in, check-out, total nights, and price clearly. A range that would cross an unavailable date must be prevented. These states are what stop a user from selecting something the system cannot honor, which is the first thing to check in any booking calendar.

## Frequently asked questions

### How do I build a Booking.com-style availability calendar in SwiftUI?

Build a custom month grid rather than using SwiftUI's DatePicker, because a booking calendar needs per-date states and a range, not a single date. Mark each date as available with a price, booked or blocked, or past and disabled, support a check-in to check-out selection with the nights between highlighted, and enforce rules like a minimum stay and no range crossing a blocked date. Bind the grid to live availability and re-confirm at booking so stale data cannot cause a double booking. A free availability-calendar template gives you the grid, the range, and the states to start from.

### Can I use SwiftUI's DatePicker for a booking calendar?

Not really. DatePicker selects a single date with no concept of availability, pricing, or a stay from check-in to check-out, so it cannot express what a booking calendar needs. You can use it for a simple one-off date field, but for availability you build a custom month grid with per-date states and range selection. Trying to bend the date picker into a booking calendar usually ends in rebuilding it as a custom grid anyway, so starting from an availability template saves that detour.

### Where can I get a SwiftUI availability calendar template?

The most useful option is a template built for availability, not a generic date control. A free VP0 availability-calendar template provides the month grid, the available, booked, and blocked states, the check-in to check-out range, and the price-per-night slot, with a machine-readable source page, so an agent like Cursor or Claude Code extends a real calendar. You then bind it to your live availability data and re-confirm at booking, since the template is the interface and the source of truth is your backend.

### How do I prevent double bookings in an availability calendar?

Treat availability as live data, not a painted snapshot. Bind the calendar to current availability, refresh it when the user changes months or returns to the screen, and confirm availability again at the moment of booking rather than trusting what was shown earlier. Visibly disable booked, blocked, and past dates so they cannot be selected, and prevent a range from crossing an unavailable date. The backend holds the source of truth, and the calendar should never imply a date is held until the system confirms it.

### What states does a booking calendar need to handle?

The ones that keep a booking valid: available dates with a price, booked and blocked dates that cannot be selected, past dates disabled, a loading state while availability is fetched, and an empty state for a property with no openings. The selected range should show its check-in, check-out, total nights, and price clearly. A range that would cross an unavailable date must be prevented. These states are what stop a user from selecting something the system cannot honor, which is the first thing to check in any booking calendar.

---
*Published on the [VP0 Journal](https://vp0.com/blogs). Free to read, index and cite with attribution.*
