freedge/README.md
ordinarthur 0134390f5e refactor: cleanup, security hardening & frontend dedup
Backend:
- Remove malicious crypto dep; use node:crypto
- Add helmet + rate-limit (100 req/min)
- CORS whitelist via CORS_ORIGINS env
- Validate required env vars on boot (fail fast)
- Health endpoint + clean shutdown (SIGINT/SIGTERM)
- Multipart limits (15MB / 1 file)
- Fix findUnique composite where bug (use findFirst)
- Wrap JSON.parse(generatedRecipe) in try/catch
- Isolate DALL-E best-effort; ENABLE_IMAGE_GENERATION toggle
- Lazy MinIO client, safe TLS handling
- Uniform fastify.hashPassword/comparePassword
- Proper audio cleanup on delete
- ESLint flat config, Prettier, .env.example, .editorconfig

Frontend:
- Delete 10 orphan/duplicate components
- Remove orphan pages/recipe/, data/recipes.ts, root src/
- Fix /reset-password route order (was unreachable)
- Remove unused ky dep

Docs:
- README rewritten to match real routes and env vars

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-07 21:00:54 +02:00

4.2 KiB

Freedge

Freedge génère des recettes personnalisées à partir des ingrédients dictés à l'oral. Le son est transcrit (Whisper), une recette est générée (GPT-4o-mini) et une image optionnelle est produite (DALL-E 3).

Stack

  • Frontend : React 19 + Vite + TailwindCSS + ShadCN/UI + React Router
  • Backend : Fastify 4 + Prisma 5 + SQLite
  • IA : OpenAI (Whisper, GPT-4o-mini, DALL-E 3)
  • Stockage : MinIO (S3-compatible) avec fallback local
  • Paiement : Stripe (client créé à l'inscription — intégration abonnement à finaliser)
  • Auth : JWT + Google OAuth

Structure

freedge/
├── backend/
│   ├── prisma/              # Schéma + migrations SQLite
│   └── src/
│       ├── plugins/         # auth, ai, stripe, google-auth
│       ├── routes/          # auth, recipes, users
│       ├── utils/           # env, storage (MinIO), email, resend
│       └── server.js
└── frontend/
    └── src/
        ├── api/             # Clients HTTP (auth, user, recipe)
        ├── components/      # UI shadcn + composants métier
        ├── hooks/           # useAuth, useMobile, useAudioRecorder
        ├── layouts/         # MainLayout
        └── pages/           # Home, Auth/*, Recipes/*, Profile, ResetPassword

Prérequis

  • Node.js ≥ 18
  • pnpm (recommandé) ou npm
  • Une clé API OpenAI
  • (Optionnel) Un serveur MinIO pour le stockage images/audio
  • (Optionnel) Un compte Resend pour les emails

Démarrage

# Installation
cd backend && npm install
cd ../frontend && pnpm install

# Variables d'environnement backend (.env dans backend/)
cp .env.example .env   # puis éditer
# Requis : DATABASE_URL, JWT_SECRET, OPENAI_API_KEY

# Base de données
cd backend
npx prisma migrate dev
npx prisma generate

# Lancement
npm run dev                                # backend sur :3000
cd ../frontend && pnpm dev                 # frontend sur :5173

Variables d'environnement backend

Variable Requis Description
DATABASE_URL URL Prisma (ex: file:./prisma/dev.db)
JWT_SECRET Clé JWT (≥ 32 caractères recommandé)
OPENAI_API_KEY Clé API OpenAI
PORT Port du serveur (défaut 3000)
CORS_ORIGINS Origines autorisées, séparées par virgule
FRONTEND_URL URL frontend pour les emails de reset
ENABLE_IMAGE_GENERATION false pour désactiver DALL-E
OPENAI_TEXT_MODEL Défaut gpt-4o-mini
STRIPE_SECRET_KEY Clé Stripe (pour créer les customers)
MINIO_ENDPOINT / MINIO_PORT / MINIO_USE_SSL / MINIO_ACCESS_KEY / MINIO_SECRET_KEY / MINIO_BUCKET Config MinIO ; fallback local sinon
MINIO_ALLOW_SELF_SIGNED true pour autoriser TLS auto-signé (DEV uniquement)
RESEND_API_KEY Clé Resend pour les emails

Routes API (préfixe /)

Auth (/auth)

  • POST /auth/register — Inscription email + mot de passe
  • POST /auth/login — Connexion
  • POST /auth/google-auth — Connexion/inscription via Google OAuth

Utilisateurs (/users)

  • GET /users/profile — Profil courant (🔒)
  • PUT /users/profile — Mise à jour du nom (🔒)
  • PUT /users/change-password — Changement de mot de passe (🔒)
  • PUT /users/change-email — Changement d'email (🔒)
  • POST /users/forgot-password — Demande de réinitialisation
  • POST /users/reset-password — Réinitialisation avec token
  • DELETE /users/account — Suppression du compte (🔒)

Recettes (/recipes) — toutes 🔒

  • POST /recipes/create — Upload audio + transcription + génération
  • GET /recipes/list — Liste les recettes de l'utilisateur
  • GET /recipes/:id — Détail d'une recette
  • DELETE /recipes/:id — Supprime une recette

Divers

  • GET /health — Healthcheck

🔒 = nécessite un JWT Authorization: Bearer <token>

Sécurité

  • Helmet + rate-limit (100 req/min) activés
  • CORS whitelisté via CORS_ORIGINS
  • JWT signé, expiration 7 jours
  • Bcrypt (10 rounds) pour les mots de passe
  • Validation des variables d'environnement au démarrage

Licence

MIT