Skip to content

DamageLabs/whiskey-canon

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

294 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

Whiskey Canon

A comprehensive whiskey collection management application built with TypeScript, React, Express, and SQLite. Track your whiskey collection with detailed information, pricing, tasting notes, inventory management, and investment tracking.

Tests codecov TypeScript React Express SQLite Bootstrap

✨ Features

πŸ“Š Analytics & Data Visualization (NEW!)

  • Interactive Analytics Dashboard with 10+ charts powered by Recharts
  • Financial metrics: Total value, ROI, gain/loss tracking
  • Visual insights: Pie charts, bar charts, scatter plots for deep analysis
  • Performance tracking: Best ROI bottles, most valuable items
  • Distribution analysis: Type, age, rating, and distillery breakdowns
  • Database performance: 10 optimized indexes for instant queries on large collections

πŸ” Authentication & Authorization

  • Session-based authentication with httpOnly cookies
  • Role-Based Access Control (RBAC) with three roles:
    • Admin: Full access including user management
    • Editor: Create, read, and update whiskeys
    • Viewer: Read-only access
  • Private collections: Each user has their own whiskey collection
  • Admin panel: Manage users, change roles, view all collections

πŸ“Š Comprehensive Collection Management

  • 8 whiskey types supported: Bourbon, Scotch, Irish, Japanese, Rye, Tennessee, Canadian, Other
  • 57 data fields organized into 7 categories for detailed tracking
  • Tabbed form interface for easy data entry without overwhelming users
  • Pre-populated data: 30+ whiskeys with MSRP and secondary market prices

Data Categories

1. Basic Information

  • Name, type, distillery, region, country
  • Age, ABV, proof, size, rating
  • Mash bill, awards
  • Limited edition, chill filtered, natural color flags
  • Description

2. Purchase & Acquisition Tracking

  • Purchase date, price, and location
  • Bottle code / batch number
  • Quantity in collection
  • MSRP and secondary market prices

3. Inventory Management

  • Status (In Collection, Consumed, Sold, Gifted, Traded)
  • Storage location
  • Opened/sealed status
  • Date opened
  • Remaining volume percentage

4. Production Details

  • Cask type and finish
  • Barrel number (for single barrels)
  • Bottle number (for limited editions)
  • Vintage year (distillation year)
  • Bottled date

5. Enhanced Tasting Notes

  • Visual color description
  • Nose/aroma notes
  • Palate/taste notes
  • Finish notes
  • General tasting notes
  • Times tasted and last tasted date
  • Food pairings

6. Investment & Value Tracking

  • Current market value
  • Value gain/loss calculation
  • Investment bottle flag
  • Track ROI on your collection

7. Visual Documentation & Social

  • Bottle image URLs
  • Label image URLs
  • Receipt/proof of purchase images
  • For sale/trade flags
  • Asking price
  • Sharing history
  • Private notes

πŸ’° Pricing & Value Features

  • MSRP tracking with pre-populated prices for popular bottles
  • Secondary market prices based on 2025 market research
  • Purchase price tracking to monitor your actual investment
  • Automatic value calculations (MSRP Value = MSRP Γ— quantity)
  • Investment tracking with gain/loss monitoring

πŸ“ˆ Statistics Dashboard

Real-time collection statistics including:

  • Unique whiskeys count (distinct entries)
  • Total bottles count (sum of all quantities)
  • Total MSRP value (collection-wide, quantity-adjusted)
  • Total secondary market value (collection-wide, quantity-adjusted)
  • Average rating (out of 10)
  • Average age (years)
  • Average ABV (%)
  • Type breakdown with visual percentage bars showing distribution

πŸ“Š Advanced Analytics Dashboard (NEW!)

Comprehensive data visualization with interactive charts powered by Recharts:

  • Financial Overview: Total value, ROI, gain/loss tracking
  • Collection Composition: Pie charts for type distribution
  • Top 10 Most Valuable: Bar chart of highest-value bottles
  • Rating Distribution: Histogram of collection quality
  • Age Distribution: Bar chart showing whiskey age ranges
  • Best ROI: Investment performance tracking
  • Top Distilleries: Most represented producers
  • Value by Type: Total market value segmented by category
  • Inventory Status: Opened vs unopened, bottles running low
  • Special Items: Limited editions, single barrels, award winners
  • Tasting Stats: Tracking tasting notes and sessions

