- mail.ts: add explicit types to decodeMimeHeader callback params - SessionList.tsx: use React.MouseEvent instead of nativeEvent - ComposeModal.tsx: construct name from first_name + last_name - MailDetail.tsx: destructure onReply/onForward from props - RichTextEditor.tsx: use SetContentOptions object instead of boolean - MailSearchBar.tsx: add optional value prop to interface - EmptyState.tsx: add optional children prop - Badge.tsx: add secondary variant to BadgeVariant, variantClasses, dotColors - ConfirmDialog.tsx: add optional children prop - hooks.ts: extend SearchResult type to include mail/file/event
LeoCRM v1.0
Self-hosted CRM for small sales teams (5–25 sales reps). Stack: FastAPI + SQLAlchemy (async) + PostgreSQL + Redis + Alpine.js + Tailwind + Docker + Coolify
Quick Start (Development)
1. Clone and Setup
git clone <repo-url> leocrm
cd leocrm
# Create virtual environment
python3 -m venv .venv
source .venv/bin/activate
# Install dependencies
pip install -r requirements.txt -r requirements-dev.txt
2. Configure Environment
cp .env.example .env
# Generate a secure SECRET_KEY (min 32 chars)
python3 -c "import secrets; print('SECRET_KEY=' + secrets.token_urlsafe(48))" >> .env
# Edit .env and set DATABASE_URL, REDIS_URL, SECRET_KEY
nano .env
3. Initialize Database
# Apply migrations
alembic upgrade head
4. Run Server
# Development with auto-reload
uvicorn app.main:app --reload --port 8000
# Start ARQ worker (for background jobs)
arq app.core.jobs.WorkerSettings
Open:
- API: http://localhost:8000
- Swagger UI: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
- Health: http://localhost:8000/api/v1/health
- Metrics: http://localhost:8000/api/v1/metrics (admin-only)
Production Setup
Docker Compose
cp .env.example .env
# Edit .env — set DATABASE_URL, REDIS_URL, SECRET_KEY, CORS_ORIGINS
# Set ENVIRONMENT=production, SESSION_COOKIE_SECURE=true
docker compose up -d
# Run migrations
docker compose exec api alembic upgrade head
Manual (without Docker)
pip install -r requirements.txt
alembic upgrade head
# Start API server (2 workers)
uvicorn app.main:app --host 0.0.0.0 --port 8000 --workers 2
# Start ARQ worker (separate process)
arq app.core.jobs.WorkerSettings
See docs/admin-guide.md for detailed deployment, backup, and troubleshooting instructions.
API
Key Endpoints
| Endpoint | Method | Auth | Description |
|---|---|---|---|
/api/v1/health |
GET | No | Health check (DB, Redis, storage, worker) |
/api/v1/metrics |
GET | Admin | Prometheus metrics (text/plain) |
/api/v1/auth/login |
POST | No | Login |
/api/v1/contacts |
GET | Yes | List contacts (paginated, max page_size=100) |
/api/v1/contacts/export |
GET | Yes | Stream contacts as CSV |
/api/v1/companies |
GET | Yes | List companies (paginated, max page_size=100) |
/api/v1/companies/export |
GET | Yes | Stream companies as CSV |
Pagination
All list endpoints support pagination with page and page_size parameters.
page_size is capped at 100 — values >100 return HTTP 422.
CSV Export
Contacts and companies support streaming CSV export via /export?format=csv.
Uses StreamingResponse — does not buffer the entire file in memory.
Swagger UI
Interactive API documentation: http://localhost:8000/docs
See docs/api-overview.md for the full endpoint summary.
Monitoring
Health Check
curl http://localhost:8000/api/v1/health
Returns JSON with overall status (healthy/degraded) and individual checks for
database, redis, storage, and worker.
Prometheus Metrics
# Requires admin authentication
curl -b "leocrm_session=<session>" http://localhost:8000/api/v1/metrics
Available metrics:
leocrm_http_requests_total— Total HTTP requestsleocrm_http_request_duration_seconds— Request duration histogramleocrm_db_pool_connections— Database connection pool sizeleocrm_arq_jobs_total— Total ARQ background jobs
Structured Logging
LeoCRM uses structlog for structured JSON logging. All API requests are logged with:
timestamp, level, event, method, path, status, duration_ms, tenant_id.
Environment Profiles
| Profile | ENVIRONMENT |
Use Case |
|---|---|---|
| Development | development |
Local dev (auto-reload, verbose logging) |
| Testing | testing |
Test suite (separate test DB, minimal logging) |
| Production | production |
Docker/Coolify deployment (JSON logging, secure cookies) |
See docs/admin-guide.md for profile details.
Testing
# Run all tests
pytest -v --tb=short
# Run specific test suites
pytest tests/test_monitoring.py tests/test_performance.py tests/test_health.py -v
# Run with coverage
pytest --cov=app --cov-report=term-missing
Environment Variables
See .env.example for all variables and docs/admin-guide.md for detailed descriptions.
Key Variables
| Variable | Required | Description |
|---|---|---|
DATABASE_URL |
✅ | PostgreSQL async connection URL |
REDIS_URL |
✅ | Redis connection URL |
SECRET_KEY |
✅ | Secret key for signing (≥32 chars in prod) |
CORS_ORIGINS |
✅ | Comma-separated allowed origins (no wildcards) |
ENVIRONMENT |
❌ | development | testing | production |
STORAGE_PATH |
❌ | File storage path (default: /tmp) |
SMTP_HOST |
❌ | SMTP server hostname |
Performance Testing
# Seed 200k contacts for performance testing
python scripts/seed_perf_data.py --count 200000
# Verify database indexes
python scripts/check_indexes.py
# Test pagination performance
# GET /api/v1/contacts?page=1&page_size=25 — should be <500ms with 200k records
Project Structure
leocrm/
├── app/
│ ├── main.py # FastAPI entry point with logging middleware
│ ├── config.py # Pydantic settings
│ ├── core/
│ │ ├── monitoring.py # Prometheus metrics + structured logging + health checks
│ │ ├── db.py # Async database engine
│ │ ├── middleware.py # CSRF middleware
│ │ └── ...
│ ├── routes/
│ │ ├── health.py # Health endpoint
│ │ ├── metrics.py # Prometheus metrics endpoint (admin-only)
│ │ ├── contacts.py # Contact CRUD + streaming CSV export
│ │ ├── companies.py # Company CRUD + streaming CSV export
│ │ └── ...
│ ├── models/ # SQLAlchemy models
│ ├── schemas/ # Pydantic schemas
│ ├── services/ # Business logic
│ └── plugins/ # Plugin system
├── scripts/
│ ├── seed_perf_data.py # Performance test data seeding
│ └── check_indexes.py # Database index verification
├── tests/ # Test suite (pytest + pytest-asyncio)
├── docs/
│ ├── admin-guide.md # Admin guide (deploy, backup, restore, troubleshooting)
│ └── api-overview.md # API endpoint summary
├── alembic/ # Database migrations
├── requirements.txt # Production dependencies
├── requirements-dev.txt # Test/lint dependencies
├── .env.example # Environment template
├── docker-compose.yml # Docker Compose
└── README.md # This file
Documentation
- Admin Guide — Deployment, backup, restore, env vars, troubleshooting
- API Overview — Full endpoint reference
- Coolify Setup — Coolify deployment instructions
- Swagger UI — Interactive API docs (auto-generated)
License
Internal project – proprietary.