Full-featured Ham Radio Logging Software with CAT control, UDP integrations, and CW keying.
- ✅ Full QSO logging with ADIF 3.x field support
- ✅ MySQL database (local and remote support)
- ✅ Modern web-based UI (React + TypeScript)
- ✅ QSO entry form with duplicate detection
- ✅ Logbook table with search and filters
- ✅ Station profile management
- ✅ Statistics dashboard
- ✅ RESTful API backend (FastAPI)
- 🔄 Phase 2: Callsign lookup (QRZ.com, HamQTH, callook.info)
- 🔄 Phase 3: CAT radio control (Hamlib, OmniRig, direct serial)
- Support for IC-7610, TS-590SG, KX3, and 200+ other radios
- 🔄 Phase 4: WSJT-X/JTDX integration via UDP
- 🔄 Phase 5: N1MM Logger+ and PSTRotator integration
- 🔄 Phase 6: Winkeyer CW keying support
- 🔄 Phase 7: ADIF import/export
- 🔄 Phase 8: Awards tracking (DXCC, WAS, grids)
- 🔄 Phase 9: Desktop application wrapper (PyWebView)
- Backend: Python 3.11+ with FastAPI
- Frontend: React 18 with TypeScript and TailwindCSS
- Database: MySQL 8.0+ (with SQLite fallback support)
- Build Tool: Vite
- ORM: SQLAlchemy with async support
- Python 3.11 or higher
- Node.js 18 or higher
- MySQL 8.0+ (already installed for Log4OM)
cd /path/to/your/projects
cd hamstack# Connect to MySQL
mysql -u root -p
# Run the initialization script
source database/init_mysql.sql
# Or manually create the database:
CREATE DATABASE hamstack CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;cd backend
# Create Python virtual environment
python -m venv venv
# Activate virtual environment
# On Windows:
venv\Scripts\activate
# On Linux/Mac:
source venv/bin/activate
# Install dependencies
pip install -r requirements.txt
# Create .env configuration file
copy .env.example .env # Windows
cp .env.example .env # Linux/Mac
# Edit .env file with your MySQL credentials
# Set your MySQL password and station callsign (W0NY)Important: Edit backend/.env and configure:
MYSQL_PASSWORD: Your MySQL root passwordSTATION_CALLSIGN: Your callsign (currently set to W0NY)- Other settings as needed
# Still in backend directory with venv activated
python -c "import asyncio; from app.database import init_db; asyncio.run(init_db())"cd ../frontend
# Install dependencies
npm installTerminal 1 - Backend:
cd backend
# Activate venv if not already activated
venv\Scripts\activate # Windows
source venv/bin/activate # Linux/Mac
# Start FastAPI server
python -m uvicorn app.main:app --reload --host 127.0.0.1 --port 8000Terminal 2 - Frontend:
cd frontend
# Start Vite dev server
npm run devAccess the application:
- Open your browser to
http://localhost:5173 - API documentation:
http://localhost:8000/docs
Coming soon in Phase 9 (Desktop wrapper with PyWebView).
-
Fill in the QSO entry form at the top:
- Callsign (required): Station worked
- Date/Time (required): When the contact occurred
- Frequency: Operating frequency in MHz
- Band: Select from common ham bands
- Mode: SSB, CW, FT8, etc.
- RST: Signal reports sent and received
- Name, QTH, Grid: Station information
- Comment: Additional notes
-
Click "Log QSO" to save
-
The QSO appears in the logbook table below
- All QSOs are displayed in the logbook table
- Sorted by date/time (most recent first)
- Click "Edit" to modify a QSO
- Click "Delete" to remove a QSO
- Click "Refresh" to reload the list
- Automatic duplicate checking when entering a callsign
- Shows a warning if the same call was worked recently (within 30 minutes)
- Checks callsign, band, and mode
hamstack/
├── backend/ # FastAPI Python backend
│ ├── app/
│ │ ├── models/ # SQLAlchemy database models
│ │ ├── api/ # API endpoints
│ │ ├── services/ # Business logic (CAT, UDP, etc.)
│ │ └── main.py # FastAPI app entry point
│ ├── requirements.txt
│ └── .env # Configuration (create from .env.example)
├── frontend/ # React TypeScript frontend
│ ├── src/
│ │ ├── components/ # React components
│ │ ├── services/ # API client
│ │ └── App.tsx # Main React app
│ └── package.json
├── database/ # Database scripts
│ └── init_mysql.sql
└── README.md
Once the backend is running, visit http://localhost:8000/docs for interactive API documentation (Swagger UI).
GET /api/qso/- List QSOs with filtersPOST /api/qso/- Create new QSOPUT /api/qso/{id}- Update QSODELETE /api/qso/{id}- Delete QSOGET /api/qso/stats/summary- Get statisticsGET /api/qso/duplicate-check/- Check for duplicatesGET /api/station/- Get station profilesGET /api/station/default- Get default station
Edit backend/.env:
STATION_CALLSIGN=W0NY
STATION_GRID=EN34
STATION_NAME=Your Name
STATION_QTH=Your CityCAT_BACKEND=hamlib
CAT_RADIO_MODEL=IC-7610
CAT_SERIAL_PORT=COM3
CAT_BAUD_RATE=19200WSJTX_ENABLED=true
WSJTX_UDP_PORT=2237
N1MM_ENABLED=false
N1MM_UDP_PORT=12060
PSTROTATOR_ENABLED=false
PSTROTATOR_UDP_PORT=12000cd backend
source venv/bin/activate
# Run tests
pytest
# Format code
black app/
# Type checking
mypy app/cd frontend
# Run dev server with hot reload
npm run dev
# Build for production
npm run build
# Preview production build
npm run preview- Check that MySQL is running
- Verify
.envfile has correct MySQL credentials - Ensure Python virtual environment is activated
- Check port 8000 is not in use
- Run
npm installto ensure dependencies are installed - Check that port 5173 is not in use
- Clear node_modules and reinstall if needed:
rm -rf node_modules && npm install
- Verify MySQL is running:
mysql -u root -p - Check database exists:
SHOW DATABASES; - Verify credentials in
.envmatch your MySQL setup
- Ensure backend is running on port 8000
- Check Vite proxy configuration in
frontend/vite.config.ts - Verify CORS settings in
backend/app/config.py
See the Features section above for the full roadmap through Phase 10.
HamStack is open source under the MIT license. Contributions are welcome!
MIT License - see LICENSE file for details.
Station W0NY
Built with ❤️ for the amateur radio community.
73 de W0NY
