Skip to content

Turn ingredients into culinary magic with AI-powered recipe suggestions. Upload ingredient photos, discover personalized recipes. Built with Flask, PostgreSQL, Azure AI & Spoonacular API.

Notifications You must be signed in to change notification settings

vladbortnik/recipe-web-app

Repository files navigation

🍳 Recipe Hub

Turn Ingredients Into Culinary Magic

Live Demo Python Flask PostgreSQL Docker

An AI-powered web application that transforms ingredient photos into personalized recipe recommendations.

Live Demo β€’ Report Bug β€’ Request Feature


πŸ“‹ Table of Contents


🎯 Overview

Recipe Hub is a production-grade web application that empowers home chefs to discover recipes based on ingredients they already have. Simply upload photos of your ingredients, and let Azure Computer Vision AI identify them automatically. The app then suggests personalized recipes using the Spoonacular API, eliminating food waste and inspiring culinary creativity.

Built with scalability, security, and user experience in mind, Recipe Hub features a load-balanced multi-instance architecture, OAuth integration, and comprehensive security hardening.


✨ Key Features

πŸ€– AI-Powered Ingredient Recognition

  • Upload ingredient photos using Azure Computer Vision API
  • Automatic ingredient identification and tagging
  • Smart ingredient management with virtual pantry

πŸ” Intelligent Recipe Discovery

  • Spoonacular API integration for 1M+ recipes
  • Personalized recommendations based on available ingredients
  • Favorite and save recipes to your account
  • Global cuisine exploration with dietary filters

πŸ‘€ User Management & Authentication

  • Traditional email/password signup with email verification
  • Google OAuth 2.0 integration for quick sign-in
  • Secure password reset flow with time-limited tokens
  • Session management with Flask-Login

πŸ” Enterprise-Grade Security

  • Password hashing with Bcrypt
  • CSRF protection on all forms
  • Network segregation with Docker (frontend/backend networks)
  • Environment-based secrets management
  • GDPR-compliant cookie consent

⚑ Production-Ready Architecture

  • Load-balanced deployment (3 Gunicorn instances)
  • PostgreSQL database with automated migrations
  • Docker Compose orchestration
  • Fault-tolerant multi-instance setup
  • Health monitoring and auto-restart

πŸ“± Modern User Experience

  • Responsive design with Bootstrap 5
  • Smooth animations using AOS library
  • Google Analytics integration
  • SEO-optimized with meta tags, sitemap, and structured data
  • Progressive enhancement for all devices

🌐 Live Demo

Experience Recipe Hub: recipe.vladbortnik.dev

The application is deployed on a production server with:

  • βœ… Load balancing across 3 instances
  • βœ… SSL/TLS encryption
  • βœ… Automated database migrations
  • βœ… Zero-downtime deployments
  • βœ… Health monitoring

πŸ› οΈ Tech Stack

Backend

Flask Python Gunicorn PostgreSQL

  • Flask 3.0+: Lightweight WSGI web framework
  • Gunicorn: Production WSGI server for concurrent request handling
  • PostgreSQL: Robust relational database
  • SQLAlchemy: Pythonic ORM with relationship management
  • Flask-Migrate: Alembic-based database migrations

Authentication & Security

OAuth

  • Flask-Login: User session management
  • Flask-Bcrypt: Secure password hashing
  • Authlib: Google OAuth 2.0 integration
  • Flask-WTF: Form validation & CSRF protection
  • python-dotenv: Environment variable management

Frontend

HTML5 CSS3 Bootstrap

  • Jinja2: Server-side templating engine
  • Bootstrap 5: Responsive UI framework
  • Font Awesome: Icon library
  • AOS: Scroll animation library
  • Google Fonts: Typography (Nunito)

External APIs

Azure

  • Azure Computer Vision: AI-powered ingredient recognition from images
  • Spoonacular API: Recipe database and nutrition information

DevOps & Infrastructure

Docker Nginx

  • Docker: Containerization
  • Docker Compose: Multi-container orchestration
  • Nginx: Reverse proxy and load balancer (upstream deployment)
  • Git: Version control

πŸ—οΈ Architecture

Multi-Instance Load-Balanced Design

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚            Nginx Load Balancer              β”‚
β”‚         (Upstream Infrastructure)           β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
             β”‚            β”‚
   β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
   β”‚              β”‚             β”‚             β”‚
β”Œβ”€β”€β–Όβ”€β”€β”€β”     β”Œβ”€β”€β”€β–Όβ”€β”€β”     β”Œβ”€β”€β”€β–Όβ”€β”€β”           β”‚
β”‚ web1 β”‚     β”‚ web2 β”‚     β”‚ web3 β”‚           β”‚
β”‚:5002 β”‚     β”‚:5003 β”‚     β”‚:5004 β”‚           β”‚
β””β”€β”€β”¬β”€β”€β”€β”˜     β””β”€β”€β”€β”¬β”€β”€β”˜     β””β”€β”€β”€β”¬β”€β”€β”˜           β”‚
   β”‚             β”‚             β”‚              β”‚
   β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                 β”‚
          β”Œβ”€β”€β”€β”€β”€β”€β–Όβ”€β”€β”€β”€β”€β”€β”
          β”‚ PostgreSQL  β”‚
          β”‚  Database   β”‚
          β”‚   (db:5432) β”‚
          β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Network Segregation

  • Frontend Network: Public-facing web services
  • Backend Network: Database access (internal only)
  • No exposed database ports to host machine
  • Internal DNS resolution between containers

