A cooking recipe manager.
  • Python 49.2%
  • Vue 40.1%
  • JavaScript 8.7%
  • SCSS 0.9%
  • Dockerfile 0.8%
  • Other 0.3%
Find a file
Repository files (latest commit first)
Filename Latest commit message Latest commit date
Till Wesselmann 3860b8c8ca One image, built from the top of the repository
The frontend is built into the application's image, which runs gunicorn
on port 8000 as an unprivileged user. The nginx image, the compose file,
the update script and the GitLab CI configuration described a deployment
that pulled images from a registry which no longer exists.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
2026-11-12 22:20:32 +01:00
claypot Log in through an OpenID Connect provider 2026-11-12 22:20:32 +01:00
config Log in through an OpenID Connect provider 2026-11-12 22:20:32 +01:00
frontend Log in through an OpenID Connect provider 2026-11-12 22:20:32 +01:00
requirements Log in through an OpenID Connect provider 2026-11-12 22:20:32 +01:00
tests Log in through an OpenID Connect provider 2026-11-12 22:20:32 +01:00
.dockerignore One image, built from the top of the repository 2026-11-12 22:20:32 +01:00
.editorconfig Added vue and cohorts to .editorconfig 2019-01-24 20:55:45 +01:00
.env Fix connection string, quotes and method naming 2019-05-29 14:12:57 +02:00
.gitignore Using Django templates to build individual pages for requests 2020-11-22 17:03:21 +01:00
.pre-commit-config.yaml Add configuration for pre-commit 2019-05-25 08:18:43 +02:00
CHANGELOG Bump changelog 2019-05-29 19:03:51 +02:00
Dockerfile One image, built from the top of the repository 2026-11-12 22:20:32 +01:00
LICENSE Add LICENSE file 2019-02-17 17:17:26 +00:00
manage.py Run Black on codebase 2019-05-25 08:17:46 +02:00
pyproject.toml Add configuration for Black 2019-05-25 08:14:21 +02:00
README.md One image, built from the top of the repository 2026-11-12 22:20:32 +01:00
tox.ini Remove pytest-black from testing 2019-12-29 23:12:33 +01:00

claypot

A simple cooking recipe manager.

Sample database

Use this command to load some sample data to your database.

$ ./manage.py loaddata ingredients_de.yaml units_de.yaml units_de_de.yaml test_recipes_de.yaml

Running tests

$ pytest --cov=claypot

Frontend

The frontend lives in frontend/ (Vue 2, built with Vite; node 24 or newer). It is not a site of its own: the build writes index.html, which Django renders as a template, and the bundles under js/ and css/ to claypot/templates/claypot/.

$ cd frontend
$ npm ci
$ npm run serve      # development build, rebuilds on every change
$ npm run build      # production build
$ npm run test:unit
$ npm run lint

With DJANGO_DEBUG=true Django serves /js/ and /css/ itself. In production the web server in front of it has to.

Logging in

claypot keeps no passwords. People log in at an OpenID Connect provider, which is configured through the environment:

Variable
OIDC_RP_CLIENT_ID, OIDC_RP_CLIENT_SECRET the client registered at the provider
OIDC_OP_AUTHORIZATION_ENDPOINT, OIDC_OP_TOKEN_ENDPOINT, OIDC_OP_USER_ENDPOINT, OIDC_OP_JWKS_ENDPOINT the provider's endpoints, as its discovery document names them
OIDC_RP_SIGN_ALGO how the provider signs ID tokens, default ES256
OIDC_RP_SCOPES default openid profile email

The redirect URL to register is https://<host>/oidc/callback/. The flow uses PKCE.

An account is linked to the provider's subject identifier at the first login. An account that existed before is found by its email address; anybody else gets a new one. Staff and superuser rights are given in the admin.

Without OIDC_RP_CLIENT_ID (development) there is no login in the frontend: create an account with ./manage.py createsuperuser, log in at /admin/ and open /accounts/login?done=1.

Deployment

The Dockerfile builds one image with the frontend inside. It runs gunicorn on port 8000 as an unprivileged user (uid 1000); the worker is the same image with python manage.py rqworker default.

Variable
DJANGO_SECRET_KEY required
DATABASE_URL required, PostgreSQL (postgresql://user:password@host/name)
DJANGO_ALLOWED_HOSTS the host name(s) the site is served under
REDIS_HOST the Redis instance of the job queue
MEDIA_ROOT thumbnails and resized images, to be served as /media/
IMAGE_ROOT the uploaded originals, not served
LANGUAGE_CODE, TIME_ZONE default en-us, UTC

Before the first start and after every update:

$ python manage.py migrate
$ python manage.py collectstatic    # the admin's files, into /code/static

The web server in front serves /js/ and /css/ from /code/claypot/templates/claypot/ in the image, /static/ from what collectstatic wrote and /media/ from MEDIA_ROOT, passes everything else on, and sets X-Forwarded-Proto.