24 Commits

Author SHA1 Message Date
ordinarthur
e7872df156 feat(ui): polish across the app with new loaders, skeletons & animations
- ui/shimmer.tsx: reusable shimmer placeholder
- recipe-card-skeleton.tsx: skeleton grid for loading states
- CookingLoader: rebuilt as floating chef hat with orbiting sparkles
- RecipeDetailLoader: now a proper skeleton of the detail page
- PageTransition: smooth fade+lift on route change
- index.css: custom keyframes (shimmer, float, glow-pulse), thin
  scrollbars, :focus-visible, safe-area utilities
- RecipeList: skeleton grid, header with count, polished tabs,
  hover lift on cards, spring FAB on mobile
- Header: scroll-aware blur/shadow, animated active underline,
  auto-close mobile menu on navigation
- MainLayout: ambient blurred blobs in background, warm gradient
- Home hero: gradient pill badge with wobbling Sparkles,
  CTA with sliding sheen
- Login/Register buttons: brand gradient, inline spinners
- Profile: skeleton loading state instead of plain spinner
- RecipeForm streaming: glow halo behind image, blur-to-sharp reveal

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:31:49 +02:00
ordinarthur
460f7d334c feat: streaming recipe generation + user preferences + parallel image gen
Backend:
- Prisma: add user preferences (dietaryPreference, allergies, maxCookingTime,
  equipment, cuisinePreference, servingsDefault) + migration SQL.
  Also make stripeId nullable so signup works without Stripe.
- prompts.ts: buildUserPrompt now takes a BuildPromptOptions with preferences.
  Injects strong, explicit constraints in the user message (vegan rules,
  allergy warnings, time limits, equipment availability, cuisine hints).
- recipe-generator.ts: new streamRecipe() async generator. Streams OpenAI
  chat completion with json_schema strict mode, parses the growing buffer
  to detect 'titre' and 'description' early, yields typed events:
    { type: 'delta' | 'title' | 'description' | 'complete' }
  Final event includes the parsed StructuredRecipe + cost log.
- recipes.ts route: new POST /recipes/create-stream returning SSE:
    event: progress     { step }
    event: transcription{ text }
    event: title        { title }     <- triggers parallel image gen
    event: description  { description }
    event: recipe       { recipe }
    event: image        { url }
    event: saved        { id }
    event: done
  Heartbeat every 15s to prevent proxy timeouts. Image generation is
  kicked off the moment the title is extracted, running in parallel with
  the rest of the recipe stream. Legacy POST /recipes/create still works
  and now also passes user preferences.
- users.ts route: GET /profile now returns preferences (equipment
  deserialized from JSON). New PUT /users/preferences with validation
  (diet enum, time 5-600, servings 1-20, equipment array -> JSON).
- ai.ts plugin: generateRecipe signature extended to accept preferences.

Frontend:
- api/recipe.ts: createRecipeStream() async generator that consumes SSE
  via fetch + ReadableStream + TextDecoder (EventSource can't do POST).
  Parses 'event:' and 'data:' lines, yields typed StreamEvent union.
- api/auth.ts: User interface extended with preferences; new
  UserPreferences type exported.
- api/user.ts: updatePreferences() method.
- RecipeForm.tsx: handleSubmit now consumes the stream. Live UI displays:
    1. Initial cooking loader with step label
    2. Transcription appears as soon as it's ready
    3. Title fades in the moment it's extracted (before the rest of the
       recipe finishes generating)
    4. Description appears right after
    5. Image replaces the loader when ready
    6. Small delay before navigating to the saved recipe detail page
- Profile.tsx: new 'Cuisine' tab with form for diet, allergies, max time,
  servings, cuisine preference, and equipment checkboxes (8 options).

UX improvement: perceived latency is dramatically reduced. Instead of
waiting 40s staring at a spinner, the user sees the title ~3-4s in and
can start reading, while the image finishes generating in parallel.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 12:53:55 +02:00
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
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
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
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