CoSpace Booking Engine
Desks, rooms and day passes without double-booking
- Role
- Full Stack Engineer
- Timeline
- 2025
- Stack
- Next.jsTypeScriptStrapiMongoDBTailwind CSS

A co-working operator was managing desks with a wall calendar and meeting rooms with goodwill. The engine's contract: if the site says a space is free, it is free — at any load, from any device.
Problem
Walk-ins, members and event bookings all competed for the same inventory with no shared source of truth. Double-bookings were resolved by whoever arrived first; recurring member reservations were tracked by memory; pricing changes meant editing a laminated sheet. None of it survived the operator opening a second location.
Solution
A Next.js application over a single availability model. Every bookable thing — desk, room, day pass — is inventory with rules: capacity, opening hours, plan entitlements, buffer times. Members book against live availability; staff manage inventory, plans and pricing through a Strapi admin without touching code; and the same model powers both locations from day one.
Architecture
Frontend
- Next.js (App Router)
- Availability calendar
- Member portal
Application
- Booking API routes
- Availability resolver
- Pricing rules
Content & Admin
- Strapi CMS
- Spaces & plans
- Locations
- Policies
Data
- MongoDB
- Bookings & holds
- Member records
Availability is computed, never stored: bookings, holds and rules are facts, and "is this slot free" is a query over them. That one decision removed the entire category of stale-availability bugs.
Challenges
Two people, one desk, same second
Concurrent checkouts on the last desk are inevitable. Short-lived reservation holds created atomically at checkout — expiring automatically if payment stalls — mean the second person finds out before paying, not after arriving.
Rules that operators keep changing
Buffer times, member-only hours, holiday closures — policies changed monthly. Modelling policies as CMS-managed data read by the availability resolver let operators change the rules without a deploy, and let the engine stay generic.
A calendar that feels instant
Availability views are read-heavy. Precomputing day-level summaries and fetching fine-grained slots on demand kept the calendar responsive while guaranteeing the checkout path always re-validates against live data.
Technologies
- Frontend — Next.js with TypeScript throughout; Tailwind CSS for a fast, consistent interface.
- Content & admin — Strapi as the operator's control panel for spaces, plans, pricing and policies.
- Data — MongoDB for bookings, holds and member records with TTL-expiring holds.
- Commerce-ready — plan entitlements structured so payment providers slot in behind the booking API.
Screens


Lessons Learned
- Compute availability from facts; caching truth is how systems learn to lie.
- Putting policy in the CMS turned "feature requests" into settings.
- Holds with automatic expiry are the polite way to say no to a race condition.