cooking.ito.com (joi.github.io)

Joi’s recipe site: Paprika 3 database → Python generator → Jekyll →
GitHub Pages. See README.md for the full architecture.

Ground rules

  • _recipes/, _tags/, _data/*.json (except navigation.yaml), and
    images/recipes/ are GENERATED by python -m cooking build. Never
    hand-edit them; edit the recipe in Paprika and rebuild.
  • Hand-written content: _notes/ (meal notes), _pages/, _posts/,
    _webpages/, layouts/includes/css.
  • The Paprika database is the source of truth for recipes. The generator
    never writes to it; keep it that way.
  • Timestamps in Paprika are Core Data (seconds since 2001-01-01 UTC).
    Convert by ADDING config.TS_OFFSET; never with SQLite’s
    '+31 year' calendar arithmetic, and never with 'localtime'. Both
    look right and are subtly wrong — see docs/paprika-gotchas.md.
  • Generated bytes define published URLs and markup, so review a build’s
    git diff before committing. The build is deterministic; the
    COOKING_PARITY=1 pytest -m parity test asserts two runs agree, but
    it is NOT a comparison against the retired monolith (that was a
    one-time check — the output has since changed on purpose). The unit
    tests (pytest) are the guard for the generator’s behavior.
  • Pushing master deploys the site (GitHub Pages). Build + commit
    locally, but confirm with Joi before pushing.

Commands (run from __scripts/)

./venv/bin/python -m cooking status    # DB vs repo sync report
./venv/bin/python -m cooking photos    # backfill photos Paprika hasn't fetched
./venv/bin/python -m cooking build     # regenerate site sources
./venv/bin/python -m cooking dupes     # duplicate recipes in DB
./venv/bin/python -m cooking search "<term>"
./venv/bin/python -m cooking show <name-or-slug>
./paprika-env ./venv/bin/python -m cooking add-recipe --url <url> --category <Cat> [--append FILE] [--dry-run]
./paprika-env ./venv/bin/python -m cooking derive <slug> --name <twin> --directions FILE   # _mine twin
./venv/bin/python -m cooking new-note YYYY-MM-DD <meal> [--feature ..] [--tag ..] [--recipe <slug>]
./venv/bin/python -m pytest            # unit tests

photos and add-recipe read PAPRIKA_EMAIL / PAPRIKA_PASSWORD from the environment
(they live in Kura: amplifier-secrets.env.age). photos hits Paprika’s v1
sync API read-only and writes missing files into Paprika’s photo store;
add-recipe is the one write path (new uid only, never edits). The v2
login endpoint rejects non-app clients; stay on v1 basic auth.

Setup on a fresh machine: python3 -m venv venv && ./venv/bin/pip install -r requirements.txt inside __scripts/.

Known state (2026-08-21)

  • Paprika account: [email protected] (survivor of a two-account sync
    mess). The 10 duplicate pairs from that merge were resolved on
    2026-08-21 (6 trashed, 4 renamed by source); the account now has 486
    active recipes and cooking dupes should report none.
  • A fresh Paprika install downloads full-size photos lazily. cooking status reports how many are still missing and cooking build now
    refuses to publish while any are missing from both Paprika and the
    already-published site (override: build --allow-missing-photos).
    Run cooking photos to backfill. To discard a bad build’s output,
    both restore tracked files and drop new untracked ones:
    git checkout -- _recipes _tags _data images && git clean -fd _recipes _tags images/recipes.
  • Recipe created timestamps and internal ids shifted in the account
    migration; that churn is already committed.