Most booking software assumes a fixed price and a calendar slot. Service businesses do not work that way: a mobile detailer prices on vehicle size and condition, a pool company on volume and access. So the quote comes first, and the booking follows from it.
The hard part was not the booking engine. It was making one deployment serve industries that use different words for the same things. A vertical is a YAML file: terminology, pricing dimensions, default services. Adding one is configuration, not a fork, and niche-branded domains all serve from the same containers.
The widget is the other half. It embeds in a customer's existing site, which means it cannot assume React, cannot inherit their CSS, and cannot break when they change themes. It is a web component with its own shadow DOM, cache-busted by commit on every deploy.
It runs on one Hetzner box behind nginx, bound to loopback, with its own Postgres container. It is the app the rest of my infrastructure is built to protect.
