Goal: get a branded boutique-hotel or B&B booking site — room availability, reservations, and payment — running self-hosted in an afternoon, starting from a demo instance instead of a blank page.
This is for a small independent property, or the developer building for one, who wants to take direct bookings on their own site instead of paying 15–20% to an online travel agency on every reservation forever. It is not for a 400-room chain with dynamic pricing, channel managers and yield optimisation — that's a different, heavier class of software. If you have five to fifty rooms and want to stop renting your customer relationship from a booking portal, this is the right size of tool.
dev-install-ce.sh on a cheap VPS.SMTP_* from the instance env).Don't start from empty. Import the hotel demo instance, which ships a coherent starting point: CMS content (home, rooms, contact pages), the booking plugin pre-wired, and a sensible default layout. This is the difference between "an afternoon" and "a fortnight" — you're editing a working hotel site, not assembling one from parts.
Success looks like: after import, browsing the site shows a hotel homepage with placeholder rooms and a working "book" path end to end (even if the rooms and prices are demo data).
In the admin backoffice, replace the demo rooms with real ones. For each room type set: name, description, photos, capacity, the nightly rate, and availability. The booking plugin models availability so it won't let two guests book the same room for overlapping nights — verify that constraint exists before you trust it (Step 6 covers the test).
Rates are a Priceable, so they run through the same pricing engine as everything else — set the price once and checkout quotes it correctly, including any tax class you assign (relevant for tourist/occupancy taxes).
Gotcha: decide your booking unit now — per night, with check-in/check-out dates — and your minimum-stay and cancellation rules. Retrofitting a two-night minimum after launch is more annoying than setting it upfront.
Connect your payment provider so a reservation takes money. Decide the model: full prepayment, a deposit, or pay-on-arrival with card capture. The payments layer is provider-agnostic — the booking flow doesn't care which PSP you plugged in, so pick the one with the best rates for your country and currency.
Success looks like: completing a test booking with a sandbox card produces a real reservation record and an invoice, and the room's availability for those dates drops.
A booking site that looks like a template converts worse than one that looks like the hotel. Rebrand the fe-user app: swap the logo, set your colours through the CSS variables (you don't fork the components, you override the tokens), and adjust the CMS content to your property's real copy and photography. Point your custom domain at the instance and get TLS in place.
Success looks like: the site at your domain shows your name, your colours, your rooms — nothing that says "demo."
Two finishing pieces that decide whether the site actually earns.
SEO: give the property and ideally each room type a real indexable page — title and description written for what guests search ("boutique B&B in [town], sea-view rooms"). If your storefront is the SPA, make sure bots get rendered HTML (the SEO renderer sidecar handles this; confirm a bot-UA request returns your real title in the markup).
Confirmation emails: a booking that doesn't send a confirmation feels broken to the guest. Confirm the booking event triggers an email with the reservation details, and that it actually arrives (check spam; verify SPF/DKIM on your sending domain). Test the full sequence: book → pay → confirmation email lands.
This is a direct-booking site, not a channel manager. It takes bookings on your site. It does not sync availability to Booking.com or Airbnb — if you keep listing on those, you're managing two calendars and risking a double-booking across them. Many small properties run direct-only precisely to escape the commissions; if you can't, you'll want channel-sync, which is beyond this setup.
You run the server. Self-hosted means you own uptime. For a booking site that's a real responsibility — a night of downtime is lost reservations. Budget for backups and basic monitoring, or use a managed host for the VPS.
Availability logic is only as good as your test. Prove the no-double-booking constraint yourself (Step 6) before you take a real reservation. Trust it after you've watched it refuse the overlap, not before.
Next: add seasonal rates, a minimum-stay rule for weekends, and an admin view your front desk can actually use to see the week's arrivals.
A small property's booking problem is not a hard software problem — it's an assembly problem, and starting from the hotel demo instance turns assembly into editing. Rooms and rates are Priceables through the standard pricing engine; the booking plugin enforces availability; payments are provider-agnostic; branding is CSS variables over the same components. In an afternoon you get a direct-booking site on your own domain, and every reservation that comes through it is one that didn't pay a 15–20% portal commission. Because it's self-hosted and source-available under BSL 1.1 (free for commercial use while annual VBWD-attributable sales stay under the value of 6.7 BTC per year), the guest relationship — and the guest's data — is yours.
Running a property? See the booking plugin, the features, and the docs for importing a demo instance and wiring payments.