πŸ“ Project Structure

recipe-web-app/
β”œβ”€β”€ app/
β”‚   β”œβ”€β”€ __init__.py              # Flask app factory
β”‚   β”œβ”€β”€ config.py                # Configuration management
β”‚   β”œβ”€β”€ models.py                # SQLAlchemy database models
β”‚   β”œβ”€β”€ routes.py                # Application routes & views
β”‚   β”œβ”€β”€ forms.py                 # WTForms definitions
β”‚   β”œβ”€β”€ utils.py                 # Helper functions (API calls, email)
β”‚   β”œβ”€β”€ templates/               # Jinja2 HTML templates
β”‚   β”‚   β”œβ”€β”€ layout.html          # Base template (SEO-optimized)
β”‚   β”‚   β”œβ”€β”€ index.html           # Landing page
β”‚   β”‚   β”œβ”€β”€ dashboard.html       # User dashboard
β”‚   β”‚   β”œβ”€β”€ upload.html          # Image upload interface
β”‚   β”‚   β”œβ”€β”€ login.html           # Login page
β”‚   β”‚   β”œβ”€β”€ signup.html          # Registration page
β”‚   β”‚   └── ...
β”‚   └── static/                  # CSS, images, favicon
β”‚       β”œβ”€β”€ main.css
β”‚       β”œβ”€β”€ robots.txt
β”‚       └── favicon.ico
β”œβ”€β”€ migrations/                  # Database migration files
β”œβ”€β”€ docker-compose.yml           # Multi-container setup
β”œβ”€β”€ Dockerfile                   # Container definition
β”œβ”€β”€ entrypoint.sh               # Startup script (migrations)
β”œβ”€β”€ requirements.txt            # Python dependencies
β”œβ”€β”€ .env-example                # Environment variables template
β”œβ”€β”€ GITHUB-ABOUT-SECTION.md     # GitHub repository metadata
└── README.md                   # This file

πŸš€ Getting Started

Prerequisites

Installation

  1. Clone the repository

    git clone https://github.com/vladbortnik/recipe-web-app.git
    cd recipe-web-app
  2. Set up environment variables

    cp .env-example .env

    Edit .env and add your API keys:

    SECRET_KEY=your-secret-key
    DATABASE_URL=postgresql://user:password@db:5432/recipe_db
    
    # Azure Computer Vision
    AZURE_VISION_KEY=your-azure-key
    AZURE_VISION_ENDPOINT=your-azure-endpoint
    
    # Spoonacular API
    SPOONACULAR_API_KEY=your-spoonacular-key
    
    # Google OAuth (optional)
    GOOGLE_CLIENT_ID=your-google-client-id
    GOOGLE_CLIENT_SECRET=your-google-client-secret
    
    # Email (for password reset)
    MAIL_SERVER=smtp.gmail.com
    MAIL_PORT=587
    MAIL_USERNAME=your-email@gmail.com
    MAIL_PASSWORD=your-app-password
  3. Build and run with Docker Compose

    docker-compose up --build -d
  4. Access the application

  5. View logs (optional)

    docker-compose logs -f web1 web2 web3
  6. Stop the application

    docker-compose down

Database Migrations

Migrations are handled automatically by entrypoint.sh. No manual intervention required.

For manual migration management:

# Access container
docker exec -it <container_name> /bin/bash

# Create migration
flask db migrate -m "Description"

# Apply migration
flask db upgrade

πŸ” Security Features

Feature Implementation Purpose
Password Hashing Bcrypt with salt Secure credential storage
CSRF Protection Flask-WTF tokens Prevent cross-site attacks
Network Isolation Docker networks Database not exposed to host
OAuth 2.0 Google Sign-In Secure third-party authentication
Environment Variables python-dotenv No hardcoded secrets
Route Protection @login_required Authenticated-only endpoints
Session Management Flask-Login Secure user sessions
Email Verification Time-limited tokens Prevent fake accounts

⚑ Performance

  • Load Balancing: 3 Gunicorn worker instances
  • Concurrent Requests: 6+ workers per instance (18+ total)
  • Database Connection Pooling: SQLAlchemy pool management
  • Static Asset Caching: Browser caching headers
  • Lazy Loading: AOS animations on scroll
  • Fault Tolerance: Auto-restart on failure

🀝 Connect With Me

Portfolio LinkedIn Twitter

GitHub Contact Me

Built with real production experience by Vlad Bortnik


🌟 Built with a passion for clean code, robust architecture, and scalable solutions

Software Engineer | Frontend (React 19) β†’ Backend (Flask, PostgreSQL) β†’ Infrastructure (Docker, Nginx, Cloud)

vladbortnik.dev β€’ Contact β€’ CS degree β€’ NYC πŸ—½


Last updated: December 2025