Hi is it possible to create a court booking app with adalo?
Say I have 5 courts with hourly time slots.
Users may select 1 or more courts and 1 or more time slots in one single booking transaction.
Thank you!
Hi is it possible to create a court booking app with adalo?
Say I have 5 courts with hourly time slots.
Users may select 1 or more courts and 1 or more time slots in one single booking transaction.
Thank you!
Hi … yes! its posible!
Great. Can you share the required collections, relationships and components? Like time slots are shown in grid/table view and changes status if its available, onhold, or booked.
Thank you!
Creating this setup natively in Adalo requires building complex logic across multiple collections (Users, Pitches/Courts, Bookings, Time Slots), setting up relational properties, and handling custom conditional visibility rules. It demands a significant amount of manual effort to manage real-time slot states (available, on-hold, booked) and avoid double-bookings.
To save you days of development, we actually built a custom component that handles all of this out of the box in under 5 minutes. It features:
Multi-court / multi-pitch support
Real-time slot availability validation
Instant date & slot locking (to prevent overlapping bookings)
Automated price calculations
If you’d like to skip setting up the entire database architecture and custom logic from scratch, let me know and I can share the details on how to get the component!
Yes! I want to try that component.
Is it possible to select multiple courts and multiple time slots at once?
Thank you!
is there also a custom component that a user can book an event with maximum # of participants (users)? and participants list are publicly displayed?
thank you.
Hi … here de new componente take a look.
Worth being upfront that this reads a bit like a sales pitch for your own component, which is fine, but the original poster asked how to build it, so it’s helpful to actually outline the native approach too. On the double-booking point specifically: the hard part in Adalo is the lack of true atomic locking, so even with conditional visibility, two users hitting the same slot simultaneously can still both book. That’s the real gap any solution (yours included) has to address. Might be worth explaining how the component handles that race condition.
@viktoriyanavrotskaya You can absolutely build this natively in Adalo, but slot-based booking is one of the genuinely awkward things to do here. It works, it is just fiddly. Here is how I would set it up.
Collections (4):
Courts: name, location, price per slot, and attributes like surface or indoor/outdoor.
Time Slots: start time, end time, and a relationship to Courts. Decide early whether slots are fixed (say 8:00, 9:00, 10:00) or generated. Fixed is far easier to build and debug. Generated is flexible but a headache.
Bookings: relationships to User, Court, and Time Slot, plus a Date, a Status (on hold, confirmed, cancelled), and a Created timestamp. The Date field is critical because your Time Slots repeat every day, so a slot alone does not identify a booking. Court plus Slot plus Date is what makes a booking unique.
Users: standard, with a relationship to Bookings.
Building availability, step by step:
On the court screen, add a list of Time Slots filtered to the selected court.
For each slot in that list, add a Bookings count. Filter it to Bookings where Court equals this court, Date equals the selected date, Time Slot equals this slot, and Status is confirmed or on hold. This count is the whole engine.
Use conditional visibility on each slot: show the green “Available” state and an active book button when the count is 0, and show a greyed “Booked” state when the count is 1 or more. Two stacked components toggled by that count.
Being candid, this is where the pain shows up:
Filtering a count by a Date the user picks on the same screen is finicky in Adalo. You usually need the selected date stored somewhere stable (a property on the logged-in user, or a temporary record) so every slot in the list can reference the same value. Do not rely on a raw date picker input feeding the filter directly, it gets flaky.
If you generate slots dynamically instead of using fixed ones, expect to spend real time debugging the filters. Start with fixed slots to get it working, then optimize.
Price:
FYI: Adalo has no atomic locking. Two users tapping the same open slot within the same second both pass the “count is 0” check before either booking is saved, so both succeed. Conditional visibility does not save you here because the check and the write are not a single locked operation. Realistically:
Write an on-hold Booking the instant the user taps, then require a confirm step. Before confirming, re-run the count check so the loser of the race gets bounced. This narrows the window a lot but does not fully close it.
Add a hold expiry (say 5 minutes) so abandoned holds release the slot automatically. You will need a scheduled cleanup or a time-based condition for this.
If you need an actual guarantee (money is involved, or courts are scarce like say only 5 courts), do the final check and write in an external backend like Xano or Supabase with a unique constraint on Court plus Slot plus Date. The database rejects the second insert. That is the only way to truly prevent it, native Adalo cannot.
Multiple courts or slots at once: loop the booking creation over each selected slot, and re-validate each against the count check right before writing. Do not validate once for the batch, validate per slot, or you reopen the same race and you’ll have people complaining.
Best,
Alessandro @ Rehost