headless.dev
← All posts

The best feedback loop we could think of: a Booking button

Scroll to the bottom of the homepage. The section called Talk to a real engineer is a real Wix Bookings flow, running against the same backend that powers any Wix site with calendar bookings: yoga studios, salons, dentists, accountants. We didn't build a scheduler. We configured one.

The honest version of "Contact us"

Most product sites end the same way: a Contact sales link, a form that drops into a queue, a salesperson optimizing a funnel. We wanted to try something else.
The right answer to your question usually depends on what you're actually trying to build, so the most useful thing we can offer is half an hour with one of the engineers shipping the product — a direct line to the people deciding what gets built next, so you get a real answer and we hear what we need to hear, without a middleman compressing it.
So at the bottom of this page is a booking section. Pick a slot. We'll see you on the call.
It sits inline on the homepage, not tucked behind a /contact page, using the same Wix Bookings API a yoga studio or a salon would use - Which is a good excuse to walk through how it's wired.

Three calls and a layout

The interesting code fits on a postcard. From the SSR pass in Welcome.astro:
import { services, availabilityTimeSlots, bookings } from "@wix/bookings";

// 1. Find the service we set up in the Wix Dashboard
const { items: [service] } = await services
  .queryServices().eq("hidden", false).limit(1).find();

// 2. Get the next two weeks of bookable slots, with the staff free at each one
const { timeSlots } = await availabilityTimeSlots.listAvailabilityTimeSlots({
  serviceId: service._id,
  fromLocalDate, toLocalDate,
  bookable: true,
  includeResourceTypeIds: [service.primaryResourceType],
});
Then, when the visitor picks a slot in the browser:
await bookings.createBooking({
  bookedEntity: {
    slot: {
      serviceId, scheduleId, startDate, endDate, timezone,
      resource: { _id: pickedEngineerId },
      location,
    },
  },
  contactDetails: { firstName, lastName, email },
  totalParticipants: 1,
});
Three SDK calls, all paged through SSR so the slot grid arrives as static HTML — no loading spinner on first paint. Everything else in the section is markup and React state.

What we didn't have to write

The afternoon-not-a-sprint feeling came from the list of things we didn't build:
  • Time-zone reconciliation - Slots come back in the business's local time. The browser renders them in the visitor's locale through Intl.DateTimeFormat. Two strings of code.
  • Calendar math - The slot generator already knows about each engineer's working hours, the service's session length, the buffer between sessions, the booking-window policies. We tuned timeBetweenSessions once in the dashboard; the API regenerated the grid.
  • Multi-engineer fan-out - Each slot's availableResources carries every engineer free at that time. The filter chip row above the grid is just the union of those lists. Any engineer lets Wix auto-assign; clicking a person's chip filters the grid to their slots and pins the booking to them.
  • Staff photosstaffMembers.queryStaffMembers() returns each engineer's mainMedia.image. After one tiny conversion from Wix's internal media URI to a CDN URL, those photos render right on the slot buttons. No photo? The avatar falls back to initials.
  • Anonymous booking - createBooking works for a logged-out browser session out of the box. Wix mints an anonymous visitor id, attributes the booking to it, and runs the conflict check against it. No sign-up wall.
  • Staff dashboard - Confirmed bookings show up in the Wix Bookings calendar, scoped to each engineer when they sign in as themselves. They can sync the calendar to Google or Outlook with one click.
  • Confirmation emails - When a booking is confirmed, the customer gets a confirmation email and the assigned engineer gets a "new booking" notification — both templated in the Bookings dashboard. No SMTP code on our side.
  • Conflict prevention - Two visitors picking the same slot at the same time? Wix's booking service rejects the second one. We didn't write a single line of locking.
A list of the files we would have written is longer than the code we did write.

Flip the toggle

Toggle X-Ray in the top nav and hover the booking section. The capability tag reads Wix Bookings, and the drawer pops up with the actual queryServices → listAvailabilityTimeSlots → createBooking snippet, plus a link to BookEngineer.tsx on GitHub. Same rule as everywhere else on this site: the code in the drawer is the code that ran.

Book one

If you're thinking about building on Wix Headless, this is an open invitation. The slot grid is right at the bottom of this page. Pick a half-hour, tell us what you want to build, hit Confirm.
You'll be talking to one of the engineers actually shipping the product. See you on the call.