Create two new legal pages (FR/EN/MG) with LAATEL Corporation
company details (STAT, RCS, NIF). Add footer links to all pages
and translation keys for the three languages.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Architecture finale :
1. User remplit formulaire + passe Turnstile CAPTCHA → form-handler.js
2. form-handler.js POST au Worker avec action 'requestVerification'
3. Worker valide Turnstile, génère un token UUID, le stocke en KV (TTL 24h)
avec firstname/email/reference_client, puis envoie un email via Resend
avec un lien : confirmation.html?token=XXX
4. User reçoit email, clique 'Confirmer mon email'
5. confirmation.html lit le token de l'URL, POST au Worker avec action
'verifyToken'
6. Worker valide le token, envoie le welcome email via Resend (avec ref +
adresse Paris depuis env var), marque le token comme utilisé
7. confirmation.html affiche 'Inscription confirmée !'
Ainsi : ref + adresse Paris ne sortent JAMAIS avant validation email,
et les bots sont bloqués à l'étape 1 par Turnstile.
Setup Cloudflare requis (côté user) :
- RESEND_API_KEY : clé API Resend (re_...)
- RESEND_FROM : adresse expéditrice ('onboarding@resend.dev' pour test,
ou domain vérifié pour prod)
- SITE_URL : optionnel, défaut https://mva-global-fret.github.io/site-mva-global-fret
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- contact.html: ajout du widget Turnstile (site key: 0x4AAAAAADKDuc7Rmlb1svIL)
- form-handler.js: blocage de la soumission si pas de token Turnstile valide
- Worker: validation server-side du token via /turnstile/v0/siteverify
avant chaque appel sendWelcomeNow → bloque les bots qui n'auraient
pas passé le challenge côté client.
Le secret Turnstile est en env var Cloudflare (TURNSTILE_SECRET).
Limite humain : Turnstile détecte les bots avec très peu d'interaction
côté utilisateur (mode 'Managed', le plus souvent invisible).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Bug 1 — Ref MVA-001 dupliquée :
Le filtre HubSpot 'HAS_PROPERTY' avec value:'' retournait 0 résultats.
Suppression du value:'' → maintenant le worker liste correctement les
contacts avec reference_client et incrémente bien (testé : MVA-004).
Bug 2 — Email post-inscription jamais reçu :
Le double opt-in HubSpot ne se déclenche pas via Forms API sans
subscription consent (impossible à configurer sans nouveaux scopes
Private App). Pivot vers une approche plus simple :
- L'email de bienvenue est désormais envoyé directement après
soumission du formulaire (pas de DOI HubSpot)
- L'envoi passe par le Cloudflare Worker (action sendWelcomeNow)
pour que l'adresse Paris reste dans les env vars Cloudflare et
ne soit JAMAIS dans le JS public
- Worker appelle EmailJS REST avec firstname + reference + paris_address
Cleanup : message de succès reverti à 'Inscription réussie' (FR/EN/MG).
Anti-spam : protection légère via filtre email/téléphone côté formulaire.
La cron-based welcome (post-DOI) reste en place mais sera inerte tant
que aucun contact n'a le statut CONFIRMED côté HubSpot.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Retire le bloc 'Numéro de référence client' de la page de succès
- Met à jour le message en FR/EN/MG : 'Vous recevrez ensuite votre numéro
de référence client' après confirmation
- Désactive l'envoi immédiat de l'email EmailJS de bienvenue (qui
contenait déjà la référence). HubSpot envoie son email de
double opt-in qui sera customisé pour inclure la référence
via le token {{contact.reference_client}}.
Résultat : la référence n'est jamais visible avant que l'email ne soit
vérifié (puisque seuls les emails valides reçoivent le double opt-in).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
HubSpot double opt-in is now enabled at the account level. After
submitting the form, contacts must click the confirmation link in
their email to be added to the marketing list.
The success message now explicitly tells the user to check their
inbox and click the confirmation link, instead of just saying
'inscription enregistrée'.
- title: 'Vérifiez votre boîte mail !' (FR), 'Check your inbox!' (EN), 'Jereo ny boaty mailaka!' (MG)
- main msg: focus on confirmation step
- icon: enveloppe-circle-check (gold) instead of generic green check
- note: nuance that the reference number is for tracking parcels
- emailSent: kept as is (informative footer)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Avant : le bloc 'Rappel tarifaire' était collé en bas de la colonne droite,
créant un déséquilibre visuel avec le formulaire plus court à gauche.
Maintenant : sorti de la grille, centré avec max-width 720px sous les
deux colonnes, en grille 2 colonnes sur ses items pour une lecture
plus dense et équilibrée.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The new index.html is a 3-act scroll-driven storytelling intro:
Act 1 (Tarmac at sunset)
Sunset gradient sky, mountain silhouettes, hangar, runway with
centerline lights. Inline SVG cargo plane (MVA-branded gold tail)
sits on the ground while box emojis cycle up a loading ramp.
Act 2 (Take-off at dusk)
Dusk sky, two parallax cloud layers and distant mountains. The
plane translates diagonally up-and-right with a slight tilt and
a glowing contrail, sized down progressively.
Act 3 (Arrival at night)
Deep navy night sky with twinkling stars, a glowing moon, and
the Madagascar coastline silhouette. A small plane fades in
descending toward the island, then a centered CTA block reveals:
"Bienvenue à bord" with the gold "Accéder au site" button that
routes to accueil.html (the real homepage).
Implementation:
- Pure CSS layered scenes; no library
- Scroll progress driven by a single CSS custom property --scroll
(0→1) updated via rAF, layers transform off it
- Mouse-move parallax on layers via --mx/--my (skipped on touch)
- Inline SVG plane reused across the 3 scenes
- All text is i18n-driven with a new `intro` section in FR/EN/MG
Architecture changes:
- index.html → new parallax intro
- accueil.html → former index.html content (full homepage)
- All nav/logo/footer links updated index.html → accueil.html across
the 8 existing pages
- Mobile-nav on accueil.html now also includes Service Commande
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Footer copyright bumped to 2026 across all 8 HTML pages and in the
three translation strings (FR/EN/MG) in translations.js.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
New page service-commande.html explaining the order-on-behalf service:
- 10% commission on total order amount
- 50% deposit + 50% on order validation
- Right to request 100% upfront for large orders
- Standard 70,000 Ar/kg shipping fee on top, paid on receipt
- 5-question FAQ
- CTA to contact / Messenger
Trilingual content (FR / EN / MG) added to translations.js with full
serviceCommande section + nav.serviceCommande key.
Menu link inserted right after "Tarifs" in main nav, mobile nav and
footer links across all pages: index, about, tarifs, contact,
guide-envoi, application, cgv, service-commande.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Replace the cramped map-container layout with a polished map-card
- Centered section header (h2 + gold-line + subtitle) above the card
- Navy gradient header inside the card with gold location icon
- Address displayed in the header alongside an "open in Google Maps" CTA
- Increased map height to 420px (320px on mobile)
- Soft shadow and gold-tinted border for premium feel
- Added mapSubtitle translation key (FR/EN/MG)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Ajout de data-i18n sur tous les éléments non traduits (tarifs, contact, guide,
application, accueil) et ajout des clés correspondantes en FR/EN/MG dans
translations.js : détails tarifaires, cartes livraison, stats accueil, sections
CTA, récapitulatif contact, footer CGV.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Mise à jour de toutes les mentions du délai de livraison sur l'ensemble du site
(index, tarifs, contact) et dans les 3 langues (FR/EN/MG) pour indiquer clairement
que les 2 semaines sont comptées à compter de l'arrivée du colis au dépôt de Paris.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Ajout du SDK EmailJS (CDN) dans contact.html
- Initialisation EmailJS avec la clé publique dans form-handler.js
- Nouvelle fonction sendWelcomeEmail() : envoie au client son prénom,
numéro de référence et l'adresse de dépôt Paris (AEIC Forwarding, Orly)
- Appel automatique dans showSuccess() après inscription réussie
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- generateRefNumber() basé sur timestamp : références jamais identiques
- checkExistingContact() : lecture HubSpot via clé de service (read-only)
- Si email déjà connu : affiche message 'déjà client' + référence existante,
AUCUNE soumission envoyée (référence existante jamais modifiée)
- Notification interne Formspree si tentative double inscription
- Traductions FR/EN/MG pour les nouveaux messages