customer-riverside/CLAUDE.md
Philip Peterson 63ce2ba2ef wip
2026-05-24 19:23:05 -07:00

4.3 KiB

Riverside Therapeutics — Project Context

What this is

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.

Running locally

docker compose up        # starts app on http://localhost:8080
docker compose exec app drush cr   # clear Drupal cache
npm run watch            # Tailwind CSS watcher (run on host, not in container)
npm run build            # minified production build

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.

Stack

  • Drupal 11 (core_version_requirement: ^11)
  • PHP 8.5-fpm (in Docker)
  • PostgreSQL 18 (db: drupal, user: drupal, pass: drupal)
  • Tailwind CSS v3 — compiled on the host via npm, output to app.css
  • FullCalendar 6 — downloaded at build time, used on the schedule page
  • Postmark — email via drupal/symfony_mailer

Custom module: riverside_pt

All site-specific code lives here: web/modules/custom/riverside_pt/

Templates

File Purpose
templates/riverside-pt-header.html.twig Fixed top nav with hamburger on mobile
templates/riverside-pt-home.html.twig Home page: hero section + services grid

The header is injected globally via riverside_pt_page_top() in .module, not rendered by a controller.

Controllers / routes

Route Path Controller / Form
riverside_pt.home /home HomeController::page
riverside_pt.schedule /schedule ScheduleController::page
riverside_pt.booking /schedule/book BookingForm
riverside_pt.booking_store_slot /schedule/book/slot (POST) ScheduleController::storeSlot
riverside_pt.schedule_events /schedule/events ScheduleController::events

CSS / JS

File Purpose
css/tailwind.css Tailwind entry point (@tailwind base/components/utilities + custom layers)
css/app.css Compiled Tailwind output — do not edit directly
css/calendar.css FullCalendar overrides
js/nav.js Hamburger toggle — adds/removes is-open on #rpt-main-nav
js/calendar.js FullCalendar init and slot-selection logic

Libraries

Defined in riverside_pt.libraries.yml:

  • riverside_pt/appapp.css + nav.js, attached globally via riverside_pt_page_attachments()
  • riverside_pt/schedulecalendar.css + fullcalendar.min.js + calendar.js

Tailwind notes

  • Config scans templates/**/*.twig and src/**/*.php for class names
  • Breakpoints are standard Tailwind v3: sm = 640px, md = 768px
  • Mobile nav collapse (max-height slide) is in tailwind.css under @layer components because it can't be expressed with utilities
  • Arbitrary Tailwind values use _ for spaces: bg-[#4a7a8a], shadow-[-56px_2px_10px_#0000001A]
  • Non-standard CSS properties (e.g. text-shadow) use arbitrary property syntax: [text-shadow:...]

Hero section layout technique

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), spacers are hidden and content goes full-width with a gradient overlay for legibility.

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.