A Flask-based web application for managing recipes with ingredients, images, and unit conversions.
Part of the README for this repo has been generated by ai and modified, because I would prefer to focus on development over writing the README. It should still be okay.
- Recipe management with ingredients and directions
- Image upload and storage (currently stored in filesystem with abstractions to be moved to bucket later)
- Unit conversions for recipe ingredients
- Ingredient density tracking for weight calculations
Obviously, software development help would be great, but feature requests are really great too! At some point, I will be happy with this repo and need more feature requests to fix. Please create a discussion post or issue.
- Python 3.10+
- Node.js 20+ (for SCSS compilation)
- pnpm package manager
- Docker & Docker Compose (optional, for containerized deployment)
The application uses environment variables for configuration:
DATABASE_URL: Database connection string (defaults to SQLite for local dev)SECRET_KEY: Flask secret key for session management and security
git clone https://github.com/EReaso/cookbook.git
cd cookbookpython -m venv venv
source venv/bin/activate # On Windows: venv\Scripts\activatepip install -r requirements.txtFor development (includes testing and linting tools):
pip install -r requirements-dev.txtpnpm installflask db upgradepnpm run buildThe easiest way to get started is with the quickstart script:
./scripts/quickstart.shThis script will:
- Create a
.envfile with generated SECRET_KEY and POSTGRES_PASSWORD - Set up Docker secrets for Postgres password (if Swarm mode is active)
- In non-Swarm mode, the password from
.envwill be used - Provide you with the command to start the application
After running the script, start the application with this command:
docker-compose up --buildThe application will be available at http://localhost:5000 depending on your environment.
If you prefer manual setup or the script doesn't work for your environment:
- Set up environment variables:
cp .env.example .env
# Generate a secure SECRET_KEY and update .env
python -c "import secrets; print(secrets.token_hex(32))"- Set up the password secret file:
# Create the password file from the example (default password is cookbook_dev_password)
mkdir -p .secrets
echo "cookbook_dev_password" > .secrets/postgres_password
chmod 600 .secrets/postgres_password
# Or use a custom secure password
echo "your_secure_password" > .secrets/postgres_password
chmod 600 .secrets/postgres_passwordThe .secrets/postgres_password file is used for Docker Compose secrets and is ignored by git. File permissions are set to 600 to restrict access to the owner only.
- Start the application:
docker-compose up --build- Stop the application:
docker-compose downTo remove volumes (including database data and uploaded images):
docker-compose down -vData Persistence:
The application uses Docker volumes to persist data across container restarts:
postgres_data: PostgreSQL database datainstance_data: Flask instance directory, which includes uploaded image files stored in/app/instance/storage
These volumes ensure that your recipes, ingredients, and uploaded images are preserved when you stop and restart the containers. Only running docker-compose down -v will remove these volumes and delete the data.
About Docker Secrets:
This application uses file-based Docker secrets for enhanced security. The Postgres password is stored in .secrets/postgres_password file, which is shared with containers via Docker secrets mechanism. This file is excluded from version control via .gitignore to prevent accidentally committing secrets to the repository.
The password file approach works with both:
- Regular Docker Compose mode: Uses file-based secrets (default)
- Docker Swarm mode: Also compatible with file-based secrets
See .secrets/POSTGRES_PASSWORD.example for the example secret format.
For local development without Docker:
python wsgi.pyThe application will be available at http://localhost:5000
Use gunicorn:
gunicorn wsgi:wsgi_apppytestpytest --cov=app --cov-report=htmlView coverage report by opening htmlcov/index.html in your browser.
pytest tests/test_models.pyTo run the same screenshot generation step locally as CI:
python -m playwright install --with-deps chromium
python scripts/take_screenshots.py --config screenshots.yml --output-dir screenshotsThis project uses Ruff for both linting and formatting:
- 4-space indentation
- Line length: 120 characters
- Import sorting via Ruff's isort-compatible rules
Format code with Ruff:
ruff format .Auto-fix lint issues:
ruff check --fix .Lint code with Ruff:
ruff check .Install pre-commit hooks:
pre-commit installRun hooks manually:
pre-commit run --all-filesCreate a new migration:
flask db migrate -m "Description of changes"Apply migrations:
flask db upgradeRollback migration:
flask db downgradeThis project uses GitHub Actions for continuous integration:
- Tests: Runs on Python 3.12
- Linting: Checks code quality with Ruff
- Coverage: Uploads coverage reports to Codecov
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes
- Run tests and linting
- Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
This project is open source and available under the AGPL 3.0 License.