Landing page de Livofit, une application de suivi nutritionnel : scan des repas, suivi de l'hydratation et des pas.
Site statique, sans framework front, sans dépendance runtime hormis un moteur d'animation de 9 Ko. La page complète pèse 116 Ko une fois construite, dont 29 Ko de CSS et 9 Ko de JavaScript.
| Outil | Rôle |
|---|---|
| Astro 5 | Génération statique, composants .astro, zéro JS par défaut |
| Tailwind CSS 4 | Styles, via le plugin Vite — aucun fichier de config |
| Motion | Animations de la section « How it works » (import motion/mini) |
| Poppins | Police, chargée depuis Google Fonts |
La configuration est volontairement minimale : astro.config.mjs
ne contient que le plugin Vite de Tailwind. Tout le design system vit dans le bloc
@theme de src/styles/global.css, d'où Tailwind dérive
automatiquement les classes (bg-surface, text-interactive, shadow-card…).
npm install
npm run devLe site est servi sur http://localhost:4321.
| Commande | Effet |
|---|---|
npm run dev |
Serveur de développement avec rechargement à chaud |
npm run build |
Génère le site statique dans dist/ |
npm run preview |
Sert le résultat du build en local |
src/
├── layouts/
│ └── Base.astro # <head>, lien d'évitement, observateur d'apparition
├── pages/
│ └── index.astro # Assemble les sections
├── components/
│ ├── Navbar.astro # Fixe, fond flouté au scroll, menu mobile
│ ├── Hero.astro # Pleine hauteur d'écran
│ ├── Features.astro # 3 piliers + bande de compléments
│ ├── HowItWorks.astro # Téléphone figé, scroll verrouillé par étape
│ ├── Pricing.astro # Livo / Livo Pro
│ ├── Faq.astro # Accordéon natif <details>, sans JS
│ ├── Download.astro # Badges officiels App Store / Google Play
│ ├── Footer.astro
│ ├── Button.astro # Variantes cta / ghost / soft
│ ├── Icon.astro # Tracés Lucide inlinés, sans dépendance
│ ├── Logo.astro
│ └── illustrations/
│ ├── PhoneFrame.astro # Coque réutilisable, contenu par slot
│ ├── PhoneMockup.astro
│ ├── Doodles.astro # Illustrations au trait, décoratives
│ └── screens/ # Écrans de l'app (placeholders)
├── styles/
│ └── global.css # Design system : tokens, utilitaires, animations
└── public/badges/ # Badges officiels des stores
Accent unique réservé aux CTA, neutres teintés à la complémentaire de l'accent.
| Token | Valeur | Usage |
|---|---|---|
--color-cta |
#ea7653 |
Corail. Un seul CTA par écran |
--color-interactive |
#2b7488 |
Onglets, progression, états, icônes |
--color-interactive-soft |
#92c4d3 |
Remplissages non porteurs de sens |
--color-chip |
#e4f0f4 |
Fond des puces et badges |
--color-bg |
#f4f8fa |
Fond de page, gris très clair bleuté |
--color-surface |
#ffffff |
Cards, posées sur le fond |
--color-element |
#e9eff1 |
Pistes de progression, barres inactives |
--color-border |
#dbe4e7 |
Séparateurs, contours |
--color-ink |
#0f1314 |
Texte principal |
--color-muted |
#5a6c72 |
Texte secondaire |
--shadow-card |
ombre fine | Toutes les cards, jamais les boutons |
Règles d'attribution :
- Un seul CTA corail par écran. C'est sa rareté qui lui donne sa force.
- La progression n'est pas une action : barres et jauges vont en niveau interactif, jamais en CTA.
- Tout état porteur de sens a un label texte, jamais la couleur seule.
--color-cta-washest strictement décoratif (halos, dégradés). Il ne doit jamais habiller un élément actionnable.
Trois mécaniques, toutes neutralisées sous prefers-reduced-motion :
.reveal— apparition au chargement (hero), en CSS pur..reveal-up— glissement de 30 px depuis la gauche à l'entrée dans le viewport, déclenché par un uniqueIntersectionObserverdéclaré dansBase.astro. Le masquage est conditionné à une classejsposée en inline dans le<head>: sans JavaScript, tout le contenu reste visible..pop— apparition en bulle d'un élément à l'intérieur d'un bloc révélé.
La section « How it works » verrouille le scroll étape par étape. L'interception
se fait sur window (et non sur un conteneur overflow) pour fonctionner quelle
que soit la position du curseur, et se relâche aux deux extrémités.
La FAQ anime la hauteur de ::details-content, ce qui fait descendre le panneau
sans toucher au texte. Elle repose sur interpolate-size: allow-keywords : les
navigateurs qui ne le supportent pas encore ouvrent la réponse instantanément,
sans animation.
Vérifié sur la page rendue :
- 157 nœuds de texte testés pour le contraste. Seuls les libellés des CTA
(blanc sur corail, 2,91:1) sont sous le seuil AA — choix de design assumé.
Le noir sur corail donnerait 7,2:1 :
--color-cta-on: #000000. - Un seul
h1, aucun saut de niveau sur 23 titres. - 42 éléments focusables, tous avec un nom accessible, aucun
tabindexpositif. - Lien d'évitement en premier dans l'ordre de tabulation.
- Menu mobile
inertquand il est replié, fermeture parÉchapavec retour du focus au bouton. - Sections nommées par
aria-labelledby, icônes décoratives enaria-hidden.
- Les écrans dans
src/components/illustrations/screens/sont des placeholders dessinés en CSS. Ils seront remplacés par les vraies captures de l'application. - Les liens des stores dans
Download.astropointent vers les pages d'accueil d'App Store et Google Play. - Les pages légales référencées dans le footer (
/privacy,/terms,/cookies,/legal) restent à créer.
- Icônes : Lucide (licence ISC), tracés inlinés.
- Données nutritionnelles : Open Food Facts, sous licence ODbL — l'attribution est obligatoire et figure dans le footer.
- Les badges App Store et Google Play sont les assets officiels d'Apple et de Google, utilisés sans modification conformément à leurs guidelines.