# Changelog

All notable changes to Epicure are documented here. This file is mirrored in-app at `/changelog` (and in the admin dashboard) via `apps/web/lib/changelog.ts` — update both together.

## 0.87.0 — 2026-07-24 21:50

### Added
- Admin → Ingredients: search box (name + alias), category filter with live counts, aliases entered as removable tag chips, and category picked from a dropdown instead of free text — needed once the list grew past a handful of entries.

## 0.86.0 — 2026-07-24 21:30

### Added
- Ingredient-alias matching now covers ~137 common bilingual EN/FR ingredients across all grocery categories (was ~10) — produce, dairy/eggs, meat/seafood, bakery, frozen, pantry staples, spices/condiments, and beverages.

### Fixed
- Ingredient name matching (pantry, can-cook, auto-deduct, shopping-list generation) now ignores accents as well as case — "café"/"Café"/"cafe" and "Épinard"/"epinard" all recognized as the same ingredient.

## 0.85.0 — 2026-07-24 21:00

### Added
- Admin → Ingredients: manage canonical ingredients and their name variants (e.g. "sel"/"sel fin"/"table salt") without a code change — previously only editable by hand in the seed file.

### Fixed
- Deleting a shopping list, recipe, or collection from its own page could leave you one back-button press away from a "Page not found" screen — the deleted URL stayed in browser history. Now replaces the history entry instead of pushing a new one.

## 0.84.0 — 2026-07-24 20:00

### Added
- Pantry items can be dragged between categories, like the shopping list. All 9 categories now always show (even empty ones) as drop targets, instead of only categories that already have items.
- Pantry has an "Auto-categorize" action, same heuristic as the shopping list's.

### Fixed
- Pantry item edit dialog's category dropdown showed the raw stored value (e.g. "__other__", "produce") instead of its translated label.
- Merging duplicate pantry items now works even when quantities differ, are missing, or use different units — previously two rows only merged if their units matched exactly, so "garlic" (no quantity) and "ail" (3, no unit) wouldn't merge at all.

## 0.83.0 — 2026-07-24 19:00

### Added
- Pantry items can now have notes and a category, with the list grouped into collapsible category sections like the shopping list.
- Ingredient-alias matching: pantry items, recipe ingredients, and shopping-list generation now recognize that "sel", "sel fin", and "table salt" are the same ingredient (seeded with ~10 common EN/FR staples) — improves can-cook scoring, auto-deduct-on-cook accuracy, and pantry-awareness when generating a shopping list.
- A "Merge duplicates" button in the pantry cleans up items that turn out to be the same ingredient under a different name, summing quantities where possible.
- Cook log entries (from "Mark cooked") can now be edited and deleted, not just created. The "Cooked N times" text is a hover tooltip listing every date, and opens a full history sheet on click.
- The "Forked by N others" backlink on a recipe page is now a click-to-open popover instead of an inline list, so a heavily-forked recipe doesn't grow a long list directly on the page.

### Fixed
- Pantry and shopping-list quantities were displayed with their full stored precision (e.g. "0.3333 kg", "2.0000 kg") everywhere — in-app, print views, and Markdown exports. Now rounded/fraction-formatted consistently with recipe ingredient display.

## 0.82.0 — 2026-07-24 17:45

### Added
- A recipe page now shows "Forked by N others" with links to each fork, alongside the existing "Forked from X" backlink — visible on both sides of a fork now, not just one. Private forks stay private: only shown to their own author, never to other viewers of the original.

## 0.81.0 — 2026-07-24 17:15

### Added
- Locked-feature upgrade prompts now route straight to Settings → Billing (with a banner naming the feature you were trying to use) instead of a generic support-ticket form.
- Every upgrade-prompt click is now recorded (feature key only, best-effort) so Admin → Insights can show which locked features are actually driving upgrade interest, in a new "Most-requested locked features" chart.

## 0.80.0 — 2026-07-24 16:45

### Added
- Recipe version history is now a 10th per-tier feature flag (enabled by default, same as variations/pairings), with the same locked-vs-hidden treatment as the others.
- Upgrade prompts for locked features now show real detail — a tagline and 2-3 concrete bullet points per feature — instead of one generic sentence for every feature.

### Fixed
- The AI-generate dialog's Photo tab was a second, completely unguarded entry point into recipe_import_photo — reachable and fully functional regardless of the feature being disabled for your tier, even though the dedicated Photo Import button was correctly gated. Now hidden/locked in step with every other entry point (server-side enforcement in the API route was already correct; this was a UI-only gap).

## 0.79.0 — 2026-07-24 16:00

### Fixed
- Standardized locked-feature treatment across every per-tier gated feature: if a feature is enabled on at least one tier, it stays visible with a "Pro" badge (clicking opens an upgrade prompt) instead of hiding; only a feature disabled on every tier hides outright. Applies to recipe variations, meal/drink pairings, nutrition estimation, Markdown export (recipe, meal plan, shopping list, collection, pantry), weekly nutrition, import from URL, import from photo, and the Instacart grocery-delivery option.

## 0.78.3 — 2026-07-24 15:00

### Fixed
- Recipe variations button: removed the small lock icon that overlapped the branch icon when the feature was locked for your tier. The button is visible again (clicking opens an upgrade prompt) and the tooltip now shows a "Pro" badge instead.

## 0.78.2 — 2026-07-24 14:30

### Fixed
- Ingredient substitutes popover was a fixed 320px wide, cramping the name/ratio/impact-badge row on narrow screens. Now scales with viewport (`min(92vw, 26rem)`) and wraps the ratio onto its own line on small widths instead of squeezing everything into one row.

## 0.78.1 — 2026-07-24 14:10

### Fixed
- Recipe variations button was the one leftover spot still shown disabled with a small lock badge for tiers without the feature, instead of hidden entirely like every other gated feature. Now hidden, matching meal/drink pairings, nutrition estimation, and Markdown export.

## 0.78.0 — 2026-07-24 13:40

### Fixed
- Marketing/vitrine pages now honor a first-time visitor's browser language (Accept-Language) instead of always defaulting to English until they manually switch. An explicit choice from the language switcher still wins on every later visit.

## 0.77.0 — 2026-07-24 13:00

