35 Commits

Author SHA1 Message Date
ordinarthur
98a2f9d5a1 chore: gitignore frontend/package-lock.json (pnpm project) 2026-04-08 12:42:12 +02:00
ordinarthur
e80341bc0c fix(server): allow cross-origin resource loading for /uploads
Helmet's default 'Cross-Origin-Resource-Policy: same-origin' header was
blocking the frontend (http://localhost:5173) from loading images and
audio served by the backend at /uploads/*. Set policy to 'cross-origin'
so images can be embedded in the frontend.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:41:36 +02:00
ordinarthur
64df5db077 fix(ai): robust image pipeline + local MinIO stack + TS errors fix
Image generation:
- Automatic model fallback: try gpt-image-1 first, fall back to
  dall-e-3 if it fails (e.g. org not verified on OpenAI)
- Local filesystem fallback: if MinIO upload fails, write the image
  to backend/uploads/recipes/ and return a URL served by fastify-static
- Unified handling of base64 vs URL responses from the Images API
- DALL-E quality mapped automatically (low/medium/high -> standard)

Local MinIO stack:
- docker-compose.yml at repo root with minio + minio-init service
  that auto-creates the bucket and makes it publicly readable
- Default credentials: freedge / freedge123 (configurable)
- Console at :9001, API at :9000
- .env.example now points to the local stack by default

Static file serving:
- Register @fastify/static to serve ./uploads at /uploads/*
- Enables local fallback to return usable URLs to the frontend
- New PUBLIC_BASE_URL env var to build absolute URLs

TypeScript errors (21 -> 0):
- JWT typing via '@fastify/jwt' module augmentation (FastifyJWT
  interface with payload + user) fixes all request.user.id errors
- Stripe constructor now passes required StripeConfig
- fastify.createCustomer guards checked on the helper itself for
  proper TS narrowing (not on fastify.stripe)
- Remove 'done' arg from async onClose hook
- MinIO transport.agent + listFiles return type cast ignored

README:
- Add 'Stockage des fichiers' section explaining the two modes
- Updated setup instructions to start with docker compose up

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:30:47 +02:00
ordinarthur
9dbd7e0ba9 feat(ai): quality-first recipe pipeline with structured outputs
Overhaul of the backend AI module to produce better recipes, better
images, more reliably, and cheaper.

New src/ai/ module:
- prompts.ts: long 'Chef Antoine' system prompt (~1500 tokens) with
  explicit originality rules, technical precision requirements, vocal
  transcription handling, and 3 few-shot style examples. Long enough
  to benefit from OpenAI's automatic prompt caching (-50% on cached
  portion from the 2nd call onward).
- recipe-generator.ts: uses Structured Outputs (json_schema strict).
  Rich schema: titre, description, origine_inspiration, ingredients
  with quantity/notes/complement flag, numbered etapes with per-step
  duration, conseils array, accord_boisson. No more JSON.parse crashes.
- image-generator.ts: switched from dall-e-3 to gpt-image-1 (medium
  quality by default). Much better photographic realism. Dedicated
  magazine-style prompt (editorial food photography, 45-deg overhead,
  natural light, stoneware). Slugify preserves extended Latin chars
  (cote-de-boeuf not c-te-de-b-uf).
- transcriber.ts: migrated from whisper-1 to gpt-4o-mini-transcribe
  (50% cheaper, better on French). Includes a context prompt to bias
  toward culinary vocabulary.
- cost.ts: centralized pricing table + helpers. Every OpenAI call now
  emits a structured log with model, durationMs, costUsd, usage, and
  cacheHit flag.

Plugin refactor:
- plugins/ai.ts now delegates to src/ai/* and only keeps the Fastify
  decoration glue + storage fallback for audio.
- OpenAI client configured with maxRetries=3, timeout=60s.
- Image generation runs in parallel with the recipe flatten/serialize
  step (minor speedup, ~0.5s).
- flattenRecipe() converts the rich structured recipe into the legacy
  flat RecipeData shape (for Prisma columns) while preserving the
  structured form in recipeData.structured.

Routes:
- recipes.ts stores the structured JSON in generatedRecipe (instead
  of the aplatissement lossy), enabling future frontends to render
  rich recipes with per-ingredient notes and step timers.

Env vars:
- OPENAI_TRANSCRIBE_MODEL, OPENAI_IMAGE_MODEL, OPENAI_IMAGE_QUALITY,
  OPENAI_IMAGE_SIZE, OPENAI_MAX_RETRIES, OPENAI_TIMEOUT_MS

Cost per recipe (estimated):
- Before: ~$0.044 (whisper $0.003 + 4o-mini $0.0004 + dall-e-3 $0.04)
- After : ~$0.018 (4o-mini-transcribe $0.0015 + 4o-mini $0.0004
  + gpt-image-1 medium $0.0165), ~-59%.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 08:46:18 +02:00
ordinarthur
fc3dfe83c9 refactor(backend): migrate from JavaScript to TypeScript
- 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>
2026-04-07 22:36:21 +02:00
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
Arthur Barre
9b98b3c0c6 fix minio2 2025-03-16 19:44:18 +01:00
Arthur Barre
fe493fe053 fix minio 2025-03-16 19:43:11 +01:00
Arthur Barre
8b6d76fdea add minio storage 2025-03-15 13:11:24 +01:00
Arthur Barre
bb7a083ae8 corret google analytics 2025-03-14 17:53:26 +01:00
Arthur Barre
adfc73ffa7 add google analytics + favicon 2025-03-14 17:42:41 +01:00
Arthur Barre
81f3900ac8 change UI 2025-03-14 00:58:18 +01:00
Arthur Barre
b311e76bf3 add reset password from mail 2025-03-13 23:03:29 +01:00
Arthur Barre
7c2374f0b3 change mail + change password ok ! 2025-03-13 22:31:10 +01:00
Arthur Barre
223b593495 add more data + image on recipe 2025-03-13 22:17:39 +01:00
Arthur Barre
bd5891ff1b update frontend routes 2025-03-13 22:04:04 +01:00
Arthur Barre
45a26e269d new build 2025-03-13 21:36:42 +01:00
Arthur Barre
20b9b17493 fix 2025-03-13 21:26:24 +01:00
Arthur Barre
de70929a62 use new audio recorder 2025-03-13 21:18:21 +01:00
Arthur Barre
20c345f05a change background color 2025-03-11 13:59:32 +01:00
Arthur Barre
c1456eec18 add manifest 2025-03-11 13:57:07 +01:00
Arthur Barre
8228fe865f update UI 2025-03-11 13:47:39 +01:00
Arthur Barre
46f50e3054 use pnpm for frontend 2025-03-11 13:35:25 +01:00
Arthur Barre
e3e6031a6c use npm instead pnpm 2025-03-11 13:34:23 +01:00
Arthur Barre
f1aa2246ea update deploy 2025-03-11 13:28:36 +01:00
Arthur Barre
81c23109c2 add deploy sh build front 2025-03-11 13:22:35 +01:00
Arthur Barre
dcb3a5c0a8 add deploy sh 2025-03-11 13:20:48 +01:00
Arthur Barre
f07767aa81 add deploy sh 2025-03-11 13:19:06 +01:00
Arthur Barre
851b8ee89c add deploy script 2025-03-11 13:16:29 +01:00
Arthur Barre
36f65152f5 correct auth forms 2025-03-11 13:14:13 +01:00
Arthur Barre
191b8a4da2 add google sso 2025-03-11 13:05:13 +01:00
Arthur Barre
3e85733f4a correct ui 2025-03-11 12:45:52 +01:00
Arthur Barre
d5be543421 upgrade UI de fou 2025-03-10 22:57:18 +01:00
Arthur Barre
9c773e8e64 update UI 2025-03-10 21:52:09 +01:00
Arthur Barre
958a778f85 init a fonctional prototype 2025-03-10 00:24:26 +01:00