Add booking stack, client deploys, and back-office updates

- deploy/booking: shared Easy!Appointments stack with brand-matched
  wizard (flatpickr recolor, single-tenant provider hide, iframe
  auto-fit height reporter)
- deploy/clients: per-client isolated nginx compose stacks with
  _template scaffold, new-client.sh, and happynails live site
- deploy/backup: smb-db backup script
- n8n: booking-sync workflow; onboarding tweaks
- playbooks: lead-to-customer lifecycle + outreach
- templates: nail-studio landing previews
- backoffice: app/db/init/compose updates

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 16:10:15 +02:00
parent 4257bd3e55
commit 156166b4e5
25 changed files with 2900 additions and 23 deletions
+46
View File
@@ -0,0 +1,46 @@
# clients/ — one isolated stack per business client
Each signed client gets their **own Compose project** (`smb-client-<slug>`) running a
single lightweight `nginx:alpine` container that serves *their* static site on *their*
domain. Clients are fully separated: independent lifecycle, logs, and removal; no shared
container or state. Booking and lead data still flow into the **shared CRM** (Postgres
source of truth) via the n8n webhooks baked into each client's page.
## Why a container per client (not one shared host)
- **Isolation** — update / restart / remove one client without touching any other.
- **Clean billing & offboarding** — `docker compose down` removes exactly that client.
- **Cheap** — static nginx idles at a few MB; capped at 64 MB each, so dozens fit the 16 GB box.
## Layout
```
deploy/clients/
├── _template/ # DON'T deploy — the source template
│ ├── docker-compose.yml (name: smb-client-${CLIENT_SLUG})
│ ├── .env.example
│ └── site/index.html
├── new-client.sh # scaffolds a client folder from _template/
└── <slug>/ # one folder per real client (created by the script)
├── docker-compose.yml
├── .env (CLIENT_SLUG, CLIENT_DOMAIN)
└── site/ (the client's branded page)
```
## Add a client
```bash
cd deploy/clients
./new-client.sh happynails happynails.de ../../templates/landing/preview-happynails
```
Then follow the printed steps: add the Caddy block + reload, point DNS, and `docker compose up -d`
on the homelab. Each client lives at `/home/mivanchenko/clients/<slug>/` on the box.
## How this fits the whole system (compose groups)
```
edge/ caddy → TLS, routing, basic-auth (one, shared)
automation/ n8n (+ postgres, redis) → n8n.mivanchenko.de (one, shared)
crm/ smb-db + smb-crm → onboard.mivanchenko.de/crm (one, shared)
demos/ smb-demos → demos.mivanchenko.de (prospect previews)
clients/ smb-client-<slug> × N → each client's domain (one per client) ← this dir
```
Shared infra (edge / automation / crm) stays single; only the client-facing sites multiply,
one isolated stack each. Previews for *prospects* stay in `demos/` until they sign — then
scaffold them a real isolated stack here.