Files
drupal-erable/CLAUDE.md

163 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Repository layout
This directory (`src/`) is a **git submodule** of the parent `docker-erable` repo. It holds the Drupal 10 application; the parent repo holds the Docker environment (`Docker/`, `docker-compose.yml`, `Makefile`, `ressources/db.sql`).
- `src/` (this repo, `drupal-erable.git`) — Drupal codebase, custom theme & modules, exported config.
- `../` (parent repo, `docker-erable.git`) — Docker setup, DB seed, Makefile commands.
Branches: `master` (dev), `stage` (preprod), `prod` (prod). A `refonte-graphique` branch is currently active for the ongoing visual redesign — **all work happens there**, not on `master`. `git push origin master` from `src/` will appear up-to-date even after committing on `refonte-graphique`; push the branch by name.
The parent repo references the submodule under its own branch set (`master`, `prod`). After pulling parent changes, run `git submodule update --recursive --checkout`.
## Commands
All commands are run **from the parent directory** (`docker-erable/`), never directly from `src/`. Never use `docker-compose` directly — always go through the Makefile.
```sh
make build # first-time build (uses host UID/GID via build args — do not skip)
make up # start the stack (php, nginx, mysql, redis, phpmyadmin)
make down # stop
make logs # follow logs
make ps # status
make exec_php # shell into the PHP container (where drush lives)
make exec_mysql # shell into the MySQL container
make dump_db # dump erable DB to ressources/erable-<date>-local.sql
```
After pulling code changes that affect Drupal config/schema:
```sh
make maj_config # composer install + drush updb + drush cim + drush cr + drush pag
```
Individual Drupal ops (also available as Make targets):
```sh
make composer_install # composer install --no-dev in the php container
make updb # drush updb -y
make cim # drush config-import -y
make cr # drush cr (cache rebuild)
make pag # drush pag all for nodes & taxonomy terms
```
For ad-hoc drush use, `make exec_php` then run `drush ...` from `/var/www/erable/`.
### Drush gotcha (Make targets broken)
The Make targets that wrap drush (`cr`, `cim`, `updb`, `crd`, `pag`, and the composite `maj_config`) are currently broken because the container's global `drush` is the Drush Launcher, which errors out against Drush 12+ (`Drush Launcher is not compatible with Drush 12+`).
Until the parent `Makefile` is fixed, call the vendor binary directly:
```sh
docker exec erable-php-1 /var/www/erable/vendor/bin/drush cr
docker exec erable-php-1 /var/www/erable/vendor/bin/drush cim -y
docker exec erable-php-1 /var/www/erable/vendor/bin/drush updb -y
```
Inside an `exec_php` shell, use `vendor/bin/drush` (or `./vendor/bin/drush` from `/var/www/erable/`) — not the bare `drush`.
### When to run drush cr
**Every Twig template edit must be followed by a cache rebuild**, otherwise Drupal keeps serving the previously rendered markup. This applies to anything under `web/themes/erabletheme/templates/` and any custom module template (e.g. `web/modules/custom/erable_mod/templates/`). SCSS/CSS changes do NOT require `drush cr` (the CSS file is served as-is by Drupal). Run:
```sh
docker exec erable-php-1 /var/www/erable/vendor/bin/drush cr
```
after every `.twig` edit, then hard-reload the browser.
Site URL (via reverse proxy on the host): `http://dev.erable.fr` (container exposed on `:8980`). phpMyAdmin on `http://dev.phpmyadmin.erable.fr` (`:8981`). See parent `README.md` for the nginx/apache vhost snippets.
## Theme build
The custom theme is `web/themes/erabletheme/`. SCSS is compiled to CSS via **Dart Sass** (`sass` package, not `node-sass`):
```sh
cd web/themes/erabletheme
npm install # first time only
npm run sass # runs: sass --watch --no-source-map scss/styles.scss:css/styles.css
```
The compiled `css/styles.css` is what Drupal serves (see `erabletheme.libraries.yml`). The watch must be running while editing SCSS, or styles won't update. If `npm run sass` ever appears to output into `scss/` itself, the script has been mis-set — the entry must be the `IN:OUT` form `scss/styles.scss:css/styles.css`, not two positional args.
Compile failures surface in the rendered page as garbage in `body::before { content: "..." }` (the Sass watcher injects the error there). To see them from a script: `curl -s http://dev.erable.fr | grep -A2 'body::before'`.
## Custom code
- **`web/themes/erabletheme/`** — base theme: `stark`. SCSS entry is `scss/styles.scss`, which imports `global/`, `partials/`, and per-page files (`_home.scss`, `_projets.scss`, `_actualites.scss`, …). Twig templates override blocks, regions, nodes and views; node templates live under `templates/node/` per content type (`actualite`, `projet`, `partenaire`, `equipe`, `ressource`, `meetup`). The single JS file is `js/erabletheme.js`. Slick carousel is vendored under `librairies/slick-1.8.1/`. Rellax is also vendored under `librairies/` (powers the parallax background).
- **`web/modules/custom/erable_mod/`** — site-specific module (routes, blocks, controllers under `src/`, templates under `templates/`). Notable: `SitesMap` block (`src/Plugin/Block/SitesMap.php`) renders project markers on the home map; its SVG marker template is at `assets/svg/point.svg` and the Twig wrapper at `templates/svg-mapsites.html.twig`.
- **`web/modules/custom/loginregisterblock/`** — combined login + register block.
## Theme design system (post-refonte)
The redesign on `refonte-graphique` introduces a token-driven design system. **All typography sizes are in `rem`**, never `px` (one exception: deliberate "magic numbers" tied to a slick-carousel structural quirk in `_carousel.scss`, commented as such).
### Tokens (single source of truth)
- `scss/global/variables/_colors.scss` — brand colors. `$fluo_green: #33ffc4` is the new accent; `$teal` is aliased to `$fluo_green` so legacy `$teal` usages propagate automatically. Other tokens: `$page_bg: #f9f9f9` (site background), `$text_grey: #4a4a49`, `$dark_green`, `$beige`. Gradient mixins `beige_gradient()` and `white_beige_gradient()` live here too.
- `scss/global/variables/_typography.scss` — font-size scale + line-heights + weights + semantic mixins. All sizes in `rem`:
- `$fs_xs: 0.8125rem` (≈13px), `$fs_sm: 0.9375rem` (≈15px), `$fs_md: 1.0625rem` (≈17px), `$fs_lg: 1.375rem` (≈22px), `$fs_xl: 2.25rem` (≈36px), `$fs_2xl: 3.5625rem` (≈57px).
- Mixins (**use these, do not hardcode font properties**): `main_title()`, `sous_titre()`, `sous_titre_alt()` (intermediate Vogun 22→36px), `main_text_content()`, `meta_text()`, `cta_text()`, `fluo_button()` (the universal CTA — propagates to `.more-link` and `footer.fluo_links` site-wide).
- `scss/global/_fonts.scss``@font-face` declarations. **Vogun** (titles/CTA, `fonts/Vogun/Vogun-Regular.woff2`) and **Marianne** (body) are the only typefaces. Barlow has been removed.
- `scss/global/variables/_layout.scss` — breakpoints: `$breakpoint_tablet: 760px`, `$breakpoint_desktop: 1080px`, `$breakpoint_desktop_large: 1600px`. Plus `$x_margin` for horizontal page padding.
### Responsive philosophy
Mobile-first via `vw` for proportional sizing + `max-width` (or aspect ratios) to cap on large screens. Avoid hard `px` breakpoints in component sizing — use the breakpoint variables for layout shifts only.
### Refonte branch conventions
- This is a redesign branch, so **replace** legacy code rather than stacking new styles on top. Removing the old `$teal` value, renaming Barlow out, deleting unused SVGs (e.g. `feuille.svg`) is the norm here.
- Semantic mixin names (`main_title`, `sous_titre`) are kept even when their visual content is overhauled — this preserves call-sites across all per-page SCSS files.
- It's OK to edit Twig block templates (e.g. `block--views-block--home-blocks-block-1.html.twig`, `block--sitesmap-block.html.twig`) when restructuring layouts. Avoid editing core templates like `node.html.twig` or `field--body.html.twig` to limit side effects.
- The CTA "En savoir plus" on the home is reparented by JS (see `js/erabletheme.js``intro.appendChild(moreLink)`) because `smart_trim` renders `.more-link` deep inside `article > div`. This is intentional and lets the separator stop at text-end instead of button-end.
### Décors parallax v2
All decor systems are JS-driven (injection + positioning + parallax where applicable). Common entry points live in `Drupal.behaviors.erabletheme.attach` inside `erabletheme.js`; positions recompute on `window.load`, `window.resize` (debounced 200ms). Body scroll is on `body` (not `html`) — see `_global.scss` (`body { overflow: scroll }`, `html { overflow: hidden }`). Rellax's `wrapper: 'body'` and the custom parallax scroll listener both depend on this.
Assets live in `assets/new-bg-shapes/` (frises, mid-left, home-diapo) and `assets/drawings/` (oiseaux, fleurs ponctuels).
1. **Side frises** (`.bgImg.decor-left/right`) — single `.decor-tile` in `page.html.twig` cloned by JS (`setupBackgroundTiles`) to fill `layout-container.offsetHeight`, then animated by Rellax (`new Rellax('.bgImg', { wrapper: 'body' })`). SCSS: `_background.scss` (positions in `%` of tile). `.decor-once` images (cut-at-top) are removed from clones.
2. **Mid-left column decors** (`.col-decor`, `mid-left-1.png` + `mid-left-2.png`) — `setupColDecor` / `positionColDecor` / `applyColDecorParallax`. Two cibles:
- `.fullpage:not(.large-container)` (internal pages): stack of up to 2 PNG at the bottom-left outer edge of the column. Sizes + gaps proportional to colH, min/max clamped. Display thresholds: 50% colH for both, 30% for one.
- `.map-projets` (home "projets" block): single PNG via `singleOnly: true`, threshold 50%.
Custom parallax (subtle upward translate, capped ±30px). Bord droit of PNG calé on bord gauche extérieur via `translateX(-100%)`. Visibility responsive: `_background.scss`.
3. **Footer ornements** (`.footer-decor`, `bird-3.png` + `flower-2.png`) — Twig in `page.html.twig` inside `<footer>`. CSS-only positioning in `_footer.scss`: `position: absolute; bottom: 100%` posed on the footer top edge. Footer raised to `z-index: 3` (cf. `_global.scss`) so the decors overlay the column bottom. `pointer-events: none`.
4. **Random page decors** (`.page-decor`) — `setupPageDecor` / `positionPageDecor`. One PNG per `.fullpage` (excluding `aside .fullpage` sidebars), tirage déterministe par colonne (index stocked on `col.dataset.pageDecorIdx`). Pool: `bird-1, bird-2, flower-1, flower-3` (flower-2 + bird-3 réservés au footer). Width by breakpoint, anchor switches to `.page-header-outside` on mobile. `flower-3` overlaps 40% inside (vs 20% default) because of thin stem.
5. **Home decors above carousel** (`.home-above-decor`, `flower-1` + `bird-1`) — `setupHomeAboveDecor`. Static (no parallax), debord `overlap` px on the carousel cards top edge, horizontal `offsetVw` from viewport edges.
6. **Home decors on carousel** (`.home-diapo-decor`, `home-diapo-left.png` + `home-diapo-right.png`) — `setupHomeDiapoDecor`. Anchored to `.slick-list` top (not `.carousel_container` to avoid catching the dots). Custom parallax shared with col-decor (same `applyColDecorParallax` siblings: `applyHomeDiapoParallax`). Width × `decorWidthScale()` (1× desktop, 1.5× tablet, 1.8× mobile).
7. **Home decors around projets block** (`.home-projet-decor`, `bird-2` + `flower-3`) — `setupHomeProjetDecor`. Anchored to `.map-projets`. `bird-2` at top-left (debord on the block left edge in desktop; `-3vw` from viewport in mobile/tablet). `flower-3` truncated by the viewport right edge (`right: -20px`), centered at 1/3 from block top. Static (no parallax).
The `decorWidthScale()` helper (mobile 1.8× / tablette 1.5× / desktop 1×) is shared by home-diapo, home-above, home-projet to keep widths visually comparable across screen sizes. Footer decors do NOT use it (pure CSS).
## Drupal configuration
- Exported config lives in `config/sync/` (and `config/tmp/`). Edits to config in the UI must be exported with `drush cex -y` and committed; conversely, after pulling config changes, run `drush cim -y` (via the vendor binary — see Drush gotcha).
- The project uses `wikimedia/composer-merge-plugin` to merge `web/profiles/drupal-starterkit-profile/composer.json` (itself a submodule from `figureslibres.io`).
- Drupal core is `^10.2`. Key contrib modules: `paragraphs`, `webform`, `panels`/`page_manager`, `geofield`+`leaflet` (project map), `smart_date`, `smart_trim` (responsible for `.more-link` rendering deep inside fields — see refonte conventions), `social_media_links`, `view_unpublished`.
## Database
- DB is auto-seeded from `${DB_IMPORTE_FILE}` (set in `.env` in the parent repo) on **first** `make up` only. To reload a dump later, copy the SQL into the mysql container and re-import manually — see "Updating manualy the mysql db" in the parent README.
- Credentials default to `root` / `erable` (DB name `erable`).
## Twig debugging
Twig theme debug is currently ON in this dev environment: every rendered region/block/field has `<!-- FILE NAME SUGGESTIONS -->` HTML comments listing candidate template names in priority order. To find which template controls a region of the page: View Source → search for the markup → read the suggestions above it. The active template is the first one that exists.
## Patterns to know
- Do not commit `web/sites/default/settings.local.php`, `salt.txt`, or the `files/` directory — they are environment-specific (copies of templates live in parent `ressources/drupal/`).
- The `php` container runs as the **host user** (USER_UID/USER_GID baked at build time) so file ownership stays clean. If you re-`make build` on a different machine, files written by the container will switch UID.
- xdebug is wired (see `Docker/php-8.1-fpm/` and the `XDEBUG_INI` mount). `host.docker.internal` resolves to the host on Linux via the `extra_hosts` mapping.
- Penpot is the design source of truth for the refonte. Frames of interest in the connected file: `1 - accueil - integration` (id `8997888b-7408-8014-8008-0cf456861e09`) for the home, and `3 - Single projet` (id `cb2f4013-441f-800a-8007-d81a04408009`) for the side-decor reference. Use `mcp__penpot__export_shape` to pull PNG/SVG references.