Commit Graph
10 Commits
Author SHA1 Message Date
Kyle DammannandClaude Opus 5.5 23adb882bd Add tabs for all, own and favourite recipes
- Tabs "Alle", "Eigene Rezepte", "Favoriten" above the recipe list;
  search and tag filters stay within the active tab
- Menu link to own recipes; empty states per tab
- Fix recipe card images rendering portrait instead of 4:3

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-31 01:45:29 +01:00
Kyle DammannandClaude Opus 5.5 c76fd119cf Make new recipes public by default
New recipes (manual, AI draft and all imports) now start as public;
private can still be chosen per recipe. Existing recipes are unchanged.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 23:05:05 +01:00
Kyle DammannandClaude Opus 5.5 015a0a5821 Fix AI calls failing in Docker with empty OPENAI_BASE_URL
docker compose passes an empty .env line as OPENAI_BASE_URL="", and with
base_url=None the openai SDK fell back to that empty value, so every
call failed with "Connection error". Always pass the base URL
explicitly. Also disable gunicorn's unused control socket, which
logged a permission error because /app is read-only for the app user.

Found while deploying to the homelab server.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 22:37:39 +01:00
Kyle DammannandClaude Opus 5.5 dfa4813a42 Refine AI prompt for countable ingredients and units
Real calls produced "2 Stück Eier" and "1 Zehen Knoblauchzehe". The
prompt now asks for no unit on countable items and no unit repeated in
the name; verified with a real gpt-5-mini call.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 22:19:25 +01:00
Kyle DammannandClaude Opus 5.5 2f73520150 Detect OpenAI "no credits" 429 as exhausted balance
A real API call returned 429 "You have no credits remaining" without the
word "quota", so the UI wrongly said the AI was busy. Match quota,
credit and billing wording; test uses the real message.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 22:15:33 +01:00
Kyle DammannandClaude Opus 5.5 3b72436119 Add OPENAI_BASE_URL and end-to-end AI tests through the SDK
- Optional OPENAI_BASE_URL for OpenAI-compatible endpoints or proxies
- Tests run the real openai SDK against a local stub server: request
  shape (model, auth, strict json_schema), text cleanup, photo import
  and an authentication error mapped to the UI message

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 22:06:35 +01:00
Kyle DammannandClaude Opus 5.5 60785e2437 Add phase 5: link import, Instagram fallback and share target
- SSRF-safe fetcher: public IPs only, connects to the checked address,
  redirects re-validated, size/time limits, honest user agent
- schema.org/Recipe JSON-LD extraction (graphs, HowToSections, ISO
  durations, yields, keywords, images) without extra dependencies;
  AI fallback on plain page text when no structured recipe exists
- Instagram: one login-free request to the public embed page; when
  Instagram withholds the caption, the import page explains how to paste
  the text or import a screenshot instead
- Suggested source photo can be downloaded and attached on save
- Text import works without AI (text becomes the description)
- Installable PWA with manifest, icons and Android share target
- Offline tests for SSRF rules, parsers, Instagram and import views

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 21:53:28 +01:00
Kyle DammannandClaude Opus 5.5 1bf8ef8b65 Add phase 4: AI cleanup and photo/text import via OpenAI
- recipes/ai.py: Chat Completions with strict JSON schema (Structured
  Outputs), Pydantic re-validation, plausibility clamping, prompt treats
  input as data only
- "Mit KI aufbereiten" on create/edit form returns an editable draft
- Import page: photo/screenshot (vision, downscaled JPEG, not stored) and
  pasted text; drafts pre-fill the recipe form with a preview
- Clear UI messages for timeout, rate limit, quota, auth, model and
  connection errors; without OPENAI_API_KEY AI features show a notice
- Optional per-user and global daily AI limits (default unlimited)
- Tests for response parsing, schema strictness, error mapping, views

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 21:43:30 +01:00
Kyle DammannandClaude Opus 5.5 9256e94286 Add phase 3: comments and cooking mode
- Comments on visible recipes; author and admin may delete; per-user
  hourly rate limit (COMMENT_RATE_LIMIT_PER_HOUR)
- Cooking mode with large text, tick-off checklists, serving scaling and
  Screen Wake Lock to keep the display on
- Serving calculator auto-submits on change
- Privacy tests cover comment and cooking-mode URLs

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 21:39:15 +01:00
Kyle DammannandClaude Opus 5.5 6f7e4f92ca Add phase 2: recipes with visibility, photos, search and favourites
- Recipe model with ingredients (amount/range, unit, group, note), steps,
  lowercase tags, author notes, source URL and private/public visibility
- Central RecipeQuerySet.visible_to() used by every read path; edit only
  by owner, delete by owner or admin (visible recipes only)
- Text-based editing: ingredient/step parser with roundtrip and scaling
- Photo upload (JPEG/PNG/WebP/HEIC), re-encoded to WebP without EXIF,
  thumbnails, cover image, served only through permission-checked view
- Search across title, description, ingredients, tags; ingredient and tag
  filters; "mine" and favourites views
- Admin can delete all recipes of a deactivated user
- Acceptance tests: private recipes unreachable for others and admins
  in list, search, tags, favourites, detail, edit, delete and image URLs

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-30 21:37:13 +01:00