Clean up and organize the flask-shopdb repository for better maintainability and discoverability: ## Changes - Update .gitignore for build artifacts (publish/, data/, 122M total) - Reorganize .claude/ into 6 subdirectories with README navigation - Consolidate overlapping MCP setup guides into MCP-QUICK-START.md - Move deployment docs from root to docs/deployment/ - Archive dated status reports to .claude/archived/ - Delete temporary files (logs, backups, empty reports, ~50K) ## New Structure .claude/ organized into: - setup/ - MCP, VM, Hyper-V, GitHub setup guides + scripts (17 files) - plans/ - Feature plans and protocols (5 files) - maintenance/ - Deployment checklists and reports (4 files) - archived/ - Historical documentation (9 files) - skills/ - Claude Code automation (5 files) - workflows/ - Security audit workflow (1 file) docs/deployment/ created with 6 deployment guides: - LOCAL-DEV-SETUP.md, DOCKER-SETUP.md, DOCKER-PREBUILT-APPROACH.md - PRODUCTION-READINESS.md, DEPLOY-TO-VM.md, README.md Root directory cleaned to essential docs only: - CLAUDE.md, README.md, CONTRIBUTING.md, CHANGELOG.md Benefits: - Clear navigation via README.md in each subdirectory - No duplicate/overlapping documentation - Large artifacts properly gitignored (won't bloat repository) - Historical context preserved in archived/ See .claude/CLEANUP-SUMMARY.md for complete details. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
10 KiB
ShopDB Local Development Setup (Windows)
Complete guide for setting up ShopDB Flask development environment on Windows.
Prerequisites
- Python 3.13+
- Docker Desktop (for MySQL and testing)
- Git
- Node.js 20+ (for frontend development)
Quick Start
# 1. Clone and enter repo
cd C:/Users/YOUR_USERNAME/Documents/github/flask-shopdb
# 2. Create Python virtual environment
python -m venv venv
./venv/Scripts/activate
pip install -r requirements.txt
# 3. Start MySQL in Docker
docker compose up -d db
# 4. Configure environment
cp .env.docker .env
# Edit .env and set DATABASE_URL (see below)
# 5. Install and enable plugins
export DATABASE_URL="mysql+pymysql://root:root-dev-password-not-for-production@localhost:3307/shopdb_flask_dev"
./venv/Scripts/flask.exe plugin install backups computers employees endpoints geenforce guides knowledgebase machines measuringtools network notifications printedparts printers slides tools usb warranty
./venv/Scripts/flask.exe plugin enable <each-plugin-name>
# 6. Start Flask
./venv/Scripts/python.exe run_dev.py
Visit http://localhost:5001 and login with admin / admin.
Detailed Setup
1. Database Setup
MySQL runs in Docker on port 3307 (not 3306) to avoid conflicts with any local MySQL instance.
# Start MySQL container
docker compose up -d db
# Verify it's running
docker ps --filter name=shopdb-dev-db
# Should show: 127.0.0.1:3307->3306/tcp
# Test connection
docker exec shopdb-dev-db mysql -u root -p'root-dev-password-not-for-production' -e "SELECT 1;"
2. Environment Configuration
Create .env file with:
# Database (port 3307 because Docker maps it there)
DATABASE_URL=mysql+pymysql://root:root-dev-password-not-for-production@localhost:3307/shopdb_flask_dev
# Flask
FLASK_ENV=development
FLASK_DEBUG=1
# Secrets (dev only)
SECRET_KEY=docker-dev-secret-key-change-for-production
JWT_SECRET_KEY=docker-dev-jwt-secret-change-for-production
# CORS
CORS_ORIGINS=http://localhost:5173,http://localhost:5001
# API Port
API_PORT=5001
# ShopDB Label
SHOPDB_ENV_LABEL=LOCAL-DEV
# Log Level
LOG_LEVEL=DEBUG
# Backup Storage (for local dev)
SHOPDB_BACKUPS_ROOT=C:/Users/YOUR_USERNAME/Documents/github/flask-shopdb/backups
Important: Change YOUR_USERNAME to your actual Windows username.
3. Import Database (Optional)
If you have a production database dump:
# Import latest.sql
docker exec -i shopdb-dev-db mysql -u root -p'root-dev-password-not-for-production' shopdb_flask_dev < latest.sql
# Run migrations
export DATABASE_URL="mysql+pymysql://root:root-dev-password-not-for-production@localhost:3307/shopdb_flask_dev"
./venv/Scripts/flask.exe db upgrade
4. Plugin Installation
All 17 plugins must be installed before they can be enabled:
# Set DATABASE_URL for CLI commands
export DATABASE_URL="mysql+pymysql://root:root-dev-password-not-for-production@localhost:3307/shopdb_flask_dev"
# Install all plugins
for plugin in backups computers employees endpoints geenforce guides knowledgebase machines measuringtools network notifications printedparts printers slides tools usb warranty; do
./venv/Scripts/flask.exe plugin install $plugin
done
# Enable all plugins
for plugin in backups computers employees endpoints geenforce guides knowledgebase machines measuringtools network notifications printedparts printers slides tools usb warranty; do
./venv/Scripts/flask.exe plugin enable $plugin
done
Why this is necessary:
- Plugin state is tracked in
instance/plugins.json, not the database - When you import a prod database, it has plugin tables but no plugin registry
- Installing registers plugins in the JSON file
- Enabling makes them active (but requires app restart)
5. Reset Admin Password
If you imported a prod database and don't know the password:
# Generate new password hash
./venv/Scripts/python.exe -c "from werkzeug.security import generate_password_hash; print(generate_password_hash('admin'))"
# Reset via MySQL
docker exec shopdb-dev-db mysql -u root -p'root-dev-password-not-for-production' shopdb_flask_dev -e "
UPDATE users
SET passwordhash = 'PASTE_HASH_HERE',
failedlogins = 0,
lockeduntil = NULL
WHERE username = 'admin';
"
Or use the simpler method:
docker exec shopdb-dev-db mysql -u root -p'root-dev-password-not-for-production' shopdb_flask_dev -e "
UPDATE users
SET passwordhash = 'scrypt:32768:8:1\$B4LhpPrM6qxijInK\$b99b47a0bb5fd45761a1823f401f70a3ceccf71a5d38dc433378aa07426ef8eaf7e679ff3dd7b0ce9772600f83368ac642e9419b9beaa49f87483318bae34547',
failedlogins = 0,
lockeduntil = NULL
WHERE username = 'admin';
"
Password is now: admin / admin
6. Starting Flask
Always use run_dev.py (not flask run directly):
./venv/Scripts/python.exe run_dev.py
This script:
- Loads
.envfile with DATABASE_URL - Sets all environment variables
- Starts Flask without auto-reloader (prevents env var loss)
- Binds to 0.0.0.0:5001
Do NOT use:
flask run- Won't load.envproperlyflask run --reload- Loses environment variables
7. Frontend Development (Optional)
To develop the Vue frontend:
cd frontend
npm ci
npm run dev
Frontend dev server runs on http://localhost:5173 and proxies API requests to Flask on port 5001.
For production build (served by Flask):
cd frontend
npm run build
# Outputs to frontend/dist/
Troubleshooting
"Can't connect to MySQL on 127.0.0.1:3306"
Cause: Flask is trying port 3306 instead of 3307.
Fix:
- Make sure
.envhasDATABASE_URL=...@localhost:3307/... - Use
run_dev.pyto start Flask (NOTflask run) - If problem persists, restart Flask completely
"Cannot import name '_backups_configured'"
Cause: Merge conflict between wj and wilm backup implementations.
Fix: This was fixed in commit 8a1fe0ada8 - pull latest wj branch.
"Plugin X is not installed"
Cause: Plugin registry (instance/plugins.json) doesn't exist or is incomplete.
Fix: Run plugin installation commands (section 4 above).
"Access is denied: '/backups'"
Cause: Backup system trying to use Linux path on Windows.
Fix:
- Add to
.env:SHOPDB_BACKUPS_ROOT=C:/Users/YOUR_USERNAME/Documents/github/flask-shopdb/backups - Create directory:
mkdir backups - Restart Flask with
run_dev.py
Docker npm install fails (Zscaler proxy)
Cause: Corporate proxy intercepts HTTPS, npm doesn't trust certificate.
Fix: Extract Zscaler root CA certificate:
# Run this PowerShell script
$request = [System.Net.HttpWebRequest]::Create('https://registry.npmjs.org/')
$request.Method = 'HEAD'
$request.Timeout = 10000
$response = $request.GetResponse()
$root = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($request.ServicePoint.Certificate)
$builder = [System.Text.StringBuilder]::new()
[void]$builder.AppendLine('-----BEGIN CERTIFICATE-----')
[void]$builder.AppendLine([System.Convert]::ToBase64String($root.RawData, 'InsertLineBreaks'))
[void]$builder.AppendLine('-----END CERTIFICATE-----')
Set-Content -Path 'C:\Users\270015376\Documents\github\flask-shopdb\corp-root-ca.pem' -Value $builder.ToString() -Encoding ASCII
Then rebuild Docker: docker compose build --no-cache
Common Tasks
Run Tests
pytest
pytest tests/test_specific.py
pytest -v -s # Verbose with print output
Run Migrations
export DATABASE_URL="mysql+pymysql://root:root-dev-password-not-for-production@localhost:3307/shopdb_flask_dev"
./venv/Scripts/flask.exe db upgrade
Create Migration
./venv/Scripts/flask.exe db migrate -m "Description of changes"
Check Plugin Status
./venv/Scripts/flask.exe plugin list
Enable/Disable Plugin
./venv/Scripts/flask.exe plugin enable slides
./venv/Scripts/flask.exe plugin disable slides
Trigger Backup
# Via API (requires admin JWT token)
curl -X POST http://localhost:5001/api/shopdbbackups \
-H "Authorization: Bearer YOUR_TOKEN"
# Or via Docker
docker compose -f docker-compose.backup.yml up backup
Architecture Notes
Why Port 3307?
Docker MySQL maps internal port 3306 to host port 3307 to avoid conflicts with any local MySQL installation. This is configured in docker-compose.yml:
ports:
- "127.0.0.1:3307:3306"
Why run_dev.py?
Flask's flask run command uses an auto-reloader that spawns a subprocess. This subprocess loses environment variables loaded from .env. The run_dev.py wrapper:
- Loads
.envvia python-dotenv BEFORE importing Flask - Uses
--no-reloadflag to prevent subprocess spawning - Ensures DATABASE_URL and other vars persist
Plugin Architecture
- Plugins are Python packages in
plugins/directory - Plugin state tracked in
instance/plugins.json(not database) - Plugin tables tracked via Alembic migration chains
- Each plugin has own migrations in
plugins/<name>/migrations/
Backup System
- Designed for Docker compose deployment
- API queues backups via sentinel file (
.backup-requested) - Actual backup execution requires Docker sidecar container
- On Windows dev, API can queue but won't execute without Docker
File Structure
flask-shopdb/
|-- .env # Local environment config (gitignored)
|-- run_dev.py # Local development launcher
|-- shopdb/ # Flask application
| |-- __init__.py # App factory
| |-- config.py # Configuration classes
| |-- core/ # Core models and APIs
| +-- plugins/ # Plugin manager
|-- plugins/ # Plugin packages
| |-- backups/
| |-- computers/
| +-- ...
|-- frontend/ # Vue 3 SPA
| |-- src/
| +-- dist/ # Production build (gitignored)
|-- instance/ # Runtime state (gitignored)
| |-- plugins.json # Plugin registry
| +-- ...
|-- migrations/ # Core Alembic migrations
|-- scripts/ # Deployment and backup scripts
|-- backups/ # Local backup storage (gitignored)
+-- tests/ # Test suite
Git Workflow
mainbranch - Published/public version (GitHub)wjbranch - Production deployment (West Jefferson site)wilmbranch - Development branch (upstream from benjamin.baker)devbranch - Ops deployment branch
Never commit to main directly - it's published to public wiki.
Additional Resources
- Backup Setup
- Plugin Development
- ADRs
- API Docs (when Flask is running)