### Added
- New post-signup onboarding wizard: a quick 3-step flow (welcome, dietary preferences & allergens, notification opt-in) shown once for new accounts, skippable at every step. Existing accounts are unaffected — only new signups see it.

### Fixed
- Allergen preferences (the `user_allergens` table) had a GDPR-export read path but no way to actually set them — the onboarding wizard's dietary/allergen step is the first UI that writes to it.

## 0.76.0 — 2026-07-24 12:15

### Added
- Settings → Billing now has a billing/invoice details section: full name (required), address, and phone number (both optional). Separate from your display name — this is what will appear on future invoices.

## 0.75.0 — 2026-07-24 11:30

### Added
- Mark any recipe as cooked (not just batch-cook dishes) — log the date, servings made, and whether to deduct matching ingredients from your pantry. Log the same recipe cooked as many times as you like; the recipe page shows how many times and when you last cooked it.

### Fixed
- Auto-deduct pantry on cook now actually fires — both existing mark-cooked flows (batch-cook dishes, meal-plan entries) previously hardcoded it off despite the underlying logic working correctly.

## 0.74.0 — 2026-07-24 10:30

### Added
- 6 new per-tier feature flags, admin-toggleable from Admin → Tier Limits, all shipped OFF by default: import from URL, import from photo, meal/drink pairings, nutrition estimation, Markdown export, weekly nutrition, and grocery delivery (Instacart). Hidden from the UI entirely (not just locked) until an admin turns them on for a tier.
- Language switcher now shows a flag icon next to English/Français instead of plain text, in both the logged-in Settings page and the logged-out marketing switcher (shared flag component).

### Fixed
- BYOK section on Settings → AI is now hidden entirely for non-BYOK users, matching the Model Prefs picker's treatment — was previously shown with a "locked" notice teasing a feature most users have no path to unlocking themselves.

## 0.73.1 — 2026-07-24 09:30

### Fixed
- Settings → AI's model picker (choose a specific provider/model like `gpt-4o-mini` or `o3-mini` per AI feature) had no access gate at all — every user could see and use it, regardless of whether they had any reason to. Now hidden unless you have BYOK access, since picking a specific model only matters once you've got your own key to route it to.

## 0.73.0 — 2026-07-23 14:00

