Aller au contenu

Calyx

Une application de nutrition propulsée par l'IA : une photo de repas suffit pour estimer calories, macros et micros, obtenir des idées de recettes et partager ses repas dans un fil social.

  • TypeScript
  • NestJS (Bun)
  • Expo
  • TanStack Start
  • Postgres (Prisma)
Calyx : photographiez votre repas, on s'occupe du reste.

Une photo. Vos calories, vos macros, vos micros.

Une application web et mobile qui analyse la photo d'un repas avec l'IA, estime ses apports nutritionnels, propose des recettes adaptées et permet de partager ses repas avec une communauté.

Fonctionnalités · Architecture


À propos

Suivre ce qu'on mange, c'est souvent chercher chaque aliment dans une base de données, peser, saisir, corriger… et abandonner au bout de trois jours.

Calyx part d'un constat simple :

Le meilleur journal alimentaire est celui qu'on n'a pas à remplir.

Vous prenez votre repas en photo. Une file de tâches en arrière-plan confie l'image à un analyseur IA, qui renvoie une estimation des calories, des macros et des micronutriments. Le résultat arrive dans l'app, prêt à nourrir votre résumé du jour, vos objectifs et un fil social.


✨ Fonctionnalités

📸 Analyse de repas par photo

Un onglet caméra dédié, un cliché, et le repas passe de « en attente » à « prêt » sans bloquer l'interface. L'analyse tourne en tâche de fond, et l'app reflète son état en direct.

  • Capture · caméra intégrée


🏠 Accueil & suivi du jour

Carte de calories, objectif du jour, calendrier de la semaine et liste des repas récents : tout ce qu'il faut en un coup d'œil.

  • Accueil · calories & repas récents


🖼️ Médias privés

Les photos sont envoyées vers un stockage objet derrière un port STORAGE, puis relues via des URLs signées à durée limitée. Aucune image n'est publique par défaut.


🔐 Authentification

Comptes, sessions et routes protégées par défaut avec Better Auth : un AuthGuard global, et un décorateur @Public() pour ouvrir explicitement une route.


🍽️ Recettes & communauté (en construction)

Suggestions de recettes à partir des repas analysés, et fil social pour partager ses assiettes. Le modèle de données est en place ; les cas d'usage arrivent ensuite.


🧱 Architecture

server/ — API NestJS sur Bun (CQRS, architecture hexagonale)
web/ — Front web TanStack Start
native/ — App mobile Expo SDK 58 + expo-router + Uniwind
db/ — Schéma Prisma 7 multi-fichiers, migrations
auth/ — Configuration Better Auth
contract/ — Contrat OpenAPI généré depuis le serveur
api-client/ — Client TypeScript généré par orval
ui/ — Composants shadcn/ui partagés
config/ — Configuration TypeScript partagée
docker-compose.yml — Postgres et Redis pour le développement

🧠 Le serveur : une architecture stricte

La partie la plus structurante du projet. Chaque module de l'API suit les mêmes couches, avec des règles de dépendance vérifiables :

  • interface → application → domain ← infrastructure — les contrôleurs se contentent de parser l'entrée et de dispatcher vers le CommandBus ou le QueryBus. Aucune logique métier.
  • Un handler par commande ou requête — petit, testable, nommé par intention.
  • Un domaine sans dépendance — pas de Nest, de Prisma ni de SDK tiers. Les ports sont des interfaces avec un token d'injection, et les adapters les implémentent côté infrastructure.
  • Des modules étanches — un module n'importe jamais les services d'un autre. Les effets de bord entre contextes passent par des événements de domaine.
  • L'IA derrière un port — NUTRITION_ANALYZER permet de brancher un faux analyseur en développement et en test, puis un vrai modèle sans toucher au reste.
  • Un contrat de bout en bout — les DTO zod produisent l'OpenAPI, committé et vérifié en CI, qui génère à son tour le client utilisé par le web et le mobile.

🛠️ Stack technique

  1. Monorepo

    • Nx
    • Bun (workspaces)
  2. Mobile

    • Expo SDK 58
    • expo-router
    • Uniwind
    • MMKV
    • jest-expo
  3. Web

    • TanStack Start
    • React
    • Tailwind CSS
    • shadcn/ui
  4. API

    • NestJS
    • Bun
    • CQRS (CommandBus / QueryBus)
    • Zod (nestjs-zod)
    • OpenAPI
  5. Auth

    • Better Auth
    • AuthGuard global
  6. Base de données

    • PostgreSQL
    • Prisma 7 (schéma multi-fichiers)
  7. Files de tâches

    • BullMQ
    • Redis
  8. Stockage

    • Supabase Storage
    • URLs signées
  9. Client API

    • orval
    • Contrat OpenAPI partagé
  10. Qualité

    • Oxlint + Oxfmt
    • Jest
    • Tests e2e sous Bun
    • GitHub Actions
  11. Config

    • Varlock
    • .env.schema typé

💡 Ce que j'en retiens

  • Garder le domaine propre. Imposer des ports et des adapters dès le début coûte un peu de cérémonie, mais permet de remplacer l'IA, le stockage ou l'ORM sans réécrire la logique métier.
  • Traiter l'IA comme un service lent et faillible. Une analyse n'est pas une requête synchrone : file de tâches, états explicites (en attente, prêt) et reprise sont nécessaires pour une expérience fluide.
  • Faire du contrat la source de vérité. Le serveur génère l'OpenAPI, l'OpenAPI génère le client, et la CI échoue si l'un dérive de l'autre : web et mobile ne peuvent plus se désynchroniser sans que ça se voie.
  • Faire cohabiter web et mobile dans un seul dépôt. Partager l'auth, le client et la configuration entre TanStack Start et Expo demande de la rigueur sur les dépendances et la config Metro.

📸 Captures d'écran

  • Repas · macros & micros

  • Semaine · suivi des objectifs

  • Profil · état de l’API


🛣️ Roadmap

  • Authentification et routes protégées
  • Santé de l'API (liveness + readiness)
  • Schéma Prisma et migrations
  • Création d'un repas → file d'analyse → statut « prêt »
  • Envoi des photos et URLs signées
  • Écran d'accueil mobile (calories, repas récents)
  • Contrat OpenAPI et client généré, avec contrôle de dérive en CI
  • Vrai modèle d'analyse nutritionnelle (à la place de l'analyseur factice)
  • Validation de l'adaptateur de stockage sur un vrai bucket
  • Recettes suggérées
  • Fil communautaire et partage de repas
  • Application web : écrans fonctionnels

Projet suivant

Configuration Neovim

Une configuration Neovim rapide et orientée TypeScript/JavaScript, construite sur NvChad v2.5, avec synchronisation automatique du thème macOS, une chaîne d'outils lint/format propulsée par oxc, et une intégration aux panneaux Zellij.