Because after a few drams (and this app), you'll be the smartest person in the room.
2.3K
Track your whisky collection, log tasting notes, and analyse flavour profiles — all in a self-hosted web app.
A native Android app is available for WhiskyWise. It connects to your self-hosted server via the REST API and requires server ≥ v1.5.9.
WhiskyWise can be installed in several ways depending on your setup.
The easiest way to run WhiskyWise if you already have a Home Assistant instance. No Docker commands, no compose files required.
Prerequisites: Home Assistant OS or Supervised installation.
https://github.com/prolife86/WhiskyWise
secret_keyAll data is stored in the add-on's persistent /data volume — your collection and photos survive restarts and updates.
See
whiskywise/DOCS.md for full configuration options.
# 1. Clone / download this folder
cd whiskywise
# 2. Set a strong SECRET_KEY in docker-compose.yml
# 3. Build and run
docker-compose up -d
# 4. Open in your browser
http://localhost:5000
WhiskyWise is available on the Unraid Community Applications (CA) store. Search for WhiskyWise and install directly from there.
| Variable | Default | Description |
|---|---|---|
SECRET_KEY | change-this-... | Flask session secret — must be changed |
DATABASE_PATH | /data/db/whiskywise.db | SQLite database path |
UPLOAD_FOLDER | /data/uploads | Photo upload directory |
For Home Assistant users, these are configured via the add-on Configuration tab in the HA UI.
All data is stored in a named Docker volume (whiskywise_data):
/data/db/whiskywise.db (SQLite)/data/uploads/The easiest way to back up and restore is via Admin Panel → 💾 Backup & Restore.
whiskywise.db.bak before being replaced.docker run --rm -v whiskywise_data:/data -v $(pwd):/backup alpine \
tar czf /backup/whiskywise-backup.tar.gz /data
To restore:
docker run --rm -v whiskywise_data:/data -v $(pwd):/backup alpine \
tar xzf /backup/whiskywise-backup.tar.gz -C /
Home Assistant users: data lives in the add-on's
/datafolder, mapped automatically to a persistent volume. Back up via the standard HA backup system or the Admin Panel.
Admins have access to a Server Settings section within ⚙ Settings. Currently this controls:
1,000.00 for USD/GBP, 1.000,00 for EUR/CHF). The Android companion app reads this from the API and applies it automatically.services:
whiskywise:
image: ghcr.io/prolife86/whiskywise:latest
ports:
- "5000:5000"
volumes:
- /mnt/user/appdata/WhiskyWise:/data
environment:
- SECRET_KEY=change-this-to-a-long-random-secret
- DATABASE_PATH=/data/db/whiskywise.db
- UPLOAD_FOLDER=/data/uploads
restart: unless-stopped
Critical: Always map the data directory to a local volume. Deleting the container without a volume mapping will permanently lose your collection data and photos.
SECRET_KEYadminwhiskywise⚠️ You will be prompted to change this on first login.
For the admin panel, navigate to http://[IP]:[Port]/admin
WhiskyWise includes a full REST API for use by Android/iOS apps or any HTTP client. All endpoints are user-scoped — a token only ever grants access to that user's own data.
curl -X POST http://localhost:5000/api/auth/token \
-H "Content-Type: application/json" \
-d '{"username": "admin", "password": "yourpassword", "name": "My Android"}'
{
"data": {
"token": "a3f9...",
"id": 1,
"name": "My Android",
"created": "2026-05-02T10:00:00+00:00"
}
}
Include the token on every subsequent request:
Authorization: Bearer a3f9...
API clients are encouraged to send their app version on every request:
X-Client-Version: 0.3.2
The server records this on the token row and updates it on each request, so admins can see which app version is behind each active token.
| Method | Path | Description |
|---|---|---|
POST | /api/auth/token | Exchange credentials for a Bearer token |
GET | /api/auth/tokens | List your tokens (metadata + IP + version) |
DELETE | /api/auth/token/<id> | Revoke a token |
GET | /api/auth/sessions | List your active browser sessions |
DELETE | /api/auth/session/<id> | Revoke a browser session |
GET | /api/v1/stats | Dashboard counts + top-10 + flavour list + currency symbol |
GET | /api/barcode-lookup | Look up a barcode in the user's collection |
GET | /api/v1/collection | Collection list (filterable + paginated) |
GET | /api/v1/wishlist | Wishlist |
POST | /api/v1/wishlist | Add wishlist item |
PUT | /api/v1/wishlist/<id> | Update wishlist item |
GET | /api/v1/whisky/<id> | Full detail for a single whisky |
POST | /api/v1/whisky | Create a collection entry |
PUT | /api/v1/whisky/<id> | Update a collection entry (partial) |
DELETE | /api/v1/whisky/<id> | Delete a whisky |
POST | /api/v1/whisky/<id>/photo/<slot> | Upload a photo (front, back, cask, barcode) |
DELETE | /api/v1/whisky/<id>/photo/<slot> | Remove a photo |
POST | /api/photo/<id>/<slot>/rotate | Rotate a saved photo 90° clockwise |
GET | /api/photo/<filename> | Authenticated photo serving |
GET /api/v1/collection accepts the following query parameters:
| Parameter | Description |
|---|---|
q | Free-text search (name, distillery, region, barcode) |
flavor | Exact flavour profile match |
min_score | Minimum score (inclusive) |
max_price | Maximum price (inclusive) |
status | open, stashed, or finished |
retired | yes, no, or omit for all |
sort | score (default), name, distillery, added, price, updated, last_tasted |
order | desc (default) or asc |
limit | Max results (default 200) |
offset | Pagination offset (default 0) |
GET /api/v1/stats returns:
{
"data": {
"total": 42,
"open": 8,
"stashed": 30,
"finished": 4,
"wishlist_count": 12,
"top10": [...],
"dominant_flavours": [...],
"currency_code": "EUR",
"currency_symbol": "€"
}
}
Every whisky in the API response includes a radar object with seven flavour axes, each scored 0–5:
"radar": {
"woody": 2, "smoky": 4, "cereal": 1,
"floral": 0, "fruity": 3, "medicinal": 5, "fiery": 2
}
Send radar values when creating or updating using either a nested dict or flat keys:
{ "radar": { "smoky": 4, "fruity": 2 } }
All successful responses use {"data": ...}. All errors use {"error": "..."} with an appropriate HTTP status code.
Barcode scanning uses the browser's BarcodeDetector API (available in Chrome 83+ and Safari 17+). Works best on Android Chrome and iOS Safari 17+. If the API is unavailable, type the barcode manually.
192.168.1.100)http://192.168.1.100:5000 on your phone, or connect via the Android appCamera/barcode scanning requires HTTPS or localhost. For LAN HTTPS, consider a reverse proxy with a local SSL certificate, or use Tailscale.
git checkout -b feature/AmazingFeature)git commit -m 'Add some AmazingFeature')git push origin feature/AmazingFeature)Parts of this project were developed with AI assistance to accelerate development. All code is reviewed and maintained manually.
Distributed under the MIT License. See LICENSE for more information.
Content type
Image
Digest
sha256:df4a80579…
Size
69.8 MB
Last updated
4 months ago
docker pull heisenbugger86/whiskywise