🎨 Modern Bootstrap UI

  • Responsive design works on mobile, tablet, and desktop
  • Bootstrap 5 for clean, professional styling
  • Dual view modes:
    • Table view: Sortable columns, easy scanning (default)
    • Card view: Visual browsing with detailed cards
  • Detail modal: Click any whiskey for complete information
  • Sortable columns: Click headers to sort by any field
  • Color-coded: Whiskey-themed blue (#5B9BD5)

πŸ‘₯ Admin Features

  • User management panel
    • View all users
    • Change user roles
    • Delete users
  • Global collection view
    • See all whiskeys from all users
    • Filter by specific user
    • Sort by any column
    • Track total collection statistics

πŸ€– AI-Powered Whiskey Lookup

  • Label scanning: Snap a photo of a bottle label to auto-fill all fields
  • Text lookup: Type a whiskey name to get structured data (distillery, region, ABV, tasting notes, etc.)
  • Three AI providers:
    • Anthropic Claude β€” cloud API, bring your own key (BYOK)
    • OpenAI β€” cloud API, BYOK
    • Ollama β€” fully local/offline, no API key required
  • Provider selection on Profile page with per-provider API key management
  • Ollama status indicator showing connection state and available models
  • Configurable Ollama models via OLLAMA_TEXT_MODEL and OLLAMA_VISION_MODEL environment variables

πŸ“„ Pagination

  • Server-side pagination on all whiskey list endpoints with configurable page size (10/25/50/100)
  • Pagination controls on Dashboard with First/Prev/Next/Last navigation and page number display
  • Pagination metadata returned in API responses (page, limit, total, totalPages)
  • Backward-compatible: responses without limit parameter return all results as before

πŸ” Search & Filter

  • Search by whiskey name
  • Filter by whiskey type
  • Filter by distillery
  • Sort by name, type, rating, age, ABV, and more
  • Paginated search results
  • Admin: Filter collections by user

🎲 Demo Data & Data Quality

  • Comprehensive demo seed: 6 diverse user profiles with 147 realistic whiskeys
  • Intelligent pricing: Automatic secondary market value calculation based on characteristics
  • Rating standardization: All ratings normalized to 2 decimal places
  • Duplicate detection: Automatic identification and smart replacement of duplicate bottles
  • User-specific replacements: Replacement bottles match user preferences and profiles
  • 80+ replacement pool: Extensive database of bourbon, scotch, Irish, Japanese, and rye whiskeys

πŸš€ Quick Start

Prerequisites

  • Node.js 18+ (LTS recommended)
  • npm 9+

Installation

# Clone the repository
git clone https://github.com/YOUR_USERNAME/whiskey-canon.git
cd whiskey-canon

# Install dependencies
npm install

# Initialize database with migrations
npm run db:migrate --workspace=backend

# Optional: Seed sample data
npm run db:seed --workspace=backend           # Bourbon data
npm run db:seed:scotch --workspace=backend    # Scotch data
npm run db:seed:irish --workspace=backend     # Irish whiskey data

# Optional: Populate pricing data
npm run db:update-msrp --workspace=backend       # Add MSRP prices
npm run db:update-secondary --workspace=backend  # Add secondary prices
npm run db:update-quantity --workspace=backend   # Set quantities to 1
npm run db:update-remaining --workspace=backend  # Update missing prices

# Optional: Create test users with collections
npm run db:seed:users --workspace=backend     # 4 basic test users

# Recommended: Create demo users with realistic collections
npm run seed:demo --workspace=backend         # 6 users with 10-40 whiskeys each (147 total)

Development

# Run both frontend and backend in development mode
npm run dev

# Or run them separately:
npm run dev:backend    # Backend runs on http://localhost:3000
npm run dev:frontend   # Frontend runs on http://localhost:5173

Visit http://localhost:5173 to view the application.

Production Build

# Build both frontend and backend
npm run build --workspace=backend
npm run build --workspace=frontend

# Start production backend
npm start --workspace=backend

πŸ“ Project Structure

whiskey-canon/
β”œβ”€β”€ backend/                    # Express backend
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ index.ts           # Server entry point
β”‚   β”‚   β”œβ”€β”€ routes/            # API routes
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.ts        # Authentication routes
β”‚   β”‚   β”‚   β”œβ”€β”€ whiskeys.ts    # Whiskey CRUD routes
β”‚   β”‚   β”‚   └── admin.ts       # Admin-only routes
β”‚   β”‚   β”œβ”€β”€ models/            # Data models
β”‚   β”‚   β”‚   β”œβ”€β”€ User.ts        # User model & CRUD
β”‚   β”‚   β”‚   └── Whiskey.ts     # Whiskey model & CRUD
β”‚   β”‚   β”œβ”€β”€ services/          # Business logic
β”‚   β”‚   β”‚   β”œβ”€β”€ whiskey-lookup.ts    # Anthropic Claude lookup
β”‚   β”‚   β”‚   β”œβ”€β”€ openai-lookup.ts     # OpenAI lookup
β”‚   β”‚   β”‚   β”œβ”€β”€ ollama-lookup.ts     # Ollama local lookup
β”‚   β”‚   β”‚   └── lookup-shared.ts     # Shared prompt & parser
β”‚   β”‚   β”œβ”€β”€ middleware/        # Express middleware
β”‚   β”‚   β”‚   β”œβ”€β”€ auth.ts        # Authentication middleware
β”‚   β”‚   β”‚   └── rbac.ts        # RBAC authorization
β”‚   β”‚   β”œβ”€β”€ types/             # TypeScript type definitions
β”‚   β”‚   β”‚   └── index.ts       # Shared types & enums
β”‚   β”‚   β”œβ”€β”€ seed-demo.ts       # Demo data with 6 users & 147 whiskeys
β”‚   β”‚   └── utils/             # Utilities
β”‚   β”‚       β”œβ”€β”€ database.ts    # Database init & migrations
β”‚   β”‚       β”œβ”€β”€ seed.ts        # Bourbon data seeding
β”‚   β”‚       β”œβ”€β”€ seed-scotch.ts # Scotch data seeding
β”‚   β”‚       β”œβ”€β”€ seed-irish.ts  # Irish data seeding
β”‚   β”‚       β”œβ”€β”€ seed-users.ts  # Test user creation
β”‚   β”‚       β”œβ”€β”€ update-msrp.ts        # MSRP price updates
β”‚   β”‚       β”œβ”€β”€ update-secondary.ts   # Secondary price updates (DEPRECATED - use update-secondary-prices.ts)
β”‚   β”‚       β”œβ”€β”€ update-secondary-prices.ts # Intelligent secondary pricing
β”‚   β”‚       β”œβ”€β”€ update-ratings.ts     # Standardize ratings to 2 decimals
β”‚   β”‚       β”œβ”€β”€ update-quantity.ts    # Quantity updates
β”‚   β”‚       β”œβ”€β”€ update-remaining-prices.ts
β”‚   β”‚       β”œβ”€β”€ remove-duplicates.ts  # Remove duplicate bottles from collections
β”‚   β”‚       β”œβ”€β”€ add-indexes.ts        # Add database indexes for performance
β”‚   β”‚       └── add-bourbons.ts       # Add 23 premium bourbons to collection
β”‚   └── whiskey.db             # SQLite database (auto-created)
β”‚
β”œβ”€β”€ frontend/                  # React frontend
β”‚   β”œβ”€β”€ src/
β”‚   β”‚   β”œβ”€β”€ App.tsx           # Main app component
β”‚   β”‚   β”œβ”€β”€ main.tsx          # Entry point
β”‚   β”‚   β”œβ”€β”€ components/       # React components
β”‚   β”‚   β”‚   β”œβ”€β”€ WhiskeyForm.tsx        # 7-tab whiskey form
β”‚   β”‚   β”‚   β”œβ”€β”€ WhiskeyTable.tsx       # Sortable table view
β”‚   β”‚   β”‚   β”œβ”€β”€ WhiskeyCard.tsx        # Card component
β”‚   β”‚   β”‚   β”œβ”€β”€ WhiskeyStats.tsx       # Statistics dashboard
β”‚   β”‚   β”‚   β”œβ”€β”€ WhiskeyDetailModal.tsx # Detail modal
β”‚   β”‚   β”‚   └── PrivateRoute.tsx       # Protected routes
β”‚   β”‚   β”œβ”€β”€ pages/            # Page components
β”‚   β”‚   β”‚   β”œβ”€β”€ LoginPage.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ RegisterPage.tsx
β”‚   β”‚   β”‚   β”œβ”€β”€ DashboardPage.tsx     # Main collection view
β”‚   β”‚   β”‚   └── AdminPage.tsx         # Admin panel
β”‚   β”‚   β”œβ”€β”€ context/          # React context
β”‚   β”‚   β”‚   └── AuthContext.tsx       # Auth state management
β”‚   β”‚   β”œβ”€β”€ services/         # API services
β”‚   β”‚   β”‚   └── api.ts                # API client
β”‚   β”‚   └── types/            # TypeScript types
β”‚   β”‚       └── index.ts              # Frontend types
β”‚   └── dist/                 # Production build output
β”‚
β”œβ”€β”€ DEPLOYMENT.md             # GCP Ubuntu deployment guide
β”œβ”€β”€ package.json              # Workspace configuration
└── README.md                 # This file

πŸ—ƒοΈ Database Schema

Users Table

CREATE TABLE users (
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  username TEXT UNIQUE NOT NULL,
  email TEXT UNIQUE NOT NULL,
  password TEXT NOT NULL,
  role TEXT NOT NULL CHECK(role IN ('admin', 'editor', 'viewer')),
  created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
  updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

Whiskeys Table (57 columns)

Core Fields:

  • id, name, type, distillery, region, country
  • age, abv, proof, size, quantity
  • rating, description, tasting_notes

Purchase & Pricing:

  • purchase_date, purchase_price, purchase_location, bottle_code
  • msrp, secondary_price

Inventory:

  • is_opened, date_opened, remaining_volume, storage_location, status

Production:

  • cask_type, cask_finish, barrel_number, bottle_number
  • vintage_year, bottled_date

Tasting:

  • color, nose_notes, palate_notes, finish_notes
  • times_tasted, last_tasted_date, food_pairings

Investment:

  • current_market_value, value_gain_loss, is_investment_bottle

Metadata:

  • mash_bill, awards, limited_edition, chill_filtered, natural_color

Media:

  • image_url, label_image_url, receipt_image_url

Social:

  • is_for_sale, asking_price, is_for_trade, shared_with, private_notes

System:

  • created_by (FOREIGN KEY β†’ users.id)
  • created_at, updated_at

πŸ”§ API Endpoints

Authentication

  • POST /api/auth/register - Register new user
  • POST /api/auth/login - Login
  • POST /api/auth/logout - Logout
  • GET /api/auth/me - Get current user
  • GET /api/auth/api-key?provider= - Check API key status for a provider
  • PUT /api/auth/api-key - Save an AI provider API key (validates with provider)
  • DELETE /api/auth/api-key?provider= - Delete an AI provider API key
  • PUT /api/auth/ai-provider - Set active AI provider (anthropic/openai/ollama)

Whiskeys (All require authentication)

  • GET /api/whiskeys?page=1&limit=25 - Get whiskeys with optional pagination (user's collection only)
  • GET /api/whiskeys/search?q=query&page=1&limit=25 - Search user's whiskeys with optional pagination
  • GET /api/whiskeys/:id - Get single whiskey (if owned by user)
  • POST /api/whiskeys - Create whiskey (Editor+ permission)
  • PUT /api/whiskeys/:id - Update whiskey (Editor+ permission, own whiskey only)
  • DELETE /api/whiskeys/:id - Delete whiskey (Editor+ permission, own whiskey only)
  • POST /api/whiskeys/lookup - AI whiskey lookup by name or label image
  • GET /api/whiskeys/ollama/status - Check Ollama availability and models

Admin (Require admin role)

  • GET /api/admin/users - Get all users
  • GET /api/admin/whiskeys?page=1&limit=25 - Get all whiskeys with owner information (supports pagination)
  • PUT /api/admin/users/:id/role - Update user role
  • DELETE /api/admin/users/:id - Delete user

🎯 Default Test Users

Basic Test Users (npm run db:seed:users)

Username Password Role Whiskeys
alice_admin password123 Admin 8
bob_editor password123 Editor 7
charlie_viewer password123 Viewer 8
diana_editor password123 Editor 6

Demo Users with Realistic Collections (npm run seed:demo)

Username Password Role Whiskeys Description
bourbon_lover demo123 Editor 26 American whiskey enthusiast
scotch_fan demo123 Editor 32 Scotch specialist with diverse regions
curator demo123 Admin 35 High-end collector across all types
beginner demo123 Viewer 13 Entry-level affordable bottles
investor demo123 Editor 24 Investment-grade bottles (unopened)
admin demo123 Admin 32 Extensive bourbon collection with premium bottles

Total Demo Whiskeys: 170 unique bottles with complete data (MSRP, secondary prices, ratings, etc.)

⚠️ IMPORTANT: Change these passwords in production!

🎯 Data Quality & Collection Management

Intelligent Secondary Pricing

The update-secondary-prices.ts script automatically calculates secondary market values based on whiskey characteristics:

  • Limited Edition/Investment Bottles: 1.5-2.0x MSRP
  • Aged 18+ Years: 1.3-1.6x MSRP
  • Highly Rated (9.0+): 1.4-1.7x MSRP
  • 12+ Years: 1.2-1.4x MSRP
  • Well-Rated (8.5+): 1.2-1.4x MSRP
  • Budget (<$40): 1.05-1.2x MSRP
  • Standard Bottles: 1.1-1.3x MSRP

This provides realistic market estimates for valuation and investment tracking.

Rating Standardization

All ratings are automatically standardized to exactly 2 decimal places for consistency across the database.

Duplicate Detection & Removal

The duplicate removal script:

  • Identifies duplicate bottles in each user's collection (same name + distillery)
  • Intelligently replaces duplicates based on user profile:
    • bourbon_lover: Gets bourbon/rye replacements
    • scotch_fan: Gets scotch/Irish replacements
    • investor: Gets high-value bottles (secondary >$100)
    • beginner: Gets affordable bottles (<$80)
    • curator/admin: Gets diverse mix across all types
  • Prevents creating new duplicates during replacement
  • Maintains collection size and user preferences

πŸ’» Database Management Scripts

# Database Migration
npm run db:migrate --workspace=backend

# Seed Whiskey Data
npm run db:seed --workspace=backend           # 10 popular bourbons
npm run db:seed:scotch --workspace=backend    # 10 popular scotches
npm run db:seed:irish --workspace=backend     # 10 popular Irish whiskeys

# Create Demo Users (RECOMMENDED)
npm run seed:demo --workspace=backend         # 6 diverse users with 170 whiskeys

# Create Basic Test Users
npm run db:seed:users --workspace=backend     # 4 basic test users

# Data Quality Scripts
npx tsx src/utils/update-secondary-prices.ts  # Intelligent secondary pricing based on characteristics
npx tsx src/utils/update-ratings.ts           # Standardize ratings to 2 decimal places
npx tsx src/utils/remove-duplicates.ts        # Remove duplicate bottles from collections
npx tsx src/utils/add-indexes.ts              # Add database indexes for performance optimization
npx tsx src/utils/add-bourbons.ts             # Add 23 premium bourbons to admin collection

# Legacy Pricing Scripts
npm run db:update-msrp --workspace=backend       # Add MSRP prices (legacy)
npm run db:update-secondary --workspace=backend  # Add secondary market prices (legacy)
npm run db:update-quantity --workspace=backend   # Set all quantities to 1
npm run db:update-remaining --workspace=backend  # Fill in missing prices

🌐 Deployment

See DEPLOYMENT.md for comprehensive deployment instructions to Google Cloud Platform (Ubuntu Server).

Quick Deployment Overview:

  1. Create GCP VM (Ubuntu 22.04 LTS, e2-small)
  2. Install dependencies (Node.js via nvm, Git, SQLite3)
  3. Clone and build the application
  4. Configure environment variables
  5. Run with PM2 for process management
  6. Setup Nginx as reverse proxy
  7. Enable SSL with Let's Encrypt
  8. Configure backups and monitoring

πŸ”’ Security Features

  • Password hashing with bcryptjs (salt rounds: 10)
  • Session management with express-session and secure httpOnly cookies
  • RBAC with permission-based middleware
  • User isolation - users can only access/modify their own whiskeys
  • Input validation with express-validator on all endpoints
  • SQL injection protection via parameterized queries
  • CORS configuration for credential handling
  • Foreign key constraints for referential integrity
  • CSRF protection via double-submit cookie pattern (csrf-csrf)
  • Helmet with strict CSP and HSTS headers
  • Rate limiting on auth, password reset, contact, and AI lookup endpoints
  • API key encryption β€” user-provided AI keys encrypted at rest with AES-256

πŸ› οΈ Technology Stack

Backend

  • Node.js - JavaScript runtime
  • Express - Web framework
  • TypeScript - Type safety
  • SQLite3 (better-sqlite3) - Embedded database
  • express-session - Session management
  • bcryptjs - Password hashing
  • express-validator - Request validation
  • cors - Cross-origin resource sharing
  • @anthropic-ai/sdk - Anthropic Claude API for AI whiskey lookup
  • openai - OpenAI API and Ollama-compatible local AI lookup

Frontend

  • React 18 - UI library
  • TypeScript - Type safety
  • Vite - Build tool and dev server
  • React Router - Client-side routing
  • Bootstrap 5 - CSS framework
  • Context API - State management

Development Tools

  • tsx - TypeScript execution
  • concurrently - Run multiple commands
  • Hot Module Replacement - Fast development iteration

πŸ“Š RBAC Permissions Matrix

Permission Admin Editor Viewer
Read whiskeys βœ“ βœ“ βœ“
Create whiskeys βœ“ βœ“ βœ—
Update whiskeys βœ“ βœ“ βœ—
Delete whiskeys βœ“ βœ— βœ—
Manage users βœ“ βœ— βœ—
View all collections βœ“ βœ— βœ—

Note: Users can only modify their own whiskeys, even with permissions.

πŸ“ˆ Statistics

  • 10+ interactive charts in the analytics dashboard (Recharts)
  • 11 database indexes for performance optimization (including created_at for pagination)
  • 57 database columns for comprehensive tracking
  • 41 new fields added beyond basic whiskey info
  • 7 organized tabs in the form interface
  • 170 demo whiskeys with complete data (MSRP, secondary prices, ratings)
  • 6 demo users with realistic collections (13-35 whiskeys each)
  • 80+ replacement bottles for duplicate removal across 5 whiskey types
  • 8 whiskey types supported (Bourbon, Scotch, Irish, Japanese, Rye, Tennessee, Canadian, Other)
  • 4 basic test users for quick testing
  • 3 user roles with granular permissions (Admin, Editor, Viewer)
  • Intelligent pricing algorithms based on 7 whiskey characteristics
  • 100% data quality: All ratings standardized to 2 decimals, no duplicates

πŸ“ Recent Updates

February 2026 - Collection-Wide Stats, Pagination & AI-Powered Whiskey Lookup

  • Collection-wide stats β€” MSRP Value and Secondary Value cards now show totals across the entire collection, not just the current page, with quantity-adjusted calculations
  • Unique Whiskeys vs Total Bottles β€” new "Total Bottles" card (sum of quantities) alongside renamed "Unique Whiskeys" card (distinct entries)
  • Server-side pagination β€” paginate whiskey lists with configurable page sizes and full navigation controls (#59)
  • AI label scanning & text lookup β€” snap a photo of a bottle label or type a name to auto-fill all 57 fields (#100)
  • Multi-provider support β€” choose between Anthropic Claude, OpenAI, or Ollama (local) as your AI provider (#126)
  • Ollama local AI β€” run whiskey lookups entirely offline using local models, no API key needed (#128)
  • BYOK (Bring Your Own Key) β€” save and manage API keys per provider on the Profile page with server-side encryption
  • Provider selection UI β€” toggle between providers with real-time Ollama status and model listing
  • Configurable models β€” set Ollama text/vision models via environment variables (defaults: llama3.1:8b, minicpm-v)

November 2024 - Analytics Dashboard & Performance Enhancements

Latest Updates (Nov 15, 2024)

  • Added 23 premium bourbons to admin collection (George T. Stagg, William Larue Weller, Booker's, etc.)
  • Fixed SQLite type compatibility issue preventing whiskey updates
  • Boolean values now properly converted to 0/1 for database storage
  • Admin collection expanded from 9 to 32 bourbons with realistic market data
  • Total demo collection now 170 whiskeys across all users

Analytics Dashboard (NEW!)

  • Complete analytics page with 10+ interactive charts using Recharts
  • Financial overview with ROI tracking and gain/loss visualization
  • Collection composition analysis (type, distillery, age distribution)
  • Performance metrics: Top 10 most valuable, best ROI bottles
  • Inventory insights: Opened/unopened status, bottles running low
  • Quality analytics: Rating distribution, highest rated bottles
  • Special items tracking: Limited editions, single barrels, award winners

Performance Optimization

  • Added 11 database indexes for faster queries on large collections
  • Indexed fields: user, type, rating, name, distillery, purchase_date, status, is_opened, created_at
  • Significant performance improvement for filtering, sorting, searching, and paginated queries
  • Login and user lookup optimizations with username and email indexes

Data Quality & Demo System

  • Added comprehensive demo seed script (seed-demo.ts) with 6 diverse user profiles
  • Created 170 realistic whiskeys across all major types
  • Each demo user has 13-35 whiskeys matching their profile

Data Quality Tools

  • update-secondary-prices.ts: Intelligent secondary pricing based on 7 characteristics
  • update-ratings.ts: Standardize all ratings to exactly 2 decimal places
  • remove-duplicates.ts: Smart duplicate detection and profile-based replacement
  • add-indexes.ts: Database performance optimization script
  • add-bourbons.ts: Populate collection with 23 premium bourbons

User Profiles

  • bourbon_lover: 26 American whiskeys (bourbon/rye focus)
  • scotch_fan: 32 Scotch whiskeys (diverse regions)
  • curator: 35 high-end bottles (all types)
  • beginner: 13 affordable entry-level bottles
  • investor: 24 investment-grade bottles (unopened, vault storage)
  • admin: 32 extensive bourbon collection (Buffalo Trace Antique Collection, premium barrels)

Pricing Algorithms

  • Limited edition/investment: 1.5-2.0x MSRP
  • Aged 18+ years: 1.3-1.6x MSRP
  • Highly rated (9.0+): 1.4-1.7x MSRP
  • Smart fallback strategies for all user types

Replacement Database

  • 20 bourbon replacements
  • 20 scotch replacements
  • 6 Irish whiskey replacements
  • 6 Japanese whiskey replacements
  • 3 rye replacements
  • Total: 80+ unique bottles for duplicate replacement

πŸ“Έ Screenshots

Dashboard & Collection Management

Main Dashboard - Table View

Dashboard Table View

The main collection view displays your whiskeys in a sortable table with comprehensive statistics including unique whiskey count, total bottle count, collection-wide MSRP and secondary market values, average rating, age, and ABV. View whiskey type breakdown with visual percentage bars.


Analytics Dashboard

The analytics dashboard provides deep insights into your collection across 5 comprehensive tabs.

Overview Tab

Analytics Overview

Financial overview showing total collection value, amount spent, and gain/loss. Includes inventory status visualization, bottle status tracking (opened vs unopened), and whiskey type distribution.

Financial Tab

Analytics Financial

Track your collection's financial performance with total MSRP and secondary market values. View your most valuable bottles and best return on investment performers.

Collection Tab

Analytics Collection

Analyze your collection composition with top distilleries by count, age distribution across different ranges, country distribution, and special/rare items tracking.

Quality Tab

Analytics Quality

Monitor collection quality with average, highest, and lowest ratings. View rating distribution histogram and list of highest-rated bottles.

Tasting Tab

Analytics Tasting

Track tasting experiences with statistics on tasting notes, food pairings, and detailed breakdowns of nose, palate, and finish notes.

Complete Analytics Dashboard

Full Analytics Dashboard

Comprehensive analytics overview showing all metrics and visualizations in a single view including collection composition pie chart, ROI analysis, age and rating distributions, top distilleries, inventory status, and value by type.


Admin Panel

User Management

Admin Panel

Admin users can manage all user accounts, view collection statistics across users (6 users with 170 total whiskeys), change user roles, and access all collections. Shows detailed user information including email, role, collection size, and creation date.


🀝 Contributing

This is a personal project, but suggestions and feedback are welcome!

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/amazing-feature)
  3. Commit your changes (git commit -m 'Add amazing feature')
  4. Push to the branch (git push origin feature/amazing-feature)
  5. Open a Pull Request

πŸ“ License

This project is licensed under the MIT License.

πŸ™ Acknowledgments

  • Whiskey pricing data sourced from market research (2025)
  • Built with modern web development best practices
  • Inspired by whiskey enthusiasts and collectors worldwide
  • Bootstrap 5 for beautiful, responsive UI

πŸ“§ Support

For questions or support, please open an issue on GitHub.


Whiskey Canon - Track, taste, and treasure your whiskey collection.

Built with TypeScript, React, Express, and a passion for fine spirits. πŸ₯ƒ

About

Whiskey collection cataloging and tasting notes

Resources

License

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors