A Drupal 11 site for Riverside Physical Therapy. Nearly all frontend work lives in a single custom module (`riverside_pt`) rather than a Drupal theme. The site runs in Docker with nginx + php-fpm + PostgreSQL.
By default, **every**`docker compose up` performs a full database wipe followed by a complete reinstall + rebuild of the site structure from code:
- Drops the database
- Runs `drush site:install standard`
- Enables modules (including `riverside_pt`)
- Runs `drush riverside:rebuild` (the single source of truth for content types, fields, roles, and navigation)
This means the site is **always** built exactly the same way from the code in `riverside_pt.install` and the Drush command. There is no persistent data between restarts unless you opt out.
**Faster iteration (preserve the database):**
```bash
DRUPAL_FAST=1 docker compose up
```
This skips the wipe + `site:install` but still runs `drush riverside:rebuild` and the rest of the startup steps. Use this when you want quicker starts during active development and don't need a completely clean slate.
You can also run the rebuild manually at any time:
The custom module directory is volume-mounted, so template/CSS/JS edits are live without rebuilding the Docker image. `settings.php` and `development.services.yml` are also volume-mounted.
The hero uses two overlapping flex rows inside a `relative` section:
- **Box 1** (`absolute inset-0 flex`): image layer, out of flow, fills the section
- **Box 2** (`relative flex min-h-[560px]`): text layer, in flow, sets section height
Spacer divs with `basis-[x%] grow-[n]` control the offset columns on desktop. On mobile (`<sm`),spacersare`hidden`andcontentgoesfull-widthwithagradientoverlayforlegibility.
## Development services
`web/sites/development.services.yml` is loaded when `DEBUG=true` (set in docker-compose). It enables Twig debug/auto-reload and defines `cache.backend.null` (used by `settings.php` to disable render/page caching in dev).
## Menu / navigation
Nav items come from Drupal's `main` menu. Items titled `"Book An Appointment"` or `"Contact"` are flagged `is_cta: true` in the preprocess hook and rendered as a CTA button in the header template.
## Email
Booking confirmation emails are sent via `riverside_pt_mail()` in `.module` using the `booking_request` key. Transport is Postmark, configured in `config/sync/symfony_mailer.mailer_transport.postmark.yml`. The API key is injected via the `POSTMARK_API_KEY` environment variable.