Tom FluxandClaude Opus 4.8 77b42a8758 nginx: 404 the .well-known/ OAuth probes for the MCP connector
claude.ai's custom-connector flow probes /.well-known/oauth-* during
setup. The catch-all 301 -> /app/ made those return the Kitchen login
page (200), so claude.ai mistook it for an OAuth sign-in service, tried
Dynamic Client Registration, and failed. Returning 404 makes it treat
the server as authless and connect.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-23 21:41:41 +01:00
2026-06-23 19:55:42 +01:00
2026-06-23 21:27:35 +01:00

Food — Meal Planning System

A custom Django app for pantry tracking, meta-recipes, and meal planning. Built for Tom, operated primarily through Caine (OpenClaw AI assistant) via Matrix chat, with Django admin as the web UI.

Architecture

  • Django 5.2 (latest LTS) with SQLite backend
  • Django REST Framework for API with token auth
  • HTMX frontend planned (Phase 4)
  • App name: kitchen

Core Concept: Meta-Recipes

Instead of rigid recipes, the system uses templates with swappable slots:

"Stir Fry" = protein (chicken OR pork) + carb (noodles OR rice) + veg (any combo) + sauce

This matches how Tom actually cooks — same method, different ingredients depending on what's in the pantry.

Models

Model Purpose
Tag Flexible ingredient tags (protein, carb, veg, etc.)
Ingredient Master ingredient list with aliases and shelf life
PantryItem Current kitchen inventory with location and expiry
MetaRecipe Cooking template with swappable slots
Slot A category in a meta-recipe (protein, carb, veg)
SlotOption An ingredient that can fill a slot, with qty/serving
MetaRecipeBase Always-needed ingredients (onion, garlic, oil)
Recipe Traditional fixed-ingredient recipe
RecipeIngredient Ingredient in a fixed recipe
CookLog What was cooked and when
ShoppingListItem Shopping list with reasons and checkboxes

Setup

cd /var/lib/food
source venv/bin/activate

# Run migrations
python manage.py migrate

# Seed initial data (ingredients, pantry, meta-recipes)
python manage.py seed

# Create superuser (if not already done)
python manage.py createsuperuser

# Run dev server
python manage.py runserver 0.0.0.0:8042

Access

  • Admin UI: http://localhost:8042/admin/
  • Browsable API: http://localhost:8042/api/
  • cgit: https://git.jihakuz.xyz/food/

API

All endpoints require auth. Token auth for Caine, session auth for browser.

Key Endpoints

Method Endpoint Purpose
GET /api/what-can-i-cook/?servings=2 Match pantry vs recipes
POST /api/log-cook/ Log a cooked meal, optionally deduct from pantry
GET /api/pantry/ List all pantry items
GET /api/pantry/expiring/ Items expiring within 3 days
GET /api/pantry/restock/ Staples needing restocking
CRUD /api/ingredients/ Ingredient master list
CRUD /api/meta-recipes/ Meta-recipes with nested slots
CRUD /api/recipes/ Fixed recipes
CRUD /api/shopping-list/ Shopping list
CRUD /api/cook-log/ Cooking history

Auth

  • Token: Authorization: Token <token> header
  • Session: Log in via admin or /api-auth/login/
  • API users: tom (admin), caine (API-only)

File Structure

/var/lib/food/
├── food_project/          # Django project config
│   ├── settings.py
│   ├── urls.py
│   └── wsgi.py
├── kitchen/               # Main app
│   ├── models.py          # All 11 models
│   ├── admin.py           # Admin config with inlines
│   ├── serializers.py     # DRF serializers
│   ├── views.py           # ViewSets + what-can-i-cook + log-cook
│   ├── urls.py            # API router
│   ├── management/
│   │   └── commands/
│   │       └── seed.py    # Initial data seeder
│   └── migrations/
├── venv/                  # Python virtual environment (gitignored)
├── db.sqlite3             # SQLite database (gitignored)
├── manage.py
├── requirements.txt
└── README.md

Pantry Business Rules

  • Freezer items → no expiry date (frozen = indefinite)
  • Fridge items → expiry date set from ingredient's shelf_life_days if available
  • Staples (onions, frozen chips, salt, etc.) → auto-flag for restocking when quantity = 0
  • Onions are a permanent staple — always restock
  • Chicken skin → remove before cooking (noted in slot option notes)
  • Tom prefers pork to chicken — pork mince over loins
  • Cooked chicken — 3 day max fridge life
  • Defrosted sausages — 2-3 days max

Implementation Phases

  • Phase 1: Django project + models + admin + seed data
  • Phase 2: DRF API + token auth + "what can I cook?" + log-cook with pantry deduction
  • Phase 3: Recipe import (URL scraping + cookbook extraction)
  • Phase 4: HTMX frontend (pantry view, recipe browser, shopping list)
  • Phase 5: Systemd service + nginx reverse proxy + production hardening

Caine Integration

OpenClaw skill file at ~/.openclaw/workspace/skills/food/SKILL.md teaches Caine the API each session. Natural language interface via Matrix:

  • "What can I cook?" → calls /api/what-can-i-cook/
  • "Add 6 eggs to the fridge" → POST to /api/pantry/
  • "Made stir fry with pork and noodles" → POST to /api/log-cook/ with deduction
  • [Photo of shopping] → identify items, bulk add to pantry

Design Doc

Full design document: Obsidian Vault/Tom Net/Meal Planning System.md

S
Description
Django + DRF meal-planning system: pantry tracking, meta-recipes and slot-based meal generation.
Readme
277 KiB
Languages
Python 76%
HTML 24%