# CLAUDE.md This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. ## Project overview Static PHP site for the Index NGO donation/support campaign (`soutenir.index.ngo`). No build step — PHP files are served directly. The site has two language versions: French (`index.php`) and English (`en/index.php`). ## Architecture ### Content flow All editorial content is managed via a **Kirby CMS** running in a separate repo (`/Users/adrienpayet/Documents/code/en-cours/index/main/`). The static site fetches content from the Kirby API and caches it locally: ``` Kirby CMS (main repo) → /support-content?lang=fr → includes/cache.php → index.php ``` - **`includes/config.php`** — API URL, token, cache TTL constants - **`includes/cache.php`** — `getContent(lang)` function: serves cache if fresh (<5 min), otherwise fetches from Kirby API via curl, falls back to stale cache - **`cache/`** — stores `content.fr.json` and `content.en.json` ### Kirby backend (separate repo) - **Blueprint**: `/Users/adrienpayet/Documents/code/en-cours/index/main/site/blueprints/pages/support.yml` — defines all editable fields for the support page - **API route**: `/Users/adrienpayet/Documents/code/en-cours/index/main/site/config/routes/support-content.php` — builds and returns the JSON response consumed by this site; uses `->inline()` on writer fields When adding a new dynamic field: add it to the blueprint, expose it in the API route, then consume `$data['fieldName']` in the PHP templates. ### Donation gauge - **`api/donorbox-proxy.php`** — server-side proxy to Donorbox API (Basic Auth). Paginates through all active plans to get `recurring_donors_count`. Caches result in `api/cache/donorbox_data.json` (5 min). - **`assets/js/donorbox-gauge.js`** — calls the proxy, adds `RECURRING_DONORS_OFFSET` to the real count, updates the gauge CSS variable `--pourcent` and the displayed number. Also sets up 5-minute auto-refresh. `RECURRING_DONORS_OFFSET` is defined at the top of `donorbox-gauge.js` and represents historic/offline supporters added to the live Donorbox count. ### Donation pad **`assets/js/donation.js`** — IIFE that: - Dynamically generates all donation buttons (amounts, after-tax calculations) on `DOMContentLoaded` - Contains `TRANSLATIONS` object for FR/EN static strings in the donation pad - Generates Donorbox redirect URLs with UTM passthrough - Handles monthly/one-off tab switching Static strings in the donation pad (e.g. "Avec déduction fiscale de 66 %") live in the `TRANSLATIONS` object in this file, not in Kirby. ## Key conventions - **Writer fields in Kirby**: use `->inline()` in the API route to get inline HTML without block wrappers. For multiline text (e.g. a title with a `
`), use a `writer` field with `nodes: false` and `buttons: false` — this preserves line breaks. In the API route, use `->inline()` which converts newlines to `
` tags; do **not** use `nl2br()`. - **`heroHeading` field**: rendered with `` (no `htmlspecialchars`) because it contains trusted HTML from the writer field. - **Language**: `document.documentElement.lang` drives JS translations. FR page sets `lang="fr"`, EN page sets `lang="en"`. - **Cache invalidation**: delete files in `cache/` to force a fresh fetch from Kirby.