A wine cellar management application with OCR label scanning.
- Label Scanning: Upload wine label images for automatic text extraction via AI
- Wine Autocomplete: Search 100K+ wines from the X-Wines dataset with community ratings
- Inventory Tracking: Check-in and check-out bottles with full history
- Smart Parsing: Automatically identifies vintage, grape variety, region, and more
- Search: Find wines by any criteria
- Web Interface: Simple, mobile-friendly interface
- Python 3.11+
- MongoDB 7.0+
- Tesseract OCR (optional fallback)
From PyPI:
pip install wineboxFrom source:
# Clone the repository
git clone https://github.com/jdrumgoole/winebox.git
cd winebox
# Install dependencies
uv sync --all-extras
# Start MongoDB (using Docker)
docker run -d -p 27017:27017 --name mongodb mongo:7
# Install Tesseract OCR (optional)
# macOS:
brew install tesseract
# Ubuntu/Debian:
sudo apt-get install tesseract-ocrWineBox uses TOML configuration files:
# Copy example configuration
cp config/config.toml.example config.toml
cp config/secrets.env.example secrets.env
# Edit secrets.env with your API keys
nano secrets.envSee the Configuration Guide for full details.
# Development mode with auto-reload
uv run python -m invoke start --reload
# Background mode
uv run python -m invoke start-background
# Check status
uv run python -m invoke status
# Stop server
uv run python -m invoke stop- Web Interface: http://localhost:8000/static/index.html
- API Documentation: http://localhost:8000/docs
- Health Check: http://localhost:8000/health
WineBox uses a TOML-based configuration system with separate secrets management:
| File | Purpose |
|---|---|
config.toml |
Main configuration (server, database, features) |
secrets.env |
Sensitive credentials (API keys) |
Files are searched in priority order:
./config.toml- Project root (development)~/.config/winebox/config.toml- User config/etc/winebox/config.toml- System config (production)
[server]
host = "127.0.0.1"
port = 8000
debug = false
[database]
mongodb_url = "mongodb://localhost:27017"
mongodb_database = "winebox"
[ocr]
use_claude_vision = true
[email]
backend = "console"WINEBOX_SECRET_KEY=your-secret-key-here
WINEBOX_ANTHROPIC_API_KEY=sk-ant-api03-...Environment variables can override any configuration value.
- Navigate to the Check In page
- Upload front label image (required)
- Optionally upload back label image
- Review/edit auto-detected wine details
- Set quantity and add notes
- Click "Check In Wine"
- Go to the Cellar view
- Click "Check Out" on a wine card
- Enter quantity to remove
- Add optional notes (tasting notes, occasion)
- Confirm checkout
Use the Search page to find wines by:
- Text search (name, winery, region)
- Vintage year
- Grape variety
- Region or country
- Stock status
Full REST API available at /api:
| Endpoint | Method | Description |
|---|---|---|
/api/wines/checkin |
POST | Add wine to cellar |
/api/wines/{id}/checkout |
POST | Remove wine from cellar |
/api/wines |
GET | List all wines |
/api/wines/{id} |
GET | Get wine details |
/api/cellar |
GET | Current inventory |
/api/cellar/summary |
GET | Cellar statistics |
/api/transactions |
GET | Transaction history |
/api/search |
GET | Search wines |
/api/xwines/search |
GET | Autocomplete wine search |
/api/xwines/wines/{id} |
GET | X-Wines wine details |
/api/xwines/stats |
GET | Dataset statistics |
See /docs for interactive API documentation.
WineBox uses MongoDB for data storage. Configure the connection in config.toml:
[database]
mongodb_url = "mongodb://localhost:27017"
mongodb_database = "winebox"Wine label images are stored in the data/images/ directory by default.
| Item | Default Location | Config Key |
|---|---|---|
| Database | MongoDB winebox |
database.mongodb_database |
| Images | data/images/ |
storage.data_dir |
Note: Back up your MongoDB database and images directory regularly.
WineBox integrates the X-Wines dataset for wine autocomplete, providing suggestions from 100,646 wines with 21 million community ratings.
# Option 1: Test dataset (100 wines, for development)
uv run python deploy/import_xwines_mongo.py --version test
# Option 2: Full dataset (100K+ wines, for production)
# First, download from Google Drive
uv pip install gdown
mkdir -p data/xwines
uv run gdown --folder "https://drive.google.com/drive/folders/1LqguJNV-aKh1PuWMVx5ELA61LPfGfuu_?usp=sharing" -O data/xwines/
cp data/xwines/X-Wines_Official_Repository/last/XWines_Full_*.csv data/xwines/
# Then import
uv run python deploy/import_xwines_mongo.py --version fullThe autocomplete appears when typing in the Wine Name field during check-in.
WineBox uses AI-powered label scanning to extract wine information from photos.
For best results, configure Claude Vision by adding your API key to secrets.env:
WINEBOX_ANTHROPIC_API_KEY=your-api-keyClaude Vision provides intelligent label analysis that:
- Handles decorative and artistic fonts
- Understands wine-specific terminology
- Extracts structured data (winery, vintage, grape variety, region, etc.)
- Works with curved or angled text
If no Anthropic API key is configured, WineBox falls back to Tesseract OCR:
# macOS
brew install tesseract
# Ubuntu/Debian
sudo apt-get install tesseract-ocrTo force Tesseract only (save API costs during development):
# config.toml
[ocr]
use_claude_vision = falseWineBox requires authentication for all API endpoints (except /health).
# Create an admin user
uv run winebox-admin add admin@example.com --admin --password yourpassword
# Create a regular user
uv run winebox-admin add user@example.com --password yourpassword
# List all users
uv run winebox-admin list
# Disable/enable a user
uv run winebox-admin disable user@example.com
uv run winebox-admin enable user@example.com
# Change password
uv run winebox-admin passwd user@example.com --password newpassword
# Remove a user
uv run winebox-admin remove user@example.com# Start server (foreground)
uv run winebox-server start --foreground
# Start server (background)
uv run winebox-server start
# Stop server
uv run winebox-server stop
# Restart server
uv run winebox-server restart
# Check status
uv run winebox-server statusThe API uses JWT bearer tokens. To authenticate:
- POST to
/api/auth/tokenwith email (in theusernamefield per OAuth2 spec) andpassword(form-urlencoded) - Include the returned token in subsequent requests:
Authorization: Bearer <token>
Tokens expire after 24 hours.
WineBox includes deployment scripts for Digital Ocean:
# Initial server setup
uv run python -m invoke deploy-setup --host YOUR_DROPLET_IP
# Deploy to production
uv run python -m invoke deploySee the Deployment Guide for full instructions.
# Run all tests
uv run python -m invoke test
# With verbose output
uv run python -m invoke test --verbose
# With coverage
uv run python -m invoke test --coverage
# Run without Claude Vision (save API costs)
WINEBOX_USE_CLAUDE_VISION=false uv run python -m invoke testwinebox/
├── winebox/ # Application package
│ ├── main.py # FastAPI app
│ ├── config/ # Configuration module
│ ├── models/ # MongoDB document models
│ ├── schemas/ # API schemas
│ ├── routers/ # API endpoints
│ ├── services/ # Business logic
│ └── static/ # Web interface
├── config/ # Configuration templates
├── deploy/ # Deployment module
├── tests/ # Test suite
├── docs/ # Documentation
└── tasks.py # Build tasks
uv run python -m invoke docs-build
uv run python -m invoke docs-serve- FastAPI: Web framework
- MongoDB: Document database
- PyMongo (async): MongoDB driver
- fastapi-users: Authentication
- Tesseract/Claude Vision: OCR engines
- Vanilla JS: Frontend (no frameworks)
MIT License