Your Magic: The Gathering Collection Companion
Spellbook is a self-hosted card collection management platform with mobile scanning, OCR recognition, and real-time sync between your phone and web dashboard.
IMPORTANT: This project is under development and is not a stable, released product. It is provided "as-is", without warranty or guarantee. It works to some extent, but may be incomplete, unstable, or contain bugs. Mentions of a version such as "v2" do not imply an official release.
- Mobile Camera Scanning: Capture cards using your phone's camera
- Batch Scanning: Scan multiple cards in a session
- OCR Recognition: Automatic card text extraction using Tesseract
- Smart Matching: AI-powered card identification with confidence scores
- Review Workflow: Confirm or correct matches from web or mobile
- Multiple Collections: Organize cards into binders, decks, trade lists
- Condition Tracking: Track card conditions (NM, LP, MP, HP, DMG)
- Foil Support: Mark foil versions separately
- Price Tracking: Real-time prices from Scryfall
- Statistics: Collection value, rarity breakdown, color distribution
- CSV Import: Deckbox, Moxfield, generic CSV formats
- MTG Arena: Import/export Arena format deck lists
- JSON Export: Full collection backup in Spellbook format
- Web Dashboard: Vite + React 18
- Mobile App: Flutter (iOS & Android)
- API: FastAPI with OpenAPI documentation
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ Mobile App │────▶│ REST API │────▶│ PostgreSQL │
│ (Flutter) │ │ (FastAPI) │ │ Database │
└─────────────────┘ └─────────────────┘ └─────────────────┘
│
┌──────────────────────┼──────────────────────┐
▼ ▼ ▼
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ MinIO │ │ Celery │ │ Redis │
│ (S3 Storage) │ │ (Background) │ │ (Cache/Queue) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
- Python 3.11+ - Backend runtime
- Node.js 18+ - Frontend build
- Docker/Podman - Container runtime
- Flutter 3.16+ - Mobile app development (optional)
# Start all services (PostgreSQL, Redis, MinIO)
docker-compose up -d
# Verify services are running
docker-compose pscd backend
# Create virtual environment
python3.11 -m venv venv
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Copy environment configuration
cp .env.dev .env
# Run database migrations
alembic upgrade head
# Initialize with admin user
DEBUG=true python init_db.py \
--admin-email [email protected] \
--admin-username admin \
--admin-password admin123!
# Start the API server
DEBUG=true uvicorn app.main:app --reload --host 0.0.0.0 --port 8000# In a new terminal, from backend directory
source venv/bin/activate
# Start Celery worker
celery -A app.celery_app worker --loglevel=info --queues=default,scans,priority
# (Optional) Start Celery beat for scheduled tasks
celery -A app.celery_app beat --loglevel=infocd frontend
# Install dependencies
npm install
# Start development server
npm run devcd mobile
# Get Flutter dependencies
flutter pub get
# Run code generation
flutter pub run build_runner build --delete-conflicting-outputs
# Run on device/emulator
flutter run| Service | URL | Description |
|---|---|---|
| API | http://localhost:8000 | FastAPI backend |
| API Docs | http://localhost:8000/docs | Swagger UI |
| Web App | http://localhost:5173 | Vite + React frontend |
| MinIO Console | http://localhost:9001 | Object storage UI |
Admin Account:
- Email:
[email protected] - Username:
admin - Password:
admin123!
MinIO:
- Username:
spellbook - Password:
spellbook-dev-password
Update the API URL in /mobile/lib/app/network/api_constants.dart:
class ApiConstants {
static const String baseUrl = 'http://YOUR_SERVER_IP:8000';
// ...
}For local development, use your machine's local IP (not localhost) so the mobile device can connect.
cd backend
source venv/bin/activate
# Create a new migration
alembic revision --autogenerate -m "Description of changes"
# Apply migrations
alembic upgrade head
# Rollback one step
alembic downgrade -1spellbook/
├── backend/ # FastAPI backend
│ ├── app/
│ │ ├── api/v1/ # API endpoints
│ │ ├── models/ # SQLAlchemy models
│ │ ├── schemas/ # Pydantic schemas
│ │ ├── services/ # Business logic
│ │ └── tasks/ # Celery tasks
│ ├── migrations/ # Alembic migrations
│ └── requirements.txt
├── frontend/ # Vite + React web app
│ ├── src/
│ │ ├── pages/ # Page components
│ │ ├── components/ # React components
│ │ └── lib/ # Utilities
│ └── package.json
├── mobile/ # Flutter mobile app
│ ├── lib/
│ │ └── app/
│ │ ├── features/ # Feature modules
│ │ └── shared/ # Shared widgets
│ └── pubspec.yaml
├── scryfall/ # Card data (not in repo)
└── docker-compose.yml # Development services
# Database
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_USER=spellbook
POSTGRES_PASSWORD=spellbook
POSTGRES_DB=spellbook
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
# MinIO (S3-compatible storage)
MINIO_ENDPOINT=localhost:9000
MINIO_ACCESS_KEY=spellbook
MINIO_SECRET_KEY=spellbook-dev-password
MINIO_SECURE=false
# Security
JWT_SECRET_KEY=your-super-secret-key-change-in-production
JWT_ALGORITHM=HS256
JWT_EXPIRE_MINUTES=30
# Feature flags
SCAN_ENABLED=true
DEBUG=true# Backend tests
cd backend
pytest
# Frontend tests
cd frontend
npm test
# Mobile tests
cd mobile
flutter testOnce the backend is running, visit:
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
Key endpoints:
POST /api/v1/auth/login- AuthenticationGET /api/v1/cards/search- Search cardsGET /api/v1/collections- List collectionsPOST /api/v1/scan/upload- Upload scan imageGET /api/v1/scan/batches- List scan batches
docker-compose logs postgres-dev
docker-compose restart postgres-dev# Check if buckets exist
docker-compose exec minio-dev mc ls local/
# Recreate buckets
docker-compose restart minio-setup# Check worker status
celery -A app.celery_app inspect active
# View task queue
celery -A app.celery_app inspect reserved- Ensure backend is running on
0.0.0.0not127.0.0.1 - Use your machine's local IP, not
localhost - Check firewall allows port 8000
MIT License - see LICENSE