### Added
- Real Stripe billing for Pro/Family: subscribe and manage your plan yourself at Settings → Billing (Checkout + Stripe's hosted Customer Portal for cancel/upgrade/card updates), instead of only an admin being able to change your tier. Cancel takes effect at the end of the paid period.
- Admin → Billing: connection status, subscriber counts, past-due payments needing attention, recent billing events. Admin → Tier Limits gained Stripe Product/Price ID fields per tier.

Family tier is purchasable solo but doesn't yet support inviting other accounts into a shared subscription — that's a separate, larger piece tracked in `plans/STRIPE_PLAN.md`, deliberately shipped after solo billing.

## 0.72.0 — 2026-07-23 09:30

### Added
- Developer access (webhooks + API keys) is now self-serve for any paid-tier user, free of charge — enable it yourself in Settings instead of waiting on an admin. Free tier still needs an admin grant. BYOK is now a fully separate permission, admin-only, unaffected by the self-serve change.

## 0.71.0 — 2026-07-22 10:00

### Added
- New "developer access" permission, admin-toggled per user (Admin → Users), gates webhooks, self-serve API keys, and BYOK AI provider keys — previously available to every logged-in user with no gating at all. Anyone who already had a webhook, API key, or BYOK key configured keeps access automatically.

## 0.70.0 — 2026-07-22 09:30

### Added
- Recipe nutrition estimation now looks up real per-ingredient data from USDA FoodData Central (for ingredients whose quantity/unit converts to grams — e.g. "200g flour", "2 tbsp oil") and only asks AI to estimate whatever's left (count-based units like "2 cloves", or ingredients with no USDA match). Configure `USDA_API_KEY` in Admin → Settings (free, no partnership needed) — unset, it falls back to the previous fully-AI-estimated behavior exactly as before.

## 0.69.0 — 2026-07-22 09:00

### Added
- Nutrition page gets a Trend tab alongside the daily Diary: a 7/30/90-day calorie chart plus daily protein/carbs/fat averages, computed from the same cooking history the diary already tracks.

## 0.68.0 — 2026-07-21 10:00

### Added
- Meal plans can now be shared with a read-only anonymous public link (Share → Public link), same idea as shopping lists' public link but view-only, plus a QR code you can screenshot or print to hand someone the week's plan.

## 0.67.0 — 2026-07-21 09:30

### Added
- Epicure now registers as an OS share target (Chromium/Android, once installed): share a recipe link from another app's share sheet and it opens straight into the URL-import flow, pre-filled and auto-imported. Safari has no equivalent API — Chromium/Android only, same restriction as the install-prompt banner.

## 0.66.0 — 2026-07-21 09:00

### Added
- Moderator role is now wired up: moderators get access to Admin → Reports (view/resolve) and Admin → Recipes (view + unpublish a public recipe as a takedown action). Every other admin section stays admin-only, enforced server-side on each page, not just hidden from the nav.
- Push notifications now actually display. The service worker had no `push` event listener at all, so incoming push messages never showed anything — fixed, plus a `notificationclick` handler that focuses an existing tab or opens one at the notification's target URL.

## 0.65.3 — 2026-07-21 01:20

### Fixed
- Removed a stale `app/favicon.ico` left over from the original create-next-app scaffold (the default Next.js/Vercel triangle logo) — Next's file-based routing served it as `/favicon.ico` regardless of the app icon configured via `icon.svg`, so some browsers showed the placeholder logo instead of Epicure's icon no matter what cache state you were in. The SVG icon is now the only favicon source.

## 0.65.2 — 2026-07-21 01:10

### Fixed
- The "Save offline" button on the recipe page was a labeled outline button, inconsistent with the icon-only ghost + tooltip style every other recipe action button (print, share, export) uses. Now matches.

## 0.65.1 — 2026-07-21 01:00

### Added
- The install banner now shows an iOS Safari-specific instructional variant ("Tap Share, then Add to Home Screen") instead of silently doing nothing — Safari never fires the event the regular Install button depends on, so it had no install guidance at all before this.

## 0.65.0 — 2026-07-21 00:45

### Added
- Save recipes for offline use: a "Save offline" button on any recipe pins it in the service worker cache so it opens with no connection. The offline fallback page now lists your saved (and recently visited) recipes instead of being a dead end.
- Marking a batch-cook dish as cooked while offline no longer just fails — it's queued and synced automatically once you're back online (via Background Sync where supported, otherwise as soon as the app detects a connection).

### Fixed
- The service worker's network-first pages never actually populated its cache on success, so the offline page's claim that "recently visited recipes are available" wasn't true. It does now.

## 0.64.0 — 2026-07-21 00:30

### Fixed
- The web app manifest was never actually linked into the page (pointed at `/manifest.json`, but the real route is `/manifest.webmanifest`) and its icons referenced PNGs that don't exist in the repo — both silently broke install eligibility on Chrome/Android. Manifest now links correctly and icons point at the existing SVGs.

### Added
- Added apple-mobile-web-app meta tags and a `viewport-fit=cover` safe-area setting for iOS home-screen installs.
- Added an install-app banner (Chrome/Edge/Android only, via the standard `beforeinstallprompt` event) so the PWA install prompt is a first-class, dismissible UI element instead of relying on the browser's own icon.

## 0.63.0 — 2026-07-21 00:15

### Added
- Support tickets now sync two-way with their linked Gitea issue: closing/reopening the issue in Gitea updates the ticket's status, and comments on either side (Epicure or Gitea) show up in both places. Configure a webhook secret (`GITEA_WEBHOOK_SECRET`) on the Gitea repo's webhook, subscribed to Issues and Issue Comment events, pointed at `/api/webhooks/gitea`.

## 0.62.0 — 2026-07-20 23:45

### Added
- Settings → Features: new Chatbots toggle — hides both the recipe cooking-chat panel and the recipe-list cooking assistant when off.

### Fixed
- Feature toggles (Settings → Features) were only respected by the mobile hamburger menu — the desktop horizontal nav still showed every item regardless of your saved preferences. Both now read the same visibility list.

## 0.61.0 — 2026-07-20 23:15

### Added
- Settings → Notifications now has an email toggle for every category alongside the existing push toggle, plus a Weekly Digest toggle to opt out of the weekly email summary entirely.
- Admin → Webhooks: site-wide ops webhooks (new signups, support tickets, reports filed) — separate from the existing per-user webhooks, for Slack/Discord-style ops alerting.
- Settings → Features: hide Nutrition, Pantry, Meal Plan, Shopping Lists, Collections, or Messages from your own navigation. Cosmetic only — hidden pages stay reachable by direct link.

## 0.60.0 — 2026-07-20 22:15

### Security
- Closed a race in recipe/storage tier-limit checks — two concurrent requests near the cap could both pass a live count check and both write, exceeding the lifetime limit. Now locked per-user inside the same transaction as the write.
- Fixed four AI recipe-creation routes (photo import, idea generation, batch-cook, translate-to-new-draft) that had no recipe-limit check at all, letting any tier create unlimited recipes through them.
- Added missing per-user rate limits to 5 AI endpoints (adapt, drinks, pairings, translate, variations).
- Search page now checks for a session server-side, matching every other page (defense-in-depth — the underlying API was already public by design and the edge proxy already blocked unauthenticated access).
- Upgraded drizzle-orm to fix a SQL-identifier-escaping vulnerability, and overrode two transitive dependencies (esbuild, postcss) with known CVEs — `pnpm audit` is now clean.

### Fixed
- Admin settings endpoint now uses the shared admin-auth check instead of a local duplicate.
- Documented two admin support-ticket endpoints that were missing from the OpenAPI spec.

## 0.59.0 — 2026-07-20 21:15

### Added
- Admin: chatbot now has its own default-model setting, separate from generic text generation — the general assistant and per-recipe Q&A chat can be pointed at a different model than recipe generation.
- Admin: tool calling (the chatbot's inline recipe/shopping-list drafting) can be toggled off — useful for a local/Ollama model that doesn't reliably support it, so the bot falls back to plain text answers instead.

### Fixed
- Simplified the admin AI Configuration page — it showed the same provider keys and routing settings twice (once read-only, once as an edit form). Merged into one section.

## 0.58.0 — 2026-07-20 21:00

### Fixed
- Recipe count and storage usage were incorrectly reset every month, same as AI calls — a user near their recipe/storage cap got fresh room on the 1st even though nothing was deleted. Only AI calls are meant to be monthly; recipes and storage are now lifetime totals derived live from actual data (recipes, photos, avatar), so deleting something is itself what frees up quota.
- Removing your avatar from Settings silently did nothing — the client sent a field the API didn't recognize, so the update was a no-op.

## 0.57.2 — 2026-07-20 20:15

### Fixed
- The previous chatbot fix only caught the model spelling a recipe out as prose. The more common case: a short reply that claims a draft exists ("here's a draft, check below") without ever calling the tool, so nothing renders. Now also detects recipe-creation intent from the user's own message and forces the tool call in that case too.

## 0.57.1 — 2026-07-20 20:00

### Fixed
- Chatbot sometimes answered "create a recipe" requests with the recipe spelled out as prose instead of the actual draft card (weaker/free-tier models occasionally ignore the tool-calling instruction). Now detects that shape and forces one retry with the tool call required, so the draft card still appears.

## 0.57.0 — 2026-07-20 09:20

### Added
- Cooking assistant, fullscreen on desktop, now has a persistent conversation sidebar on the left (like ChatGPT/Claude) instead of a dropdown menu. Mobile and the normal drawer view keep the dropdown.

## 0.56.0 — 2026-07-20 09:10

### Added
- Step timers in the recipe editor now take a unit (seconds/minutes/hours) instead of forcing everyone to do the math into seconds. Editing an existing recipe shows the timer in whichever unit divides evenly into what's stored.

### Fixed
- Ingredient list on the recipe page didn't line up — the quantity column only had a minimum width, so a longer value pushed that row's ingredient name further right than the others. Switched to a shared grid column so every row's name starts at the same spot.

## 0.55.3 — 2026-07-19 19:00

### Fixed
- Admin Insights page's actual crash, found from server logs: the page (a server component) was passing plain formatter functions as props into its chart components (client components) — React can't serialize functions across that boundary. Replaced with a plain string prop ("day" vs "month") formatted inside the client component instead.

## 0.55.2 — 2026-07-19 18:20

### Fixed
- Admin Insights page could 500 the whole panel if any one of its six aggregate queries failed — replaced a non-standard positional GROUP BY with the expression-repeat pattern used everywhere else in the codebase, and made the six queries independent (Promise.allSettled) so one failing degrades that one chart instead of crashing the page.

## 0.55.1 — 2026-07-19 18:05

### Fixed
- Chatbot's rename/delete buttons for a conversation were hover-only, so they never appeared on mobile (no hover state on touch). Now always visible.

## 0.55.0 — 2026-07-19 17:50

### Added
- New Admin > Insights page — signups and recipes-created over the last 30 days, users by tier, recipes by visibility, monthly AI usage, and support tickets by status. Charts are hand-built (hover tooltips, table-view fallback, colorblind-safe palette), no new dependency.

## 0.54.1 — 2026-07-19 17:25

### Added
- Public collections are now viewable by logged-out visitors at /c/{id} (no account needed), same as public recipes at /r/{id} — the collection's QR code/print link and the new "view publicly" icon on the collection page both point here. Followers-only collections check the visitor's follow status the same way followers-only recipes do.

## 0.54.0 — 2026-07-19 17:05

### Added
- Collections now have the same visibility options as recipes — private, followers-only, unlisted, or public — replacing the old public/private toggle. Fork, favorite, and viewing a collection all respect the new followers-only option the same way recipes do.
- Collection PDF exports now include a QR code linking back to the collection, same as recipe PDFs.

## 0.53.1 — 2026-07-19 16:10

### Fixed
- Drag-reorder in a collection now animates live as you drag instead of only updating on drop, and the grip handle is now visible instead of an invisible hover target.
- "Edit" was untranslated everywhere it's used (missing from both languages, not just French).
- Recipes generated via "Generate meal", weekly meal plan, or "Adapt recipe" never had their language recorded — this made the Translate button appear even though the recipe was already in your language. Fixed at the source for all three.
- The Translate dialog itself was hardcoded in English regardless of app language — now fully translated.

### Added
- Recipe tags now show on the recipe detail page.
- Collection header actions are now icon-only with tooltips, matching the recipe page.
- Searching collections now also matches recipes inside them.
- Explore links to "Discover collections" next to its tabs.

## 0.53.0 — 2026-07-19 15:20

### Added
- Collections got a big upgrade: drag-and-drop reorder recipes, search collections and search within a collection, edit name/description/tags/private notes, delete with a choice to also delete the recipes (only ones you own), and tags/labels on collections themselves.

### Fixed
- Collection cards showed the wrong recipe count (capped at 1) — now a real count. Cards also got a visual refresh (photo collage preview) and collection detail pages now use the same recipe card as the main Recipes page.

## 0.52.1 — 2026-07-19 14:10

### Fixed
- Steps with no timer sometimes showed a stray "0" on the recipe page, cook mode, and print views — a step whose timer happened to be stored as 0 (rather than empty) hit a JS truthiness quirk where `0 && ...` renders the literal 0 instead of nothing.

## 0.52.0 — 2026-07-19 13:55

### Added
- Generate a complete meal from a collection — pick a theme and 2+ courses (starter, main, side, dessert, drink), AI generates one coherent, matching recipe per course and adds them all to that collection in one go.

## 0.51.7 — 2026-07-19 13:35

### Fixed
- Account dropdown menu: "View profile" and "Settings" now have icons like every other item in the menu, and there's a new separator grouping the account/support links apart from the theme switcher.

## 0.51.6 — 2026-07-19 13:20

### Fixed
- Image attachments on support tickets now embed inline in the Gitea issue (rendered preview) instead of just a plain link. Also fixed the admin "Create Gitea issue" retry action, which was dropping attachments entirely and only ever sent the ticket description.

## 0.51.5 — 2026-07-19 13:05

### Fixed
- Gitea issue creation was sending label names ("bug", "enhancement") where Gitea's API expects numeric label IDs, failing with a 422 on every attempt. Now looks up the repo's actual label IDs by name first — issues still get created (just unlabeled) if the repo doesn't have matching labels yet.

## 0.51.4 — 2026-07-19 12:50

### Fixed
- Gitea issue creation failures now log the real network-level cause server-side (DNS/connection/timeout, not just "fetch failed") and surface a more specific message in the admin support view's tooltip.

## 0.51.3 — 2026-07-19 12:35

### Fixed
- Admin Settings' Gitea Integration section now spells out exactly what each field expects and what token scope to grant, instead of a one-line hint.

## 0.51.2 — 2026-07-19 12:20

### Fixed
- Recipe cover placeholder icons now use a solid color instead of a transparent one — the transparency darkened wherever an icon's own strokes overlapped, showing up as an uneven blotch on icons like the chef's hat or croissant.

## 0.51.1 — 2026-07-19 12:05

### Added
- More icon choices for custom recipe covers — dish icons went from 16 to 29 (banana, grape, citrus, hamburger, popcorn, bean, vegan, utensils, leaf, shrimp, cooking pot, candy, nut), drinks got milk.

## 0.51.0 — 2026-07-19 11:40

### Added
- Pick your own recipe cover color + icon in the recipe editor (below Photos) — used whenever that recipe has no photo. Also toned down the auto-generated placeholder colors from the previous release, which were too saturated next to real cover photos.

## 0.50.2 — 2026-07-19 10:15

### Fixed
- Recipes without a cover photo now get a varied gradient + food/drink icon instead of the same flat emoji everywhere — deterministic per recipe, so it stays stable across reloads. Applied to the Recipes grid/list, Explore/collections cards, and public profile pages.

## 0.50.1 — 2026-07-19 09:30

### Fixed
- Password sign-in for 2FA-enabled accounts could silently bounce back to the login page with no error shown — the app was pushing straight to /recipes on any non-error sign-in response, racing the SDK's own redirect to the 2FA code screen and sometimes losing. Now waits for that case explicitly.

## 0.50.0 — 2026-07-18 14:20

### Added
- Per-tier feature toggles, managed from Admin > Tier Limits. Recipe variations, drink pairing, and meal pairing can each be disabled for a tier (e.g. Free) — the buttons stay visible but show an upgrade prompt instead of running, and the API rejects the call server-side either way.

## 0.49.1 — 2026-07-18 13:10

### Added
- Support form now accepts attachments — screenshots or files (images, PDF, text, JSON, zip; up to 5 files, 10MB each). They're linked in the confirmation email's Gitea issue and shown as thumbnails on your ticket history and in the admin support view.

## 0.49.0 — 2026-07-18 12:30

### Added
- New Support page — report a bug, share a suggestion, or ask a question right from the app. Submissions email you a confirmation and (if an admin has configured a Gitea repo in Settings) automatically open a tracked issue. Admins get a Support section in the admin panel to triage tickets and retry issue creation.

## 0.48.2 — 2026-07-18 11:15

### Fixed
- Marketing site's language switcher no longer uses emoji flags (inconsistent rendering across OS/browsers) — now inline SVG flags in a proper dropdown menu. Home page's feature grid also got a 9th highlight (personalized recommendations) so the last row isn't left half-empty.

## 0.48.1 — 2026-07-18 11:00

### Added
- Marketing site: language switcher (flag toggle, EN/FR) and a dark-mode toggle in the header — both work for logged-out visitors, no account needed. Features/Home now also cover cook mode, recipe variations, personalized recommendations, and ingredient substitution. Signup CTAs now say "Signups closed" instead of "Get started free" when signups are disabled.

## 0.48.0 — 2026-07-18 09:45

### Added
- Public marketing pages — Home, Features, About, Privacy, Terms, Contact — visible to logged-out visitors at the root domain, plus a sitemap and robots.txt. Logged-in users hitting "/" still land straight in the app, unchanged.

Note: Privacy and Terms are structural drafts, not lawyer-reviewed (see `VITRINE_PLAN.md` §4). Pricing page intentionally not included yet (waiting on Stripe Checkout per `STRIPE_PLAN.md`).

## 0.47.0 — 2026-07-18 00:30

Renamed the "Team" billing tier to "Family" (free/pro/family) — same limits, same admin editing, just the name. Existing Team users keep their tier/limits unaffected; the DB enum value itself was renamed in place (no data migration needed).

## 0.46.2 — 2026-07-17 19:20

### Fixed
- Recipe editor's ingredient and step rows were cramped on mobile — 4 inline fields plus a timer/delete button squeezed into one row with no real wrap plan. Both now stack sanely on narrow screens (name/quantity/unit on one line, note/timer + delete on the next) and stay a single row on larger screens.

## 0.46.1 — 2026-07-17 19:05

### Fixed
- Asking the cooking assistant to create a recipe would often just get you the recipe typed out in the chat instead of the createRecipe draft card — the instruction telling the model to use the tool was a soft suggestion, not a hard rule. Made it explicit: full recipes must go through the tool, never as plain-text ingredients/steps in the reply.

## 0.46.0 — 2026-07-17 18:00

### Added
- The cooking assistant can now also propose adding items to a shopping list ("add that to my shopping list") — pick an existing list or name a new one, then confirm. Same no-action-without-confirmation pattern as recipe creation, going through the same endpoints the manual "Add to shopping list" button already uses.

Note: generateMealPlan is still not built as a chat tool — the existing meal-plan-generation endpoint generates and saves in one step with its own input shape (week/preferences, not a specific plan to save), so it doesn't fit the draft-then-confirm pattern the other two tools use without a larger change to that endpoint.

## 0.45.0 — 2026-07-17 17:30

### Added
- The cooking assistant can now propose creating a recipe when you explicitly ask it to ("make me a recipe for X", "write that down") — it drafts one right in the chat with a Create/Discard choice. Nothing is saved until you confirm; confirming goes through the same recipe-creation endpoint (and the same per-tier recipe limit) as the manual editor.

Note: this is the first step of chatbot-driven actions — only recipe creation for now. Adding to a shopping list or generating a meal plan from chat are tracked as follow-ups, not yet built.

## 0.44.1 — 2026-07-17 17:00

### Fixed
- Every recipe page was broken (server error) since 0.41.0 — the new followers-visibility check referenced the user_follows table incorrectly inside a query the ORM rewrites in a way that silently produces invalid SQL for cross-table references. Fixed by using a literal table reference instead.

## 0.44.0 — 2026-07-17 16:15

### Added
- New "Team" billing tier, above Pro — higher AI-call, recipe, and storage limits, editable from Admin > Tiers like the existing tiers. (Moderator/admin remain separate account roles, unrelated to billing tier — unchanged by this.)

## 0.43.0 — 2026-07-17 15:45

### Added
- The cooking assistant now supports multiple named conversations — start a new one, rename, or delete from the conversations menu in the chat header. Auto-titled from your first question; older single-thread history stays as-is but isn't shown in the new list.

## 0.42.0 — 2026-07-17 15:15

### Added
- Recipe editor now has "Regenerate with AI" — describe what to change (e.g. "make it spicier", "swap in chicken") and the draft you're editing updates in place, no new recipe created. You still need to save.

## 0.41.0 — 2026-07-17 14:45

### Added
- New recipe visibility option: "Followers only" — visible to people who follow you, hidden from public browsing, search, and anonymous share links. Available in the recipe editor, bulk visibility actions, and the Recipes filter.

Note: public profile pages and search results don't yet surface a viewer's followers-only recipes from that author — those remain reachable only via the recipe's direct link or the Following feed.

## 0.40.0 — 2026-07-17 14:00

### Added
- AI Settings now shows a usage panel — AI calls, recipes created, and storage used this month against your tier's limits, with progress bars.

## 0.39.0 — 2026-07-17 13:30

### Fixed
- Adapting/varying a recipe with AI could fail silently (no error shown) on a network hiccup, and could save a byte-for-byte duplicate recipe when the AI's output didn't actually differ from the original — both flows now surface real errors and skip saving when nothing changed. AI-adapted recipes also now show up in recipe history (Forked from…) like forks always have.

## 0.38.0 — 2026-07-17 13:00

### Added
- The cooking assistant and per-recipe chat can now expand to fullscreen — a new toggle in the chat header.

## 0.37.0 — 2026-07-17 12:30

### Fixed
- Generating a recipe from a photo now uses two separate AI steps — a vision model recognizes what's in the picture, then a text model writes the recipe from that — instead of one model doing both, so each step can use the model actually suited to it.

## 0.36.0 — 2026-07-17 12:00

### Added
- Explore and the Activity Feed are now one page — Explore has Discover/Following/For You tabs, so browsing and following recipes no longer live in two separate places.
- Explore's recipe cards (search results, trending, recently added, following, for you) now use the same cover-photo card as the Recipes page, instead of the old text-only search card.

## 0.35.0 — 2026-07-14 18:20

### Added
- Recipe editor now lets you enter nutrition values by hand (calories, protein, carbs, fat, fiber, sodium per serving) instead of relying only on the AI estimate — the nutrition panel shows a "Manually entered" badge and swaps to "Estimate with AI instead" when manual data is present.

## 0.34.0 — 2026-07-14 18:05

### Added
- Admin overview now shows growth (new users/recipes this week), engagement (recipes cooked this week), a moderation queue count, storage used, and platform-integration counts (webhooks, API keys) — not just totals.

### Fixed
- The admin Signups toggle was inverted — switching it "on" used to disable signups. It now reads naturally: on means open.
- AI provider keys and default-model settings have moved from Site Settings to AI Config, alongside the rest of the AI setup.

## 0.33.1 — 2026-07-14 17:45

### Fixed
- URL-imported recipes never recorded what language they were actually written in, so the Translate button couldn't tell whether translation was needed — the importer now detects the source page's language, and photo import records the language it always writes in.

## 0.33.0 — 2026-07-14 17:35

### Added
- **AI recipe generation/import now auto-detects drinks vs dishes** — generate, generate-from-idea, URL import, and photo import all classify the result and skip cook time for drinks, defaulting to dish whenever it's ambiguous.
- **Drink recipes get their own default icon** (🍹 instead of 🍽️) wherever a recipe has no cover photo.
- **Explore now has a Type filter** (dish/drink), alongside My Recipes' existing one.

## 0.32.0 — 2026-07-14 17:10

### Security
- Fixed a stored-XSS hole in public recipe pages' embedded structured data, and tightened the production Content-Security-Policy so script injection like it can't execute even if a similar bug slips in again.
- Avatar photos now require proof you actually own the upload — previously any URL was accepted, including another user's uploaded photo key.
- Changing your password now signs out every other active session, and so does resetting a forgotten password.
- Fixed a rate-limit bypass on public share-link throttling caused by trusting a spoofable header.
- Webhook signing secrets are now encrypted at rest, matching how API keys and other secrets are already stored.
- Login/2FA/password-reset rate limiting now shares Redis instead of quietly resetting per server instance.
- Photo/avatar uploads are now size-capped by the storage server itself, not just a number the client could lie about.
- A private recipe's title could leak via its page's browser-tab title to any signed-in user who had the link — fixed to respect the same visibility rules as the page itself.
- Blocking/unblocking a user is now rate-limited, matching follow/unfollow.
- AI calls made with your own API key (Settings → AI Keys) no longer count against your monthly AI-call limit.

## 0.31.0 — 2026-07-14 16:35

### Added
- **Recipes can now be marked as a Drink/cocktail** instead of a dish — the recipe form hides irrelevant food-only fields (prep/cook time, difficulty, batch cooking) for drinks, and you can filter your recipe list by type. Drink recipes also no longer show the food/drink pairing suggestion buttons on their own page.

## 0.30.1 — 2026-07-14 16:20

Internal: fixed test mocks left stale by the earlier API-key auth-widening pass (recipes/meal-plans/shopping-lists route tests) — no user-facing change.

## 0.30.0 — 2026-07-14 16:05

### Added
- **Admins can now set the site-wide default AI provider/model** per use case (text generation, photo/vision, meal-plan generation) from Settings → Admin, applied whenever a user hasn't picked their own model preference or brought their own API key.

## 0.29.0 — 2026-07-14 15:20

### Added
- **Photo recipe import now respects your app language** — previously it defaulted to English (or whatever language was in the photo) instead of matching your locale like other AI generation features.

### Fixed
- Importing a photo with no recognizable recipe used to open the recipe editor anyway with empty/garbage fields — it now shows a clear error instead.

## 0.28.3 — 2026-07-14 14:55

### Fixed
- Copying an unlisted recipe's share link wrongly warned "this link won't work until the recipe is Public" — unlisted links work fine (that's the point of unlisted); the warning now only shows for actually-private recipes.

## 0.28.2 — 2026-07-14 14:45

### Fixed
- Recipe cards on Explore and Search cramped the title next to the difficulty badge, cutting titles off early — the title now gets its own full-width line, and the grid gains a medium-viewport column step matching the Recipes page.

## 0.28.1 — 2026-07-14 14:25

### Fixed
- Cooking mode's keyboard/voice shortcuts panel could overflow and overlap the surrounding screen in French (longer translated labels) — now scrolls internally and wraps instead of overflowing.

## 0.28.0 — 2026-07-14 14:05

### Added
- **Meal plan and shopping list header buttons now match the recipe page's icon+tooltip style** — Share, Generate shopping list, Shopping lists, Print, Export to calendar, Send to grocery delivery all collapsed to icon-only with a tooltip, instead of crowding the header with text labels.
- **Week-switch arrows on the meal plan now sit right next to the week date**, instead of at the far end of the button row.

## 0.27.2 — 2026-07-14 13:20

### Fixed
- Dietary tag chips, the recipe tag-adding form, the "Edit recipe" title, and the meal-plan nutrition-goals bar were all hardcoded in English regardless of app language — now translated.

## 0.27.1 — 2026-07-14 12:05

### Fixed
- API Reference (`/docs`) schemas corrected against the actual code across the whole API — recipes (batch-cook fields, tags, photos were undocumented), comments, ratings, meal plans, shopping lists, pantry, feed, and several missing error responses. A webhook-redelivery route also returned a malformed error body — now matches the rest of the API's `{ error: string }` convention.

## 0.27.0 — 2026-07-14 11:15

### Added
- **API keys now work on recipes, collections, meal plans, shopping lists, pantry, feed, and AI generation** — previously most of the API only accepted a session cookie, so keys couldn't actually be used for most endpoints. Account/credential-adjacent routes (profile, AI provider keys, webhooks, notifications, messages, admin) intentionally stay session-only.

## 0.26.0 — 2026-07-14 10:20

### Added
- **API Reference (`/docs`) now covers the full API**: went from 14 documented endpoints to all ~100 — pantry, meal plans, shopping lists, collections, users/social, AI generation, webhooks, conversations, notifications, and admin routes are now all documented with request/response schemas.

## 0.25.1 — 2026-07-14 09:40

### Fixed
- API key "Last used" only showed a date — now shows date and time.

## 0.25.0 — 2026-07-14 09:36

### Added
- **Gravatar is now opt-in, off by default** — previously every account without a custom photo automatically had its email hashed and sent to gravatar.com. Turn it on in Settings → Profile if you want it.

## 0.24.1 — 2026-07-14 09:24

### Fixed
- My Recipes search result count showed a literal "{count}" instead of the number, in every locale.

## 0.24.0 — 2026-07-14 08:08

### Added
- **My Recipes search now matches ingredients and tags too**, not just title/description — same improvement shipped for Explore/Search earlier.
- **QR code on printed recipes**: a public or unlisted recipe's printout now includes a scannable code linking back to the online version.

## 0.23.0 — 2026-07-13 23:06

### Added
- **Two-factor authentication**: turn it on in Settings → Security to require a code from an authenticator app when signing in, with backup codes in case you lose access to it.

## 0.22.0 — 2026-07-13 22:49

### Added
- **QR code on printed shopping lists**: a public list's printout now includes a scannable code linking back to the live version — pairs with public-editable links, so someone at the store can scan and check items off in real time.

## 0.21.0 — 2026-07-13 22:34

### Added
- **Rating stars on recipe cards** — average rating and review count now show on Search and Explore results, not just the recipe detail page.

## 0.20.0 — 2026-07-13 22:26

### Added
- **Duplicate your own recipe** — same one-click copy used for forking others' recipes, now also on your own, for making variations without touching version history.

## 0.19.0 — 2026-07-13 22:21

### Added
- **Export your meal plan to a calendar file** — download a week's meals as a .ics file to import into Google/Apple/Outlook calendar.

## 0.18.0 — 2026-07-13 22:16

### Added
- **Live updates on shared meal plans**: entries added, removed, or cleared by a collaborator now appear automatically, both on the owner's own week view and everyone else's shared view.

## 0.17.0 — 2026-07-13 22:06

### Added
- **Clear a day or the whole meal-plan week** in one click instead of removing each meal individually.

## 0.16.0 — 2026-07-13 21:59

### Added
- **@mention autocomplete in comments**: type "@" and a name to search and insert a mention, instead of typing the exact username blind.

## 0.15.0 — 2026-07-13 21:54

### Added
- **Search now matches ingredients and tags**, not just title/description — "zaatar" now finds a recipe that uses it even if the title doesn't mention it.
- **Tag filter chips on Explore**: click a popular tag to narrow results instead of typing it.

## 0.14.0 — 2026-07-13 21:47

### Added
- **Change your username** in Settings — previously auto-assigned at signup with no way to change it.

## 0.13.1 — 2026-07-13 17:25

### Fixed
- People search never found anyone, for anyone — there was no signup or settings flow that ever set a username, and search (along with profiles and follow) requires one. Every account now gets one automatically on signup; existing accounts were backfilled.

## 0.13.0 — 2026-07-13 15:37

### Added
- **Explore search now finds people and recipes together**: one search bar, one query — no more separate, hard-to-find people tab.

## 0.12.1 — 2026-07-13 13:25

### Fixed
- Changelog entries showed literal `**bold**` markup instead of rendering it.

## 0.12.0 — 2026-07-13 12:52

### Added
- **Public shopping list links can now allow editing**: turn on "Allow editing" alongside the public link so anyone who has it can check off, add, and reorder items — no account needed. Off by default, and turning off the public link revokes editing too.

## 0.11.0 — 2026-07-13 12:27

### Added
- **Live updates on shared shopping lists**: items checked, added, recategorized, or reordered by a collaborator now appear automatically, without a manual refresh.

## 0.10.0 — 2026-07-13 11:55

### Added
- **Bulk tag editing**: add or remove tags across several selected recipes at once.
- **Bulk export**: export several selected recipes to a single Markdown file.
- **Move recipes between collections**: select recipes inside a collection to move them to another collection or remove them from this one.

## 0.9.6 — 2026-07-13 09:31

### Added
- **Rate limiting on public routes**: sign-in/sign-up now throttle after 3 attempts per 10s per IP; public recipe/shopping-list share links (`/r/`, `/s/`) throttle after 60 requests/min per IP.

## 0.9.5 — 2026-07-13 09:20

### Fixed
- Explore page's "Recipe ideas" input got squeezed to a couple of visible characters on mobile — buttons now stay icon-only below `sm:`.
- The per-recipe chat button could overlap the private-notes save button on short recipe pages.

## 0.9.4 — 2026-07-13 09:03

### Fixed
- "New recipe" wrapped to its own line on mobile (especially French) instead of sharing a row with Generate/Import — icon-only below that breakpoint now.
- The view-toggle/Select row floated flush right with a large dead gap on the left — now left-aligned outside select mode.

## 0.9.3 — 2026-07-13 08:38

### Fixed
- Recipes page wasted a lot of vertical space above the recipe list on mobile — Sort/Filter now sit alongside Search on one row instead of forcing an extra one.

## 0.9.2 — 2026-07-13 07:14

### Fixed
- Explore page's "Recipe ideas" banner buttons clashed with its violet gradient background — restyled to match.

## 0.9.1 — 2026-07-13 06:59

### Fixed
- Destructive confirm buttons (clear chat history, discard recipe changes) had unreadable black text on a red background — a missing CSS variable.

## 0.9.0 — 2026-07-12 23:28

### Added
- **Clear chat history**: a trash-icon button in both chatbots clears that conversation's saved history.
- Chat history now auto-expires after 90 days (daily cleanup job).

## 0.8.0 — 2026-07-12 22:38

### Added
- **Read-only API key scoping**: create keys that can only read (GET), not create/edit/delete anything.
- **AI chat history**: both chatbots now remember past conversations across sessions, and let you search across everything you've ever asked.

## 0.7.1 — 2026-07-12 21:36

### Fixed
- Cooking-assistant button on the homepage sat too high.
- The chatbots would answer honestly if asked what AI model they run on — now always identify as Epicure.

## 0.7.0 — 2026-07-12 19:36

### Added
- **General cooking-question chatbot** on the recipes homepage — ask technique/substitution/timing questions not tied to a specific recipe.

### Fixed
- API keys always showed "never used" — middleware was blocking every Bearer-key request before it ever reached the code that verifies the key and records usage.
- The webhooks documentation page had no way back to webhooks settings.

## 0.6.0 — 2026-07-12 19:09

### Added
- **Granular push-notification settings**: turn individual categories on/off (follows, comments, replies, reactions, ratings, mentions, leftover reminders, shared shopping list updates) instead of all-or-nothing.

### Fixed
- The push-notification toggle in Settings always showed as off, even when notifications were genuinely still enabled — it never checked the actual browser subscription state.
- The API Reference page (`/docs`) was blank — Content-Security-Policy blocked the script it needs to render.

## 0.5.1 — 2026-07-12 19:05

### Security
- Recipe/review photo uploads: a stolen storage key from another user's public recipe or review could be submitted as your own, causing that user's photo to be deleted from storage when the recipe was later edited or deleted. Both routes now check the key was actually issued to you for that recipe.
- AI URL-import could be redirected to internal/private network addresses via a crafted 3xx response, and was separately vulnerable to DNS-rebinding between validation and fetch. Both the import and outgoing webhook delivery now resolve the host once and pin the connection to that address, re-validating on every redirect hop.
- Comment moderation and monthly AI/recipe/storage quota checks trusted a session field that can lag up to 5 minutes behind a role or tier change — both now re-check the current value in the database.

## 0.5.0 — 2026-07-12 18:37

### Added
- **Push notifications for shared shopping lists** — get pinged when someone else checks off or adds items.

### Fixed
- Batch-cook dishes never deducted pantry when marked cooked — now deducts once, on the first dish cooked per batch session.
- Weekly meal-plan nutrition coverage compared a week's total intake against a daily goal (reading ~7x too high) — now compares a proper daily average, with a per-day breakdown and a flag for meals missing nutrition data.
- Meal-plan week navigation could resolve the wrong Monday depending on server timezone.

## 0.4.0 — 2026-07-12 16:13

### Added
- **Profile pictures**: upload a custom photo, or get a Gravatar-backed avatar automatically — no more generic initials by default.
- **"Imported from" badge** on recipe cards for recipes brought in from a URL.
- **Share shopping lists via a public link** — anyone with the link can view, no account required, alongside the existing private collaborator invites.

### Fixed
- Batch-cook recipes shifted left in compact view when they had no time set or a longer dish/time label.

## 0.3.1 — 2026-07-12 15:08

### Added
- A free-text "describe what you're after" field for batch-cooking generation, matching the standard recipe generator.

### Fixed
- AI recipe generation used a separate language picker instead of following the app's own language — removed, generation now always matches your app language.
- The bulk-select action bar on the recipe list could show a horizontal scrollbar on desktop even though there was room to grow.
- Recipes imported from a URL never actually saved their source URL — the "Source: ..." link on the recipe page was dead code until now.

## 0.3.0 — 2026-07-12 14:46

### Added
- **Manually create and edit batch-cook recipes**: the recipe form now has a batch-cook toggle, an editable dish list (storage/reheat guidance per dish), and per-step dish tagging — not just AI-generated ones anymore. Editing an existing batch-cook recipe no longer silently strips its dish data.

## 0.2.2 — 2026-07-12 13:54

### Fixed
- Recipe photo thumbnails always tried to load from `localhost:9000` in production, tripping CSP/mixed-content blocks in every browser — the public storage URL wasn't reaching client-side code.

## 0.2.1 — 2026-07-12 13:21

### Fixed
- Recipe photos were lost after saving, and multi-file uploads only kept the last file selected.
- Photo thumbnails failed to load (blocked by Next.js's image optimizer refusing local-storage hosts).

## 0.2.0 — 2026-07-12

### Added
- **Batch cooking**: generate a single "mega recipe" covering several meals at once — merged shopping list, steps tagged per dish (including steps that advance several dishes at once), and per-dish storage/reheat guidance. Available from the recipe list's Generate dialog and from the meal planner.
- **Leftover expiry reminders**: mark a batch-cook dish as cooked, track its fridge life, see it surfaced on the Pantry page, and get a daily reminder before it goes bad.
- **"Cooked it" photo reviews**: attach a photo and written review when rating a recipe.
- **Pantry-expiry recipe suggestions**: the Pantry page now surfaces recipes that use up ingredients about to expire.
- **Trending collections**: star public collections; browse trending and recently-added ones under Collections → Discover.
- **Add to collection from the recipe list**: select recipes and add them to a new or existing collection without leaving the page.
- List and compact view modes for the recipe list, alongside the existing grid view.

### Fixed
- Recipe version-comparison diff was unreadable and partially untranslated.
- Print/export pages always render light, regardless of the app's dark/light setting.
- Presigned photo-upload URLs were signed against an internal-only address in production, breaking uploads.
- Several recipe-list and recipe-form UI issues: filter menu closing on every click, tag filter not accepting keystrokes, inconsistent card badge styling, missing tooltips, a floating save button on long recipe forms.

## 0.1.0 — earlier

Initial feature set: recipes (create, edit, AI-generate, import from URL/photo), meal planning, shopping lists, pantry tracking, collections, social features (follow, comment, rate, notifications), nutrition tracking, admin dashboard, and account/billing basics.
