A tool to facilitate personal Bible Study
Milk2Meat is a personal Bible study tool inspired by Hebrews 5:13-14 and 1 Corinthians 3:1-2, representing the journey from spiritual milk (basics) to meat (deeper understanding). I wrote it with a view to engage more deeply with the Scriptures through structured note-taking, book introductions, and organized Bible study.
The name reflects the spiritual growth process:
"For everyone who lives on milk is unskilled in the word of righteousness, since he is a child. But solid food is for the mature, for those who have their powers of discernment trained by constant practice to distinguish good from evil." - Hebrews 5:13-14
- Book Introductions: Add detailed introductions to each book of the Bible (inspired by The Reformation Study Bible and The ESV Global Study Bible)
- Note Taking: Create and organize study notes, sermon notes, and devotionals
- File Attachments: Upload handwritten notes or other files (PDFs, images)
- References: Link notes to specific Bible books
- Tags: Organize notes with custom tagging
- Markdown Support: Rich text editing with Markdown (powered by EasyMDE)
- Search: Full-text search across all your content
- Private: All notes and attached files are private to your user account
- Dark Mode: Support for light and dark themes
This project requires
- Postgres 15 (this is provided via Docker & Docker Compose – see note below.)
- Node.js 22 on your system
- A Python 3.13 virtual environment
libmagicon your system (homebrew | debian | ubuntu | fedora)
Note
When I started this project via django-admin startproject milk2meat ., I wanted to get up and running quickly, so I didn't bother to do a proper Docker Compose development setup. However, I don't like using a system-wide Postgres installation, so I set up Postgres using Docker & Docker Compose.
The development docker compose config file is located in docker/docker-compose.dev.yml and only contains a db service for Postgres.
For production, there's a separate docker-compose.yml in the root directory that contains the complete stack.
Steps:
- install dependencies
poetry install --with dev,docs,test --no-root
npm ci- configure environment variables
cp -v .dev.env.example .dev.env- fire up the postgres container
inv up --build # First time
inv up # Subsequent runsNote
You don't need TURNSTILE_SITE_KEY and TURNSTILE_SECRET_KEY during development.
- apply database migrations
./manage.py migrate- create a superuser
./manage.py createsuperuser- add Bible Books data
./manage.py populate_bible_books- add some fake notes for testing
./manage.py create_demo_notes- run the dev server (runs Django dev server and webpack simultaneously, courtesy of honcho).
inv startYou should be able to access the site at http://127.0.0.1:8000
Important
This application is configured to use Cloudflare R2 for media storage, and Cloudflare Turnstile, a verification tool to replace CAPTCHAs. You'll need to set those up and provide the necessary environment variables.
The docker-compose.yml is configured to work with Traefik, based on the following requirements:
- A server with Docker and Docker Compose installed
- Traefik already set up and configured like this
- Domain name pointing to your server
-
Copy the example environment file to
.envand edit the latter with your production settings:cp .env.example .env
-
Spin up the containers and start the application:
docker compose up -d --build
-
Create a superuser:
docker compose exec milk2meat python manage.py createsuperuser -
Populate Bible books data:
docker compose exec milk2meat python manage.py populate_bible_books
That's it! The application should be running at your configured domain with Traefik handling SSL certificates.
You'd have to remove the following lines from the Dockerfile:
# Make entrypoint script executable
RUN chmod +x entrypoint.sh
# Collect static files
RUN python manage.py collectstatic --noinput --clear
# Set the entrypoint script
ENTRYPOINT ["./entrypoint.sh"]I wrote bin/deploy.sh for deployment to a machine running Dokku. It's accompanied by bin/.deploy.env.example which shows the required environment variables.
- Run python tests via
pytest - Run javascript tests via
npm test - Run
invoke -lto see all available Invoke tasks. These are defined in the tasks.py file. - You'll want to setup pre-commit by running
pre-commit installfollowed bypre-commit install --hook-type commit-msg. Optionally runpre-commit run --all-filesto make sure your pre-commit setup is okay.
Illustrations
