- tsconfig.json strict mode (noImplicitAny, strictNullChecks, noUnused*) - Replace nodemon with tsx (watch + run TS directly) - Build script (tsc -> dist/) and typecheck script - Fastify decorator types in types/fastify.d.ts (prisma, openai, stripe, googleClient, auth helpers, ai helpers, request.user) - Typed route handlers with generic Body/Params - Strict null checks on Prisma results and env vars - Stripe plugin now optional (no-op if STRIPE_SECRET_KEY missing) - Delete dead utils/errors.js (empty) and utils/resend.js (contained a hardcoded Resend API key, unused) - Add @types/bcrypt, @types/nodemailer, typescript-eslint - ESLint upgraded to typescript-eslint flat config - deploy.sh: run prisma generate, migrate deploy, backend build Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
4.5 KiB
4.5 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 + TypeScript + 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/ # TypeScript
│ ├── prisma/ # Schéma + migrations SQLite
│ ├── tsconfig.json
│ └── src/
│ ├── plugins/ # auth, ai, stripe, google-auth
│ ├── routes/ # auth, recipes, users
│ ├── types/ # fastify.d.ts (augmentation décorateurs)
│ ├── utils/ # env, storage (MinIO), email
│ └── server.ts
└── 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 (tsx watch) sur :3000
cd ../frontend && pnpm dev # frontend sur :5173
# Build production backend
cd backend && npm run build && npm start # compile vers dist/ puis lance node dist/server.js
npm run typecheck # vérification TS sans build
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 passePOST /auth/login— ConnexionPOST /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éinitialisationPOST /users/reset-password— Réinitialisation avec tokenDELETE /users/account— Suppression du compte (🔒)
Recettes (/recipes) — toutes 🔒
POST /recipes/create— Upload audio + transcription + générationGET /recipes/list— Liste les recettes de l'utilisateurGET /recipes/:id— Détail d'une recetteDELETE /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