7 Commits

Author SHA1 Message Date
ordinarthur
21c92abc9c feat: implement Kubernetes deployment infrastructure, migrate database to PostgreSQL, and add CI/CD pipeline
Some checks failed
Build & Deploy to K3s / build-and-deploy (push) Failing after 24s
2026-04-11 14:09:16 +02:00
ordinarthur
339de4c44c feat(stripe): full subscription flow (checkout, portal, webhooks)
Backend:
- Prisma: add stripeSubscriptionId, subscriptionStatus, priceId,
  currentPeriodEnd to User + migration SQL
- plugins/stripe.ts: getPlans catalog with env-based price IDs
- server.ts: raw body JSON parser for webhook signature verification,
  skip rate limit on /stripe/webhook
- types/fastify.d.ts: declare rawBody on FastifyRequest
- routes/stripe.ts (new):
  - GET  /stripe/plans        public
  - GET  /stripe/subscription user status
  - POST /stripe/checkout     hosted Checkout Session, lazy-creates
    customer, dynamic payment methods, promo codes enabled
  - POST /stripe/portal       Billing Portal session
  - POST /stripe/webhook      signature verified, handles
    checkout.session.completed, customer.subscription.*,
    invoice.payment_failed. Resolves user by clientReferenceId,
    metadata.userId, or stripeId fallback
- .env.example + README: Stripe setup, stripe CLI, test cards

Frontend:
- api/stripe.ts typed client (getPlans, getSubscription,
  startCheckout, openPortal)
- pages/Pricing.tsx: 3-card grid (free/essentiel/premium) with
  popular badge, current plan indicator, gradient popular card
- pages/CheckoutSuccess.tsx: animated confirmation with polling on
  /stripe/subscription until webhook activates plan
- pages/Profile.tsx: SubscriptionCard above tabs — free users see an
  upgrade banner, paid users see plan + status + next billing date
  + 'Gérer l'abonnement' button opening Customer Portal
- components/header.tsx: 'Tarifs' link in nav
- App.tsx: /pricing (public) and /checkout/success (protected) routes

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-08 13:54:27 +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
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
191b8a4da2 add google sso 2025-03-11 13:05:13 +01:00
Arthur Barre
958a778f85 init a fonctional prototype 2025-03-10 00:24:26 +01:00