Latest commit

History

2,921 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenHamClock

A real-time amateur radio dashboard for the modern operator.

OpenHamClock brings DX cluster spots, space weather, propagation predictions, POTA/SOTA/WWFF/WWBOTA activations, PSKReporter, satellite tracking, WSJT-X integration, direct rig control, an in-browser logbook, and a full emergency-communications mode into a single browser-based interface. Run it locally on a Raspberry Pi, on your desktop, in Docker, or just use the hosted site.

🌐 Live Site:openhamclock.com

📧 Contact: Chris, K0CJH — chris@cjhlighting.com

☕ Support the Project:buymeacoffee.com/k0cjh — Running openhamclock.com comes with real hosting costs including network egress, memory, CPU, and the time spent maintaining and improving the project. There is absolutely no obligation to donate — OpenHamClock is and always will be free. But if you find it useful and want to chip in, your donations are greatly appreciated and go directly toward keeping the site running and funding future development.

🔧 Get Involved: This is an open-source project and the amateur radio community is encouraged to dig into the code, fork it, and build the features you want to see. Whether it's a new panel, a data source integration, or a bug fix — PRs are welcome. See Contributing below.

📝 License: MIT — See LICENSE


Documentation

GuideWhat's in it
Quick StartUse the hosted site, or self-host on Docker, Linux/macOS, Raspberry Pi, Windows, Railway
User ManualEvery panel, map layer, keyboard shortcut, and setting explained
Docker GuideCompose, Portainer, persistence, reverse proxies
RoadmapProject history and what's coming
ContributingDev setup, code style, PR workflow
TestingUnit test guide
Security PolicyVulnerability disclosure
ArchitectureCodebase map for contributors

Release notes live in the app itself: click the version number in the header to open What's New.


Feature Highlights

  • Interactive world map in three projections — flat (Mercator), azimuthal-equidistant centered on your QTH, and a full 3D globe with real satellite models — with a dozen basemap styles and ~28 toggleable overlay layers (gray line, aurora, MUF, D-RAP, lightning, satellites, RBN, WSPR, Maidenhead grid, CQ/ITU zones, aircraft, and more), most with single-key shortcuts.
  • DX cluster spots from OpenHamClock's own cluster node (RBN + HamQTH + POTA/SOTA/WWFF + user spots, deduplicated), with band/mode/zone/watchlist filtering, worked-before and dupe badges from your log, click-to-tune, and click-to-listen via the nearest live KiwiSDR.
  • Activations — live POTA, SOTA, WWFF, and WWBOTA activator panels with map markers.
  • Native logbook — QSOs stored in your browser (IndexedDB), ADIF import/export, log-from-spot, and worked-before integration across all spot panels.
  • Propagation — browser-side ITU-R P.533-14 (VOACAP-class) predictions via WebAssembly, point-to-point reliability charts, world heatmap, MUF map, band conditions, and ionosonde-corrected real-time data.
  • Space weather — SFI/Kp/SSN with history, GOES X-ray flux, NOAA SWPC alerts, aurora forecast, solar imagery, lunar phase.
  • Satellite tracking — SGP4 tracking of amateur satellites from CelesTrak/AMSAT/SatNOGS (optionally Space-Track), orbit tracks, footprints, pass info, and 3D models on the globe.
  • Rig control — click any spot and your radio tunes, via the Rig Bridge (Yaesu, Kenwood, Icom, Elecraft, FlexRadio, flrig, rigctld, and more) with a cloud relay for hosted use.
  • Digital modes — WSJT-X/JTDX decodes on the map (UDP or cloud relay), JS8Call/MSHV control, PSKReporter TX/RX reports in real time.
  • Contest tools — contest calendar, N1MM+/DXLog QSOs plotted live on the map, band plan overlay on the rig display.
  • EmComm layout — ARES/RACES dashboard with APRS (internet + RF via local TNC), net roster, point-to-point messaging, resource token aggregation, telemetry dashboards, NWS alerts, FEMA shelters and disaster declarations, Winlink gateways and Pat client.
  • Meshtastic & MeshCom — mesh network nodes and messages on the map and in dockable panels.
  • Works your way — dockable drag-anywhere layout, Classic (original HamClock style), and EmComm layouts; five themes including a custom theme editor; named profiles; 16 languages; PWA offline mode with cached data.

Quick Start

Just want to use it? Open openhamclock.com, set your callsign and grid, done.

Self-host with Docker:

docker run -d -p 3000:3000 --name openhamclock ghcr.io/accius/openhamclock:latest

Self-host from source (Node.js 22 LTS recommended):

git clone https://github.com/accius/openhamclock.git
cd openhamclock
npm ci
npm start

Open http://localhost:3000. A setup wizard walks you through callsign and grid on first run.

One-line installers for Linux/macOS (scripts/setup.sh), Raspberry Pi kiosk (scripts/setup-pi.sh), and Windows (scripts/setup-windows.ps1) — full commands and per-platform details in the Quick Start guide.

For development with hot reload:

# Terminal 1 — Backend (http://localhost:3001)
node server.js
# Terminal 2 — Frontend (hot reload on http://localhost:3000)
npm run dev

Deployment Matrix

PlatformMethodGuide
Nothing (hosted)openhamclock.comQuick Start
Docker / Portainerdocker compose up -d or ghcr.io/accius/openhamclock:latestdocs/DOCKER.md
Linux / macOS / FreeBSDscripts/setup.sh (add --service for systemd on Linux)Quick Start
Raspberry Pi (3B–5)scripts/setup-pi.sh (--kiosk for a dedicated display)Quick Start
Windowsscripts/setup-windows.ps1Quick Start
Railway (cloud)railway up or connect the GitHub repoQuick Start
Desktop appnpm run electron (experimental)

Hardware: the server side is light (~100–150 MB RAM); it's the browser rendering the map that works a machine. A Pi 4 (2 GB+) or Pi 5 makes a smooth kiosk; a Pi 3B+ is best as a headless server or with Low Memory Mode enabled in Settings. The 3D globe wants WebGL — without it the app falls back to the flat map automatically.


Configuration

All configuration lives in .env (auto-created from .env.example on first run) — and almost everything can also be changed in the in-app Settings panel, which takes priority. The only two lines most people touch:

CALLSIGN=K0CJH
LOCATOR=EN10

Files starting with a dot are hidden by default — ls -la in a terminal, Ctrl+H in a Linux file manager, Cmd+Shift+. in macOS Finder.

Settings priority: browser Settings panel (localStorage) → .env → built-in defaults. Your .env is never overwritten by updates. Self-hosted single-operator installs can set SETTINGS_SYNC=true to store UI settings on the server so every device gets the same setup.

Common variables

The complete annotated list lives in .env.example. Highlights:

VariableDefaultDescription
CALLSIGNN0CALLYour callsign — used for DX cluster login, PSKReporter queries, and "my spots" tracking
LOCATORFN31Maidenhead grid (4 or 6 characters); LATITUDE/LONGITUDE override the derived coordinates
PORT3001 (dev)Backend port. Containers run on 3000; in dev, Vite owns 3000 and proxies /api to 3001
HOSTlocalhostSet 0.0.0.0 to allow other devices on your LAN
THEME / LAYOUTdark / modernStartup theme (dark, light, legacy, retro) and layout (modern, classic)
DISTUNITS / TEMPUNITS / PRESSUNITSimperialDistance, temperature, and pressure units (imperial or metric); UNITS is deprecated
TIME_FORMAT1212 or 24 hour clock
SETTINGS_SYNCfalseStore all UI settings server-side (single-operator self-host only)
WSJTX_ENABLEDtrueWSJT-X/JTDX UDP listener (legacy name WSJTX_UDP_ENABLED still honored)
WSJTX_UDP_PORT2237Must match WSJT-X Settings → Reporting → UDP Server
WSJTX_MULTICAST_ADDRESS(none)Set when WSJT-X broadcasts to a multicast group (e.g. 224.0.0.1)
WSJTX_RELAY_KEY(none)Shared secret for the WSJT-X relay agent (cloud deployments only)
AUTO_UPDATE_ENABLEDfalsePeriodic git self-update (legacy name AUTO_UPDATE still honored)
AUTO_UPDATE_INTERVAL_MINUTES60Update check interval (legacy name AUTO_UPDATE_INTERVAL still honored)
DX_CLUSTER_SOURCEautoauto, proxy, hamqth, or dxspider; see the manual
DX_CLUSTER_CALLSIGNCALLSIGN-56Cluster login (use -57 for a second/staging instance)
SPOT_RETENTION_MINUTES30How long DX spots stay in the list (5–30)
APRS_ENABLEDfalseRead-only APRS-IS feed; filter with APRS_FILTER (e.g. r/40.12/-74.82/500)
N1MM_UDP_ENABLEDfalseContest logger UDP listener on N1MM_UDP_PORT (12060) — see docs/N1MM-SETUP.md
QRZ_USERNAME/QRZ_PASSWORD, HAMQTH_USERNAME/HAMQTH_PASSWORD(none)Optional callbook credentials for better callsign lookups
OPENWEATHER_API_KEY(none)Only needed for the Cloud Layer map overlay (also set VITE_OPENWEATHER_API_KEY)
API_WRITE_KEY(none)Protects write endpoints — required for public/cloud deployments
METRICS_AUTH_KEY(none)Bearer-token auth for the Prometheus /metrics endpoint
CELESTRAK_ENABLED / AMSAT_TLE_ENABLED / SATNOGS_TLE_ENABLEDtrueSatellite element-set sources; SPACE_TRACK_USERNAME/_PASSWORD enable Space-Track as primary
ITURHFPROP_URL(built-in)External ITU-R P.533 service — only if self-hosting iturhfprop-service/
WINLINK_API_KEY(none)Winlink gateway proxy (cloud deployments; local installs use the rig-bridge plugin instead)

API Overview

The backend exposes a JSON REST API under /api, heavily cached server-side to be kind to upstream services. Notable endpoints:

EndpointDescription
GET /api/config, GET /api/versionStation config and lightweight version check (drives the update toast)
GET /api/healthLive server dashboard — uptime, visitors, sessions, per-endpoint traffic (?format=json for raw data)
GET /api/dxcluster/spots, /paths, /sourcesDX cluster spots, map paths, and available source backends
POST /api/dxcluster/spotSubmit a spot to the OHC cluster
GET /api/pota/spots, /api/sota/spots, /api/wwff/spotsActivator spots (1–2 min cache)
GET /api/solar-indices, /api/noaa/xray, /api/noaa/aurora, /api/drap, /api/swpc/alertsSpace weather feeds
GET /api/n0nbhN0NBH band conditions
GET /api/propagation, /heatmap, /mufmapPoint-to-point prediction, world heatmap, MUF map
GET /api/p533-data/:fileITU-R P.533 coefficient tables for the in-browser WASM engine
GET /api/satellites/dataMerged satellite element sets (CelesTrak / AMSAT / SatNOGS / Space-Track)
GET /api/callsign/:call, /api/ctyCallsign lookup and the AD1C cty.dat prefix database
GET /api/rbn/spots, /api/wspr/heatmapReverse Beacon Network spots and WSPR heatmap
GET /api/pskreporter/stream/:idLive PSKReporter spots over SSE (server-side MQTT proxy)
GET /api/wsjtx/decodes, POST /api/wsjtx/relayWSJT-X decodes and the cloud relay ingest
GET /api/contests, /api/dxpeditions, /api/dxnewsContest calendar, DXpeditions, DX news
GET/POST /api/contest/qsosN1MM/DXLog contest QSOs (UDP-fed, plus HTTP ingest)
GET /api/aprs/stations, /messages, /telemetry, /netAPRS stations, messaging, telemetry, net roster
GET /api/emcomm/alerts, /shelters, /disastersNWS alerts, FEMA shelters and disaster declarations
GET /api/winlink/gatewaysWinlink RMS gateways (needs WINLINK_API_KEY server-side)
GET /api/websdr/receiversNearest live KiwiSDR/WebSDR receivers for click-to-listen
GET /api/aircraft, /api/atc/sectorsADS-B aircraft (adsb.lol) and ATC sector boundaries
GET /metricsPrometheus metrics (optionally gated by METRICS_AUTH_KEY)

Write endpoints (settings, rig, rotator, spot submission, etc.) are rate-limited and honor API_WRITE_KEY when set.


Architecture

React 18 + Vite frontend, Express backend. The backend is an API proxy and data aggregator — external calls are cached server-side so any number of browsers add near-zero upstream load. Real-time data flows over SSE (DX cluster, PSKReporter, RBN), UDP (WSJT-X, N1MM), and a server-side MQTT proxy.

Companion services in this repo:

DirectoryService
rig-bridge/Local rig control bridge — 20+ plugins (radios, digital modes, APRS TNC, rotator, Winlink)
ohc-cluster/OpenHamClock's own DX cluster node (telnet :7300 + HTTP), aggregating RBN, HamQTH, POTA/SOTA/WWFF, Parks n Peaks, DX Summit, and user spots
dxspider-proxy/Persistent telnet connection to the DX Spider network, served over HTTP
iturhfprop-service/ITU-R P.533-14 propagation engine as a REST API (self-host alternative)
wasm-build/Builds the P.533 engine to WebAssembly for in-browser predictions
wsjtx-relay/WSJT-X UDP → HTTPS relay for cloud-hosted instances
fletcher/TLE fetch egress proxy used by the hosted deployment
watchtower/Cloudflare Worker uptime probe

Full codebase map: docs/ARCHITECTURE.md


Updating

  • Hosted site — nothing to do; a toast appears when a new version deploys.
  • Git installs./scripts/update.sh (Linux/macOS/Pi) or .\scripts\update.ps1 (Windows), then restart. Local installs also get an UPDATE button in the header. Optional auto-update via AUTO_UPDATE_ENABLED=true.
  • Dockerdocker compose pull && docker compose up -d.
  • Railway — push to the connected repo, or railway up.

The update scripts back up .env, pull, rebuild, and restore .env — your configuration is never lost.


FAQ

Do I need a license to use OpenHamClock? No — it's a receive-only dashboard. A callsign makes PSKReporter "my signal" views and cluster login meaningful, but anyone can watch spots and space weather.

Can multiple people use one server? Yes. Each browser keeps its own settings, filters, and DX target; the server cache means extra users add no upstream load. Shared-station operators can use Profiles (Settings → Profiles) to switch setups.

Why don't I see DX spots / PSK reports? Make sure your callsign is set. PSKReporter falls back from the live stream to HTTP automatically; check the panel footer for the active method. For clusters, check the server console and any custom DXSPIDER_PROXY_URL.

Emoji show as boxes on Linux/Pi? Install a color emoji font on the machine running the browser: sudo apt install fonts-noto-color-emoji, then restart the browser. The Pi setup script does this automatically.

Where's the .env file? In the repo root, hidden by the leading dot — ls -la shows it. Run npm start once and it's created from .env.example automatically.

More Q&A throughout the User Manual.


Monitoring

OpenHamClock exposes a Prometheus-compatible endpoint at /metrics (optionally protected with METRICS_AUTH_KEY as a bearer token) and a human-friendly health dashboard at /api/health.


Contributing

OpenHamClock is built by the ham radio community — 40+ contributors and growing. Whether it's a bug fix, a new panel, a map layer plugin, or better docs, PRs are welcome.

git clone https://github.com/accius/openhamclock.git
cd openhamclock
git checkout Staging
npm ci
node server.js # Terminal 1 — Backend on :3001
npm run dev # Terminal 2 — Frontend on :3000

Open pull requests against Staging, not main. Read CONTRIBUTING.md for the workflow, code style, and the documentation policy, and docs/ARCHITECTURE.md for the codebase map.

Community:


Credits

  • K0CJH (Chris Hetherington) — Creator and maintainer — chris@cjhlighting.com
  • Elwood Downey, WB0OEW (SK) — Creator of the original HamClock that inspired this project. OpenHamClock is dedicated to his memory.
  • Claude AI (Anthropic) — Accelerated development by assisting with bug fixes, code structure, and feature implementation
  • Keith, G6NHU — DX Spider cluster operator at dxspider.co.uk
  • NOAA Space Weather Prediction Center — Space weather data (SFI, Kp, SSN, X-ray flux, aurora, D-RAP)
  • N0NBH (Paul Herrman) — Real-time band conditions data feed
  • POTA / SOTA / WWFF / WWBOTA — Activator spot APIs
  • PSKReporter — Digital mode reception report network
  • Reverse Beacon Network — CW/RTTY/FT skimmer spots
  • Open-Meteo — Free weather API
  • Leaflet — Open-source mapping library
  • CelesTrak · AMSAT · SatNOGS — Satellite orbital element data
  • NASA — Imagery, EONET hazards data, and the ISS 3D model (NASA/VTAD)
  • KC2G / GIRO — Ionospheric sounding data (acknowledgements)
  • AD1C — cty.dat DXCC entity database
  • NG3K — DXpedition listing
  • DXNews.com / DX-World — DX news headlines
  • WA7BNM — Contest calendar data
  • adsb.lol — Community ADS-B aircraft feed

And thank you to every contributor — the full wall lives in the app under Settings → Community.


License

MIT License — See LICENSE file.


73 de K0CJH openhamclock.com · chris@cjhlighting.com

About

"The original HamClock will cease to function in June 2026. OpenHamClock aims to carry on Elwood's legacy with a modern, open-source implementation that the community can maintain and improve together."

Resources

Code of conduct

Contributing

Security policy

Stars

462 stars

Watchers

19 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Latest commit

History

2,921 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenHamClock

A real-time amateur radio dashboard for the modern operator.

OpenHamClock brings DX cluster spots, space weather, propagation predictions, POTA/SOTA/WWFF/WWBOTA activations, PSKReporter, satellite tracking, WSJT-X integration, direct rig control, an in-browser logbook, and a full emergency-communications mode into a single browser-based interface. Run it locally on a Raspberry Pi, on your desktop, in Docker, or just use the hosted site.

🌐 Live Site:openhamclock.com

📧 Contact: Chris, K0CJH — chris@cjhlighting.com

☕ Support the Project:buymeacoffee.com/k0cjh — Running openhamclock.com comes with real hosting costs including network egress, memory, CPU, and the time spent maintaining and improving the project. There is absolutely no obligation to donate — OpenHamClock is and always will be free. But if you find it useful and want to chip in, your donations are greatly appreciated and go directly toward keeping the site running and funding future development.

🔧 Get Involved: This is an open-source project and the amateur radio community is encouraged to dig into the code, fork it, and build the features you want to see. Whether it's a new panel, a data source integration, or a bug fix — PRs are welcome. See Contributing below.

📝 License: MIT — See LICENSE


Documentation

GuideWhat's in it
Quick StartUse the hosted site, or self-host on Docker, Linux/macOS, Raspberry Pi, Windows, Railway
User ManualEvery panel, map layer, keyboard shortcut, and setting explained
Docker GuideCompose, Portainer, persistence, reverse proxies
RoadmapProject history and what's coming
ContributingDev setup, code style, PR workflow
TestingUnit test guide
Security PolicyVulnerability disclosure
ArchitectureCodebase map for contributors

Release notes live in the app itself: click the version number in the header to open What's New.


Feature Highlights

  • Interactive world map in three projections — flat (Mercator), azimuthal-equidistant centered on your QTH, and a full 3D globe with real satellite models — with a dozen basemap styles and ~28 toggleable overlay layers (gray line, aurora, MUF, D-RAP, lightning, satellites, RBN, WSPR, Maidenhead grid, CQ/ITU zones, aircraft, and more), most with single-key shortcuts.
  • DX cluster spots from OpenHamClock's own cluster node (RBN + HamQTH + POTA/SOTA/WWFF + user spots, deduplicated), with band/mode/zone/watchlist filtering, worked-before and dupe badges from your log, click-to-tune, and click-to-listen via the nearest live KiwiSDR.
  • Activations — live POTA, SOTA, WWFF, and WWBOTA activator panels with map markers.
  • Native logbook — QSOs stored in your browser (IndexedDB), ADIF import/export, log-from-spot, and worked-before integration across all spot panels.
  • Propagation — browser-side ITU-R P.533-14 (VOACAP-class) predictions via WebAssembly, point-to-point reliability charts, world heatmap, MUF map, band conditions, and ionosonde-corrected real-time data.
  • Space weather — SFI/Kp/SSN with history, GOES X-ray flux, NOAA SWPC alerts, aurora forecast, solar imagery, lunar phase.
  • Satellite tracking — SGP4 tracking of amateur satellites from CelesTrak/AMSAT/SatNOGS (optionally Space-Track), orbit tracks, footprints, pass info, and 3D models on the globe.
  • Rig control — click any spot and your radio tunes, via the Rig Bridge (Yaesu, Kenwood, Icom, Elecraft, FlexRadio, flrig, rigctld, and more) with a cloud relay for hosted use.
  • Digital modes — WSJT-X/JTDX decodes on the map (UDP or cloud relay), JS8Call/MSHV control, PSKReporter TX/RX reports in real time.
  • Contest tools — contest calendar, N1MM+/DXLog QSOs plotted live on the map, band plan overlay on the rig display.
  • EmComm layout — ARES/RACES dashboard with APRS (internet + RF via local TNC), net roster, point-to-point messaging, resource token aggregation, telemetry dashboards, NWS alerts, FEMA shelters and disaster declarations, Winlink gateways and Pat client.
  • Meshtastic & MeshCom — mesh network nodes and messages on the map and in dockable panels.
  • Works your way — dockable drag-anywhere layout, Classic (original HamClock style), and EmComm layouts; five themes including a custom theme editor; named profiles; 16 languages; PWA offline mode with cached data.

Quick Start

Just want to use it? Open openhamclock.com, set your callsign and grid, done.

Self-host with Docker:

docker run -d -p 3000:3000 --name openhamclock ghcr.io/accius/openhamclock:latest

Self-host from source (Node.js 22 LTS recommended):

git clone https://github.com/accius/openhamclock.git
cd openhamclock
npm ci
npm start

Open http://localhost:3000. A setup wizard walks you through callsign and grid on first run.

One-line installers for Linux/macOS (scripts/setup.sh), Raspberry Pi kiosk (scripts/setup-pi.sh), and Windows (scripts/setup-windows.ps1) — full commands and per-platform details in the Quick Start guide.

For development with hot reload:

# Terminal 1 — Backend (http://localhost:3001)
node server.js
# Terminal 2 — Frontend (hot reload on http://localhost:3000)
npm run dev

Deployment Matrix

PlatformMethodGuide
Nothing (hosted)openhamclock.comQuick Start
Docker / Portainerdocker compose up -d or ghcr.io/accius/openhamclock:latestdocs/DOCKER.md
Linux / macOS / FreeBSDscripts/setup.sh (add --service for systemd on Linux)Quick Start
Raspberry Pi (3B–5)scripts/setup-pi.sh (--kiosk for a dedicated display)Quick Start
Windowsscripts/setup-windows.ps1Quick Start
Railway (cloud)railway up or connect the GitHub repoQuick Start
Desktop appnpm run electron (experimental)

Hardware: the server side is light (~100–150 MB RAM); it's the browser rendering the map that works a machine. A Pi 4 (2 GB+) or Pi 5 makes a smooth kiosk; a Pi 3B+ is best as a headless server or with Low Memory Mode enabled in Settings. The 3D globe wants WebGL — without it the app falls back to the flat map automatically.


Configuration

All configuration lives in .env (auto-created from .env.example on first run) — and almost everything can also be changed in the in-app Settings panel, which takes priority. The only two lines most people touch:

CALLSIGN=K0CJH
LOCATOR=EN10

Files starting with a dot are hidden by default — ls -la in a terminal, Ctrl+H in a Linux file manager, Cmd+Shift+. in macOS Finder.

Settings priority: browser Settings panel (localStorage) → .env → built-in defaults. Your .env is never overwritten by updates. Self-hosted single-operator installs can set SETTINGS_SYNC=true to store UI settings on the server so every device gets the same setup.

Common variables

The complete annotated list lives in .env.example. Highlights:

VariableDefaultDescription
CALLSIGNN0CALLYour callsign — used for DX cluster login, PSKReporter queries, and "my spots" tracking
LOCATORFN31Maidenhead grid (4 or 6 characters); LATITUDE/LONGITUDE override the derived coordinates
PORT3001 (dev)Backend port. Containers run on 3000; in dev, Vite owns 3000 and proxies /api to 3001
HOSTlocalhostSet 0.0.0.0 to allow other devices on your LAN
THEME / LAYOUTdark / modernStartup theme (dark, light, legacy, retro) and layout (modern, classic)
DISTUNITS / TEMPUNITS / PRESSUNITSimperialDistance, temperature, and pressure units (imperial or metric); UNITS is deprecated
TIME_FORMAT1212 or 24 hour clock
SETTINGS_SYNCfalseStore all UI settings server-side (single-operator self-host only)
WSJTX_ENABLEDtrueWSJT-X/JTDX UDP listener (legacy name WSJTX_UDP_ENABLED still honored)
WSJTX_UDP_PORT2237Must match WSJT-X Settings → Reporting → UDP Server
WSJTX_MULTICAST_ADDRESS(none)Set when WSJT-X broadcasts to a multicast group (e.g. 224.0.0.1)
WSJTX_RELAY_KEY(none)Shared secret for the WSJT-X relay agent (cloud deployments only)
AUTO_UPDATE_ENABLEDfalsePeriodic git self-update (legacy name AUTO_UPDATE still honored)
AUTO_UPDATE_INTERVAL_MINUTES60Update check interval (legacy name AUTO_UPDATE_INTERVAL still honored)
DX_CLUSTER_SOURCEautoauto, proxy, hamqth, or dxspider; see the manual
DX_CLUSTER_CALLSIGNCALLSIGN-56Cluster login (use -57 for a second/staging instance)
SPOT_RETENTION_MINUTES30How long DX spots stay in the list (5–30)
APRS_ENABLEDfalseRead-only APRS-IS feed; filter with APRS_FILTER (e.g. r/40.12/-74.82/500)
N1MM_UDP_ENABLEDfalseContest logger UDP listener on N1MM_UDP_PORT (12060) — see docs/N1MM-SETUP.md
QRZ_USERNAME/QRZ_PASSWORD, HAMQTH_USERNAME/HAMQTH_PASSWORD(none)Optional callbook credentials for better callsign lookups
OPENWEATHER_API_KEY(none)Only needed for the Cloud Layer map overlay (also set VITE_OPENWEATHER_API_KEY)
API_WRITE_KEY(none)Protects write endpoints — required for public/cloud deployments
METRICS_AUTH_KEY(none)Bearer-token auth for the Prometheus /metrics endpoint
CELESTRAK_ENABLED / AMSAT_TLE_ENABLED / SATNOGS_TLE_ENABLEDtrueSatellite element-set sources; SPACE_TRACK_USERNAME/_PASSWORD enable Space-Track as primary
ITURHFPROP_URL(built-in)External ITU-R P.533 service — only if self-hosting iturhfprop-service/
WINLINK_API_KEY(none)Winlink gateway proxy (cloud deployments; local installs use the rig-bridge plugin instead)

API Overview

The backend exposes a JSON REST API under /api, heavily cached server-side to be kind to upstream services. Notable endpoints:

EndpointDescription
GET /api/config, GET /api/versionStation config and lightweight version check (drives the update toast)
GET /api/healthLive server dashboard — uptime, visitors, sessions, per-endpoint traffic (?format=json for raw data)
GET /api/dxcluster/spots, /paths, /sourcesDX cluster spots, map paths, and available source backends
POST /api/dxcluster/spotSubmit a spot to the OHC cluster
GET /api/pota/spots, /api/sota/spots, /api/wwff/spotsActivator spots (1–2 min cache)
GET /api/solar-indices, /api/noaa/xray, /api/noaa/aurora, /api/drap, /api/swpc/alertsSpace weather feeds
GET /api/n0nbhN0NBH band conditions
GET /api/propagation, /heatmap, /mufmapPoint-to-point prediction, world heatmap, MUF map
GET /api/p533-data/:fileITU-R P.533 coefficient tables for the in-browser WASM engine
GET /api/satellites/dataMerged satellite element sets (CelesTrak / AMSAT / SatNOGS / Space-Track)
GET /api/callsign/:call, /api/ctyCallsign lookup and the AD1C cty.dat prefix database
GET /api/rbn/spots, /api/wspr/heatmapReverse Beacon Network spots and WSPR heatmap
GET /api/pskreporter/stream/:idLive PSKReporter spots over SSE (server-side MQTT proxy)
GET /api/wsjtx/decodes, POST /api/wsjtx/relayWSJT-X decodes and the cloud relay ingest
GET /api/contests, /api/dxpeditions, /api/dxnewsContest calendar, DXpeditions, DX news
GET/POST /api/contest/qsosN1MM/DXLog contest QSOs (UDP-fed, plus HTTP ingest)
GET /api/aprs/stations, /messages, /telemetry, /netAPRS stations, messaging, telemetry, net roster
GET /api/emcomm/alerts, /shelters, /disastersNWS alerts, FEMA shelters and disaster declarations
GET /api/winlink/gatewaysWinlink RMS gateways (needs WINLINK_API_KEY server-side)
GET /api/websdr/receiversNearest live KiwiSDR/WebSDR receivers for click-to-listen
GET /api/aircraft, /api/atc/sectorsADS-B aircraft (adsb.lol) and ATC sector boundaries
GET /metricsPrometheus metrics (optionally gated by METRICS_AUTH_KEY)

Write endpoints (settings, rig, rotator, spot submission, etc.) are rate-limited and honor API_WRITE_KEY when set.


Architecture

React 18 + Vite frontend, Express backend. The backend is an API proxy and data aggregator — external calls are cached server-side so any number of browsers add near-zero upstream load. Real-time data flows over SSE (DX cluster, PSKReporter, RBN), UDP (WSJT-X, N1MM), and a server-side MQTT proxy.

Companion services in this repo:

DirectoryService
rig-bridge/Local rig control bridge — 20+ plugins (radios, digital modes, APRS TNC, rotator, Winlink)
ohc-cluster/OpenHamClock's own DX cluster node (telnet :7300 + HTTP), aggregating RBN, HamQTH, POTA/SOTA/WWFF, Parks n Peaks, DX Summit, and user spots
dxspider-proxy/Persistent telnet connection to the DX Spider network, served over HTTP
iturhfprop-service/ITU-R P.533-14 propagation engine as a REST API (self-host alternative)
wasm-build/Builds the P.533 engine to WebAssembly for in-browser predictions
wsjtx-relay/WSJT-X UDP → HTTPS relay for cloud-hosted instances
fletcher/TLE fetch egress proxy used by the hosted deployment
watchtower/Cloudflare Worker uptime probe

Full codebase map: docs/ARCHITECTURE.md


Updating

  • Hosted site — nothing to do; a toast appears when a new version deploys.
  • Git installs./scripts/update.sh (Linux/macOS/Pi) or .\scripts\update.ps1 (Windows), then restart. Local installs also get an UPDATE button in the header. Optional auto-update via AUTO_UPDATE_ENABLED=true.
  • Dockerdocker compose pull && docker compose up -d.
  • Railway — push to the connected repo, or railway up.

The update scripts back up .env, pull, rebuild, and restore .env — your configuration is never lost.


FAQ

Do I need a license to use OpenHamClock? No — it's a receive-only dashboard. A callsign makes PSKReporter "my signal" views and cluster login meaningful, but anyone can watch spots and space weather.

Can multiple people use one server? Yes. Each browser keeps its own settings, filters, and DX target; the server cache means extra users add no upstream load. Shared-station operators can use Profiles (Settings → Profiles) to switch setups.

Why don't I see DX spots / PSK reports? Make sure your callsign is set. PSKReporter falls back from the live stream to HTTP automatically; check the panel footer for the active method. For clusters, check the server console and any custom DXSPIDER_PROXY_URL.

Emoji show as boxes on Linux/Pi? Install a color emoji font on the machine running the browser: sudo apt install fonts-noto-color-emoji, then restart the browser. The Pi setup script does this automatically.

Where's the .env file? In the repo root, hidden by the leading dot — ls -la shows it. Run npm start once and it's created from .env.example automatically.

More Q&A throughout the User Manual.


Monitoring

OpenHamClock exposes a Prometheus-compatible endpoint at /metrics (optionally protected with METRICS_AUTH_KEY as a bearer token) and a human-friendly health dashboard at /api/health.


Contributing

OpenHamClock is built by the ham radio community — 40+ contributors and growing. Whether it's a bug fix, a new panel, a map layer plugin, or better docs, PRs are welcome.

git clone https://github.com/accius/openhamclock.git
cd openhamclock
git checkout Staging
npm ci
node server.js # Terminal 1 — Backend on :3001
npm run dev # Terminal 2 — Frontend on :3000

Open pull requests against Staging, not main. Read CONTRIBUTING.md for the workflow, code style, and the documentation policy, and docs/ARCHITECTURE.md for the codebase map.

Community:


Credits

  • K0CJH (Chris Hetherington) — Creator and maintainer — chris@cjhlighting.com
  • Elwood Downey, WB0OEW (SK) — Creator of the original HamClock that inspired this project. OpenHamClock is dedicated to his memory.
  • Claude AI (Anthropic) — Accelerated development by assisting with bug fixes, code structure, and feature implementation
  • Keith, G6NHU — DX Spider cluster operator at dxspider.co.uk
  • NOAA Space Weather Prediction Center — Space weather data (SFI, Kp, SSN, X-ray flux, aurora, D-RAP)
  • N0NBH (Paul Herrman) — Real-time band conditions data feed
  • POTA / SOTA / WWFF / WWBOTA — Activator spot APIs
  • PSKReporter — Digital mode reception report network
  • Reverse Beacon Network — CW/RTTY/FT skimmer spots
  • Open-Meteo — Free weather API
  • Leaflet — Open-source mapping library
  • CelesTrak · AMSAT · SatNOGS — Satellite orbital element data
  • NASA — Imagery, EONET hazards data, and the ISS 3D model (NASA/VTAD)
  • KC2G / GIRO — Ionospheric sounding data (acknowledgements)
  • AD1C — cty.dat DXCC entity database
  • NG3K — DXpedition listing
  • DXNews.com / DX-World — DX news headlines
  • WA7BNM — Contest calendar data
  • adsb.lol — Community ADS-B aircraft feed

And thank you to every contributor — the full wall lives in the app under Settings → Community.


License

MIT License — See LICENSE file.


73 de K0CJH openhamclock.com · chris@cjhlighting.com

About

"The original HamClock will cease to function in June 2026. OpenHamClock aims to carry on Elwood's legacy with a modern, open-source implementation that the community can maintain and improve together."

Resources

Code of conduct

Contributing

Security policy

Stars

462 stars

Watchers

19 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

2,921 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenHamClock

A real-time amateur radio dashboard for the modern operator.

OpenHamClock brings DX cluster spots, space weather, propagation predictions, POTA/SOTA/WWFF/WWBOTA activations, PSKReporter, satellite tracking, WSJT-X integration, direct rig control, an in-browser logbook, and a full emergency-communications mode into a single browser-based interface. Run it locally on a Raspberry Pi, on your desktop, in Docker, or just use the hosted site.

🌐 Live Site:openhamclock.com

📧 Contact: Chris, K0CJH — chris@cjhlighting.com

☕ Support the Project:buymeacoffee.com/k0cjh — Running openhamclock.com comes with real hosting costs including network egress, memory, CPU, and the time spent maintaining and improving the project. There is absolutely no obligation to donate — OpenHamClock is and always will be free. But if you find it useful and want to chip in, your donations are greatly appreciated and go directly toward keeping the site running and funding future development.

🔧 Get Involved: This is an open-source project and the amateur radio community is encouraged to dig into the code, fork it, and build the features you want to see. Whether it's a new panel, a data source integration, or a bug fix — PRs are welcome. See Contributing below.

📝 License: MIT — See LICENSE


Documentation

GuideWhat's in it
Quick StartUse the hosted site, or self-host on Docker, Linux/macOS, Raspberry Pi, Windows, Railway
User ManualEvery panel, map layer, keyboard shortcut, and setting explained
Docker GuideCompose, Portainer, persistence, reverse proxies
RoadmapProject history and what's coming
ContributingDev setup, code style, PR workflow
TestingUnit test guide
Security PolicyVulnerability disclosure
ArchitectureCodebase map for contributors

Release notes live in the app itself: click the version number in the header to open What's New.


Feature Highlights

  • Interactive world map in three projections — flat (Mercator), azimuthal-equidistant centered on your QTH, and a full 3D globe with real satellite models — with a dozen basemap styles and ~28 toggleable overlay layers (gray line, aurora, MUF, D-RAP, lightning, satellites, RBN, WSPR, Maidenhead grid, CQ/ITU zones, aircraft, and more), most with single-key shortcuts.
  • DX cluster spots from OpenHamClock's own cluster node (RBN + HamQTH + POTA/SOTA/WWFF + user spots, deduplicated), with band/mode/zone/watchlist filtering, worked-before and dupe badges from your log, click-to-tune, and click-to-listen via the nearest live KiwiSDR.
  • Activations — live POTA, SOTA, WWFF, and WWBOTA activator panels with map markers.
  • Native logbook — QSOs stored in your browser (IndexedDB), ADIF import/export, log-from-spot, and worked-before integration across all spot panels.
  • Propagation — browser-side ITU-R P.533-14 (VOACAP-class) predictions via WebAssembly, point-to-point reliability charts, world heatmap, MUF map, band conditions, and ionosonde-corrected real-time data.
  • Space weather — SFI/Kp/SSN with history, GOES X-ray flux, NOAA SWPC alerts, aurora forecast, solar imagery, lunar phase.
  • Satellite tracking — SGP4 tracking of amateur satellites from CelesTrak/AMSAT/SatNOGS (optionally Space-Track), orbit tracks, footprints, pass info, and 3D models on the globe.
  • Rig control — click any spot and your radio tunes, via the Rig Bridge (Yaesu, Kenwood, Icom, Elecraft, FlexRadio, flrig, rigctld, and more) with a cloud relay for hosted use.
  • Digital modes — WSJT-X/JTDX decodes on the map (UDP or cloud relay), JS8Call/MSHV control, PSKReporter TX/RX reports in real time.
  • Contest tools — contest calendar, N1MM+/DXLog QSOs plotted live on the map, band plan overlay on the rig display.
  • EmComm layout — ARES/RACES dashboard with APRS (internet + RF via local TNC), net roster, point-to-point messaging, resource token aggregation, telemetry dashboards, NWS alerts, FEMA shelters and disaster declarations, Winlink gateways and Pat client.
  • Meshtastic & MeshCom — mesh network nodes and messages on the map and in dockable panels.
  • Works your way — dockable drag-anywhere layout, Classic (original HamClock style), and EmComm layouts; five themes including a custom theme editor; named profiles; 16 languages; PWA offline mode with cached data.

Quick Start

Just want to use it? Open openhamclock.com, set your callsign and grid, done.

Self-host with Docker:

docker run -d -p 3000:3000 --name openhamclock ghcr.io/accius/openhamclock:latest

Self-host from source (Node.js 22 LTS recommended):

git clone https://github.com/accius/openhamclock.git
cd openhamclock
npm ci
npm start

Open http://localhost:3000. A setup wizard walks you through callsign and grid on first run.

One-line installers for Linux/macOS (scripts/setup.sh), Raspberry Pi kiosk (scripts/setup-pi.sh), and Windows (scripts/setup-windows.ps1) — full commands and per-platform details in the Quick Start guide.

For development with hot reload:

# Terminal 1 — Backend (http://localhost:3001)
node server.js
# Terminal 2 — Frontend (hot reload on http://localhost:3000)
npm run dev

Deployment Matrix

PlatformMethodGuide
Nothing (hosted)openhamclock.comQuick Start
Docker / Portainerdocker compose up -d or ghcr.io/accius/openhamclock:latestdocs/DOCKER.md
Linux / macOS / FreeBSDscripts/setup.sh (add --service for systemd on Linux)Quick Start
Raspberry Pi (3B–5)scripts/setup-pi.sh (--kiosk for a dedicated display)Quick Start
Windowsscripts/setup-windows.ps1Quick Start
Railway (cloud)railway up or connect the GitHub repoQuick Start
Desktop appnpm run electron (experimental)

Hardware: the server side is light (~100–150 MB RAM); it's the browser rendering the map that works a machine. A Pi 4 (2 GB+) or Pi 5 makes a smooth kiosk; a Pi 3B+ is best as a headless server or with Low Memory Mode enabled in Settings. The 3D globe wants WebGL — without it the app falls back to the flat map automatically.


Configuration

All configuration lives in .env (auto-created from .env.example on first run) — and almost everything can also be changed in the in-app Settings panel, which takes priority. The only two lines most people touch:

CALLSIGN=K0CJH
LOCATOR=EN10

Files starting with a dot are hidden by default — ls -la in a terminal, Ctrl+H in a Linux file manager, Cmd+Shift+. in macOS Finder.

Settings priority: browser Settings panel (localStorage) → .env → built-in defaults. Your .env is never overwritten by updates. Self-hosted single-operator installs can set SETTINGS_SYNC=true to store UI settings on the server so every device gets the same setup.

Common variables

The complete annotated list lives in .env.example. Highlights:

VariableDefaultDescription
CALLSIGNN0CALLYour callsign — used for DX cluster login, PSKReporter queries, and "my spots" tracking
LOCATORFN31Maidenhead grid (4 or 6 characters); LATITUDE/LONGITUDE override the derived coordinates
PORT3001 (dev)Backend port. Containers run on 3000; in dev, Vite owns 3000 and proxies /api to 3001
HOSTlocalhostSet 0.0.0.0 to allow other devices on your LAN
THEME / LAYOUTdark / modernStartup theme (dark, light, legacy, retro) and layout (modern, classic)
DISTUNITS / TEMPUNITS / PRESSUNITSimperialDistance, temperature, and pressure units (imperial or metric); UNITS is deprecated
TIME_FORMAT1212 or 24 hour clock
SETTINGS_SYNCfalseStore all UI settings server-side (single-operator self-host only)
WSJTX_ENABLEDtrueWSJT-X/JTDX UDP listener (legacy name WSJTX_UDP_ENABLED still honored)
WSJTX_UDP_PORT2237Must match WSJT-X Settings → Reporting → UDP Server
WSJTX_MULTICAST_ADDRESS(none)Set when WSJT-X broadcasts to a multicast group (e.g. 224.0.0.1)
WSJTX_RELAY_KEY(none)Shared secret for the WSJT-X relay agent (cloud deployments only)
AUTO_UPDATE_ENABLEDfalsePeriodic git self-update (legacy name AUTO_UPDATE still honored)
AUTO_UPDATE_INTERVAL_MINUTES60Update check interval (legacy name AUTO_UPDATE_INTERVAL still honored)
DX_CLUSTER_SOURCEautoauto, proxy, hamqth, or dxspider; see the manual
DX_CLUSTER_CALLSIGNCALLSIGN-56Cluster login (use -57 for a second/staging instance)
SPOT_RETENTION_MINUTES30How long DX spots stay in the list (5–30)
APRS_ENABLEDfalseRead-only APRS-IS feed; filter with APRS_FILTER (e.g. r/40.12/-74.82/500)
N1MM_UDP_ENABLEDfalseContest logger UDP listener on N1MM_UDP_PORT (12060) — see docs/N1MM-SETUP.md
QRZ_USERNAME/QRZ_PASSWORD, HAMQTH_USERNAME/HAMQTH_PASSWORD(none)Optional callbook credentials for better callsign lookups
OPENWEATHER_API_KEY(none)Only needed for the Cloud Layer map overlay (also set VITE_OPENWEATHER_API_KEY)
API_WRITE_KEY(none)Protects write endpoints — required for public/cloud deployments
METRICS_AUTH_KEY(none)Bearer-token auth for the Prometheus /metrics endpoint
CELESTRAK_ENABLED / AMSAT_TLE_ENABLED / SATNOGS_TLE_ENABLEDtrueSatellite element-set sources; SPACE_TRACK_USERNAME/_PASSWORD enable Space-Track as primary
ITURHFPROP_URL(built-in)External ITU-R P.533 service — only if self-hosting iturhfprop-service/
WINLINK_API_KEY(none)Winlink gateway proxy (cloud deployments; local installs use the rig-bridge plugin instead)

API Overview

The backend exposes a JSON REST API under /api, heavily cached server-side to be kind to upstream services. Notable endpoints:

EndpointDescription
GET /api/config, GET /api/versionStation config and lightweight version check (drives the update toast)
GET /api/healthLive server dashboard — uptime, visitors, sessions, per-endpoint traffic (?format=json for raw data)
GET /api/dxcluster/spots, /paths, /sourcesDX cluster spots, map paths, and available source backends
POST /api/dxcluster/spotSubmit a spot to the OHC cluster
GET /api/pota/spots, /api/sota/spots, /api/wwff/spotsActivator spots (1–2 min cache)
GET /api/solar-indices, /api/noaa/xray, /api/noaa/aurora, /api/drap, /api/swpc/alertsSpace weather feeds
GET /api/n0nbhN0NBH band conditions
GET /api/propagation, /heatmap, /mufmapPoint-to-point prediction, world heatmap, MUF map
GET /api/p533-data/:fileITU-R P.533 coefficient tables for the in-browser WASM engine
GET /api/satellites/dataMerged satellite element sets (CelesTrak / AMSAT / SatNOGS / Space-Track)
GET /api/callsign/:call, /api/ctyCallsign lookup and the AD1C cty.dat prefix database
GET /api/rbn/spots, /api/wspr/heatmapReverse Beacon Network spots and WSPR heatmap
GET /api/pskreporter/stream/:idLive PSKReporter spots over SSE (server-side MQTT proxy)
GET /api/wsjtx/decodes, POST /api/wsjtx/relayWSJT-X decodes and the cloud relay ingest
GET /api/contests, /api/dxpeditions, /api/dxnewsContest calendar, DXpeditions, DX news
GET/POST /api/contest/qsosN1MM/DXLog contest QSOs (UDP-fed, plus HTTP ingest)
GET /api/aprs/stations, /messages, /telemetry, /netAPRS stations, messaging, telemetry, net roster
GET /api/emcomm/alerts, /shelters, /disastersNWS alerts, FEMA shelters and disaster declarations
GET /api/winlink/gatewaysWinlink RMS gateways (needs WINLINK_API_KEY server-side)
GET /api/websdr/receiversNearest live KiwiSDR/WebSDR receivers for click-to-listen
GET /api/aircraft, /api/atc/sectorsADS-B aircraft (adsb.lol) and ATC sector boundaries
GET /metricsPrometheus metrics (optionally gated by METRICS_AUTH_KEY)

Write endpoints (settings, rig, rotator, spot submission, etc.) are rate-limited and honor API_WRITE_KEY when set.


Architecture

React 18 + Vite frontend, Express backend. The backend is an API proxy and data aggregator — external calls are cached server-side so any number of browsers add near-zero upstream load. Real-time data flows over SSE (DX cluster, PSKReporter, RBN), UDP (WSJT-X, N1MM), and a server-side MQTT proxy.

Companion services in this repo:

DirectoryService
rig-bridge/Local rig control bridge — 20+ plugins (radios, digital modes, APRS TNC, rotator, Winlink)
ohc-cluster/OpenHamClock's own DX cluster node (telnet :7300 + HTTP), aggregating RBN, HamQTH, POTA/SOTA/WWFF, Parks n Peaks, DX Summit, and user spots
dxspider-proxy/Persistent telnet connection to the DX Spider network, served over HTTP
iturhfprop-service/ITU-R P.533-14 propagation engine as a REST API (self-host alternative)
wasm-build/Builds the P.533 engine to WebAssembly for in-browser predictions
wsjtx-relay/WSJT-X UDP → HTTPS relay for cloud-hosted instances
fletcher/TLE fetch egress proxy used by the hosted deployment
watchtower/Cloudflare Worker uptime probe

Full codebase map: docs/ARCHITECTURE.md


Updating

  • Hosted site — nothing to do; a toast appears when a new version deploys.
  • Git installs./scripts/update.sh (Linux/macOS/Pi) or .\scripts\update.ps1 (Windows), then restart. Local installs also get an UPDATE button in the header. Optional auto-update via AUTO_UPDATE_ENABLED=true.
  • Dockerdocker compose pull && docker compose up -d.
  • Railway — push to the connected repo, or railway up.

The update scripts back up .env, pull, rebuild, and restore .env — your configuration is never lost.


FAQ

Do I need a license to use OpenHamClock? No — it's a receive-only dashboard. A callsign makes PSKReporter "my signal" views and cluster login meaningful, but anyone can watch spots and space weather.

Can multiple people use one server? Yes. Each browser keeps its own settings, filters, and DX target; the server cache means extra users add no upstream load. Shared-station operators can use Profiles (Settings → Profiles) to switch setups.

Why don't I see DX spots / PSK reports? Make sure your callsign is set. PSKReporter falls back from the live stream to HTTP automatically; check the panel footer for the active method. For clusters, check the server console and any custom DXSPIDER_PROXY_URL.

Emoji show as boxes on Linux/Pi? Install a color emoji font on the machine running the browser: sudo apt install fonts-noto-color-emoji, then restart the browser. The Pi setup script does this automatically.

Where's the .env file? In the repo root, hidden by the leading dot — ls -la shows it. Run npm start once and it's created from .env.example automatically.

More Q&A throughout the User Manual.


Monitoring

OpenHamClock exposes a Prometheus-compatible endpoint at /metrics (optionally protected with METRICS_AUTH_KEY as a bearer token) and a human-friendly health dashboard at /api/health.


Contributing

OpenHamClock is built by the ham radio community — 40+ contributors and growing. Whether it's a bug fix, a new panel, a map layer plugin, or better docs, PRs are welcome.

git clone https://github.com/accius/openhamclock.git
cd openhamclock
git checkout Staging
npm ci
node server.js # Terminal 1 — Backend on :3001
npm run dev # Terminal 2 — Frontend on :3000

Open pull requests against Staging, not main. Read CONTRIBUTING.md for the workflow, code style, and the documentation policy, and docs/ARCHITECTURE.md for the codebase map.

Community:


Credits

  • K0CJH (Chris Hetherington) — Creator and maintainer — chris@cjhlighting.com
  • Elwood Downey, WB0OEW (SK) — Creator of the original HamClock that inspired this project. OpenHamClock is dedicated to his memory.
  • Claude AI (Anthropic) — Accelerated development by assisting with bug fixes, code structure, and feature implementation
  • Keith, G6NHU — DX Spider cluster operator at dxspider.co.uk
  • NOAA Space Weather Prediction Center — Space weather data (SFI, Kp, SSN, X-ray flux, aurora, D-RAP)
  • N0NBH (Paul Herrman) — Real-time band conditions data feed
  • POTA / SOTA / WWFF / WWBOTA — Activator spot APIs
  • PSKReporter — Digital mode reception report network
  • Reverse Beacon Network — CW/RTTY/FT skimmer spots
  • Open-Meteo — Free weather API
  • Leaflet — Open-source mapping library
  • CelesTrak · AMSAT · SatNOGS — Satellite orbital element data
  • NASA — Imagery, EONET hazards data, and the ISS 3D model (NASA/VTAD)
  • KC2G / GIRO — Ionospheric sounding data (acknowledgements)
  • AD1C — cty.dat DXCC entity database
  • NG3K — DXpedition listing
  • DXNews.com / DX-World — DX news headlines
  • WA7BNM — Contest calendar data
  • adsb.lol — Community ADS-B aircraft feed

And thank you to every contributor — the full wall lives in the app under Settings → Community.


License

MIT License — See LICENSE file.


73 de K0CJH openhamclock.com · chris@cjhlighting.com

About

"The original HamClock will cease to function in June 2026. OpenHamClock aims to carry on Elwood's legacy with a modern, open-source implementation that the community can maintain and improve together."

Resources

Code of conduct

Contributing

Security policy

Stars

462 stars

Watchers

19 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

2,921 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenHamClock

A real-time amateur radio dashboard for the modern operator.

OpenHamClock brings DX cluster spots, space weather, propagation predictions, POTA/SOTA/WWFF/WWBOTA activations, PSKReporter, satellite tracking, WSJT-X integration, direct rig control, an in-browser logbook, and a full emergency-communications mode into a single browser-based interface. Run it locally on a Raspberry Pi, on your desktop, in Docker, or just use the hosted site.

🌐 Live Site:openhamclock.com

📧 Contact: Chris, K0CJH — chris@cjhlighting.com

☕ Support the Project:buymeacoffee.com/k0cjh — Running openhamclock.com comes with real hosting costs including network egress, memory, CPU, and the time spent maintaining and improving the project. There is absolutely no obligation to donate — OpenHamClock is and always will be free. But if you find it useful and want to chip in, your donations are greatly appreciated and go directly toward keeping the site running and funding future development.

🔧 Get Involved: This is an open-source project and the amateur radio community is encouraged to dig into the code, fork it, and build the features you want to see. Whether it's a new panel, a data source integration, or a bug fix — PRs are welcome. See Contributing below.

📝 License: MIT — See LICENSE


Documentation

GuideWhat's in it
Quick StartUse the hosted site, or self-host on Docker, Linux/macOS, Raspberry Pi, Windows, Railway
User ManualEvery panel, map layer, keyboard shortcut, and setting explained
Docker GuideCompose, Portainer, persistence, reverse proxies
RoadmapProject history and what's coming
ContributingDev setup, code style, PR workflow
TestingUnit test guide
Security PolicyVulnerability disclosure
ArchitectureCodebase map for contributors

Release notes live in the app itself: click the version number in the header to open What's New.


Feature Highlights

  • Interactive world map in three projections — flat (Mercator), azimuthal-equidistant centered on your QTH, and a full 3D globe with real satellite models — with a dozen basemap styles and ~28 toggleable overlay layers (gray line, aurora, MUF, D-RAP, lightning, satellites, RBN, WSPR, Maidenhead grid, CQ/ITU zones, aircraft, and more), most with single-key shortcuts.
  • DX cluster spots from OpenHamClock's own cluster node (RBN + HamQTH + POTA/SOTA/WWFF + user spots, deduplicated), with band/mode/zone/watchlist filtering, worked-before and dupe badges from your log, click-to-tune, and click-to-listen via the nearest live KiwiSDR.
  • Activations — live POTA, SOTA, WWFF, and WWBOTA activator panels with map markers.
  • Native logbook — QSOs stored in your browser (IndexedDB), ADIF import/export, log-from-spot, and worked-before integration across all spot panels.
  • Propagation — browser-side ITU-R P.533-14 (VOACAP-class) predictions via WebAssembly, point-to-point reliability charts, world heatmap, MUF map, band conditions, and ionosonde-corrected real-time data.
  • Space weather — SFI/Kp/SSN with history, GOES X-ray flux, NOAA SWPC alerts, aurora forecast, solar imagery, lunar phase.
  • Satellite tracking — SGP4 tracking of amateur satellites from CelesTrak/AMSAT/SatNOGS (optionally Space-Track), orbit tracks, footprints, pass info, and 3D models on the globe.
  • Rig control — click any spot and your radio tunes, via the Rig Bridge (Yaesu, Kenwood, Icom, Elecraft, FlexRadio, flrig, rigctld, and more) with a cloud relay for hosted use.
  • Digital modes — WSJT-X/JTDX decodes on the map (UDP or cloud relay), JS8Call/MSHV control, PSKReporter TX/RX reports in real time.
  • Contest tools — contest calendar, N1MM+/DXLog QSOs plotted live on the map, band plan overlay on the rig display.
  • EmComm layout — ARES/RACES dashboard with APRS (internet + RF via local TNC), net roster, point-to-point messaging, resource token aggregation, telemetry dashboards, NWS alerts, FEMA shelters and disaster declarations, Winlink gateways and Pat client.
  • Meshtastic & MeshCom — mesh network nodes and messages on the map and in dockable panels.
  • Works your way — dockable drag-anywhere layout, Classic (original HamClock style), and EmComm layouts; five themes including a custom theme editor; named profiles; 16 languages; PWA offline mode with cached data.

Quick Start

Just want to use it? Open openhamclock.com, set your callsign and grid, done.

Self-host with Docker:

docker run -d -p 3000:3000 --name openhamclock ghcr.io/accius/openhamclock:latest

Self-host from source (Node.js 22 LTS recommended):

git clone https://github.com/accius/openhamclock.git
cd openhamclock
npm ci
npm start

Open http://localhost:3000. A setup wizard walks you through callsign and grid on first run.

One-line installers for Linux/macOS (scripts/setup.sh), Raspberry Pi kiosk (scripts/setup-pi.sh), and Windows (scripts/setup-windows.ps1) — full commands and per-platform details in the Quick Start guide.

For development with hot reload:

# Terminal 1 — Backend (http://localhost:3001)
node server.js
# Terminal 2 — Frontend (hot reload on http://localhost:3000)
npm run dev

Deployment Matrix

PlatformMethodGuide
Nothing (hosted)openhamclock.comQuick Start
Docker / Portainerdocker compose up -d or ghcr.io/accius/openhamclock:latestdocs/DOCKER.md
Linux / macOS / FreeBSDscripts/setup.sh (add --service for systemd on Linux)Quick Start
Raspberry Pi (3B–5)scripts/setup-pi.sh (--kiosk for a dedicated display)Quick Start
Windowsscripts/setup-windows.ps1Quick Start
Railway (cloud)railway up or connect the GitHub repoQuick Start
Desktop appnpm run electron (experimental)

Hardware: the server side is light (~100–150 MB RAM); it's the browser rendering the map that works a machine. A Pi 4 (2 GB+) or Pi 5 makes a smooth kiosk; a Pi 3B+ is best as a headless server or with Low Memory Mode enabled in Settings. The 3D globe wants WebGL — without it the app falls back to the flat map automatically.


Configuration

All configuration lives in .env (auto-created from .env.example on first run) — and almost everything can also be changed in the in-app Settings panel, which takes priority. The only two lines most people touch:

CALLSIGN=K0CJH
LOCATOR=EN10

Files starting with a dot are hidden by default — ls -la in a terminal, Ctrl+H in a Linux file manager, Cmd+Shift+. in macOS Finder.

Settings priority: browser Settings panel (localStorage) → .env → built-in defaults. Your .env is never overwritten by updates. Self-hosted single-operator installs can set SETTINGS_SYNC=true to store UI settings on the server so every device gets the same setup.

Common variables

The complete annotated list lives in .env.example. Highlights:

VariableDefaultDescription
CALLSIGNN0CALLYour callsign — used for DX cluster login, PSKReporter queries, and "my spots" tracking
LOCATORFN31Maidenhead grid (4 or 6 characters); LATITUDE/LONGITUDE override the derived coordinates
PORT3001 (dev)Backend port. Containers run on 3000; in dev, Vite owns 3000 and proxies /api to 3001
HOSTlocalhostSet 0.0.0.0 to allow other devices on your LAN
THEME / LAYOUTdark / modernStartup theme (dark, light, legacy, retro) and layout (modern, classic)
DISTUNITS / TEMPUNITS / PRESSUNITSimperialDistance, temperature, and pressure units (imperial or metric); UNITS is deprecated
TIME_FORMAT1212 or 24 hour clock
SETTINGS_SYNCfalseStore all UI settings server-side (single-operator self-host only)
WSJTX_ENABLEDtrueWSJT-X/JTDX UDP listener (legacy name WSJTX_UDP_ENABLED still honored)
WSJTX_UDP_PORT2237Must match WSJT-X Settings → Reporting → UDP Server
WSJTX_MULTICAST_ADDRESS(none)Set when WSJT-X broadcasts to a multicast group (e.g. 224.0.0.1)
WSJTX_RELAY_KEY(none)Shared secret for the WSJT-X relay agent (cloud deployments only)
AUTO_UPDATE_ENABLEDfalsePeriodic git self-update (legacy name AUTO_UPDATE still honored)
AUTO_UPDATE_INTERVAL_MINUTES60Update check interval (legacy name AUTO_UPDATE_INTERVAL still honored)
DX_CLUSTER_SOURCEautoauto, proxy, hamqth, or dxspider; see the manual
DX_CLUSTER_CALLSIGNCALLSIGN-56Cluster login (use -57 for a second/staging instance)
SPOT_RETENTION_MINUTES30How long DX spots stay in the list (5–30)
APRS_ENABLEDfalseRead-only APRS-IS feed; filter with APRS_FILTER (e.g. r/40.12/-74.82/500)
N1MM_UDP_ENABLEDfalseContest logger UDP listener on N1MM_UDP_PORT (12060) — see docs/N1MM-SETUP.md
QRZ_USERNAME/QRZ_PASSWORD, HAMQTH_USERNAME/HAMQTH_PASSWORD(none)Optional callbook credentials for better callsign lookups
OPENWEATHER_API_KEY(none)Only needed for the Cloud Layer map overlay (also set VITE_OPENWEATHER_API_KEY)
API_WRITE_KEY(none)Protects write endpoints — required for public/cloud deployments
METRICS_AUTH_KEY(none)Bearer-token auth for the Prometheus /metrics endpoint
CELESTRAK_ENABLED / AMSAT_TLE_ENABLED / SATNOGS_TLE_ENABLEDtrueSatellite element-set sources; SPACE_TRACK_USERNAME/_PASSWORD enable Space-Track as primary
ITURHFPROP_URL(built-in)External ITU-R P.533 service — only if self-hosting iturhfprop-service/
WINLINK_API_KEY(none)Winlink gateway proxy (cloud deployments; local installs use the rig-bridge plugin instead)

API Overview

The backend exposes a JSON REST API under /api, heavily cached server-side to be kind to upstream services. Notable endpoints:

EndpointDescription
GET /api/config, GET /api/versionStation config and lightweight version check (drives the update toast)
GET /api/healthLive server dashboard — uptime, visitors, sessions, per-endpoint traffic (?format=json for raw data)
GET /api/dxcluster/spots, /paths, /sourcesDX cluster spots, map paths, and available source backends
POST /api/dxcluster/spotSubmit a spot to the OHC cluster
GET /api/pota/spots, /api/sota/spots, /api/wwff/spotsActivator spots (1–2 min cache)
GET /api/solar-indices, /api/noaa/xray, /api/noaa/aurora, /api/drap, /api/swpc/alertsSpace weather feeds
GET /api/n0nbhN0NBH band conditions
GET /api/propagation, /heatmap, /mufmapPoint-to-point prediction, world heatmap, MUF map
GET /api/p533-data/:fileITU-R P.533 coefficient tables for the in-browser WASM engine
GET /api/satellites/dataMerged satellite element sets (CelesTrak / AMSAT / SatNOGS / Space-Track)
GET /api/callsign/:call, /api/ctyCallsign lookup and the AD1C cty.dat prefix database
GET /api/rbn/spots, /api/wspr/heatmapReverse Beacon Network spots and WSPR heatmap
GET /api/pskreporter/stream/:idLive PSKReporter spots over SSE (server-side MQTT proxy)
GET /api/wsjtx/decodes, POST /api/wsjtx/relayWSJT-X decodes and the cloud relay ingest
GET /api/contests, /api/dxpeditions, /api/dxnewsContest calendar, DXpeditions, DX news
GET/POST /api/contest/qsosN1MM/DXLog contest QSOs (UDP-fed, plus HTTP ingest)
GET /api/aprs/stations, /messages, /telemetry, /netAPRS stations, messaging, telemetry, net roster
GET /api/emcomm/alerts, /shelters, /disastersNWS alerts, FEMA shelters and disaster declarations
GET /api/winlink/gatewaysWinlink RMS gateways (needs WINLINK_API_KEY server-side)
GET /api/websdr/receiversNearest live KiwiSDR/WebSDR receivers for click-to-listen
GET /api/aircraft, /api/atc/sectorsADS-B aircraft (adsb.lol) and ATC sector boundaries
GET /metricsPrometheus metrics (optionally gated by METRICS_AUTH_KEY)

Write endpoints (settings, rig, rotator, spot submission, etc.) are rate-limited and honor API_WRITE_KEY when set.


Architecture

React 18 + Vite frontend, Express backend. The backend is an API proxy and data aggregator — external calls are cached server-side so any number of browsers add near-zero upstream load. Real-time data flows over SSE (DX cluster, PSKReporter, RBN), UDP (WSJT-X, N1MM), and a server-side MQTT proxy.

Companion services in this repo:

DirectoryService
rig-bridge/Local rig control bridge — 20+ plugins (radios, digital modes, APRS TNC, rotator, Winlink)
ohc-cluster/OpenHamClock's own DX cluster node (telnet :7300 + HTTP), aggregating RBN, HamQTH, POTA/SOTA/WWFF, Parks n Peaks, DX Summit, and user spots
dxspider-proxy/Persistent telnet connection to the DX Spider network, served over HTTP
iturhfprop-service/ITU-R P.533-14 propagation engine as a REST API (self-host alternative)
wasm-build/Builds the P.533 engine to WebAssembly for in-browser predictions
wsjtx-relay/WSJT-X UDP → HTTPS relay for cloud-hosted instances
fletcher/TLE fetch egress proxy used by the hosted deployment
watchtower/Cloudflare Worker uptime probe

Full codebase map: docs/ARCHITECTURE.md


Updating

  • Hosted site — nothing to do; a toast appears when a new version deploys.
  • Git installs./scripts/update.sh (Linux/macOS/Pi) or .\scripts\update.ps1 (Windows), then restart. Local installs also get an UPDATE button in the header. Optional auto-update via AUTO_UPDATE_ENABLED=true.
  • Dockerdocker compose pull && docker compose up -d.
  • Railway — push to the connected repo, or railway up.

The update scripts back up .env, pull, rebuild, and restore .env — your configuration is never lost.


FAQ

Do I need a license to use OpenHamClock? No — it's a receive-only dashboard. A callsign makes PSKReporter "my signal" views and cluster login meaningful, but anyone can watch spots and space weather.

Can multiple people use one server? Yes. Each browser keeps its own settings, filters, and DX target; the server cache means extra users add no upstream load. Shared-station operators can use Profiles (Settings → Profiles) to switch setups.

Why don't I see DX spots / PSK reports? Make sure your callsign is set. PSKReporter falls back from the live stream to HTTP automatically; check the panel footer for the active method. For clusters, check the server console and any custom DXSPIDER_PROXY_URL.

Emoji show as boxes on Linux/Pi? Install a color emoji font on the machine running the browser: sudo apt install fonts-noto-color-emoji, then restart the browser. The Pi setup script does this automatically.

Where's the .env file? In the repo root, hidden by the leading dot — ls -la shows it. Run npm start once and it's created from .env.example automatically.

More Q&A throughout the User Manual.


Monitoring

OpenHamClock exposes a Prometheus-compatible endpoint at /metrics (optionally protected with METRICS_AUTH_KEY as a bearer token) and a human-friendly health dashboard at /api/health.


Contributing

OpenHamClock is built by the ham radio community — 40+ contributors and growing. Whether it's a bug fix, a new panel, a map layer plugin, or better docs, PRs are welcome.

git clone https://github.com/accius/openhamclock.git
cd openhamclock
git checkout Staging
npm ci
node server.js # Terminal 1 — Backend on :3001
npm run dev # Terminal 2 — Frontend on :3000

Open pull requests against Staging, not main. Read CONTRIBUTING.md for the workflow, code style, and the documentation policy, and docs/ARCHITECTURE.md for the codebase map.

Community:


Credits

  • K0CJH (Chris Hetherington) — Creator and maintainer — chris@cjhlighting.com
  • Elwood Downey, WB0OEW (SK) — Creator of the original HamClock that inspired this project. OpenHamClock is dedicated to his memory.
  • Claude AI (Anthropic) — Accelerated development by assisting with bug fixes, code structure, and feature implementation
  • Keith, G6NHU — DX Spider cluster operator at dxspider.co.uk
  • NOAA Space Weather Prediction Center — Space weather data (SFI, Kp, SSN, X-ray flux, aurora, D-RAP)
  • N0NBH (Paul Herrman) — Real-time band conditions data feed
  • POTA / SOTA / WWFF / WWBOTA — Activator spot APIs
  • PSKReporter — Digital mode reception report network
  • Reverse Beacon Network — CW/RTTY/FT skimmer spots
  • Open-Meteo — Free weather API
  • Leaflet — Open-source mapping library
  • CelesTrak · AMSAT · SatNOGS — Satellite orbital element data
  • NASA — Imagery, EONET hazards data, and the ISS 3D model (NASA/VTAD)
  • KC2G / GIRO — Ionospheric sounding data (acknowledgements)
  • AD1C — cty.dat DXCC entity database
  • NG3K — DXpedition listing
  • DXNews.com / DX-World — DX news headlines
  • WA7BNM — Contest calendar data
  • adsb.lol — Community ADS-B aircraft feed

And thank you to every contributor — the full wall lives in the app under Settings → Community.


License

MIT License — See LICENSE file.


73 de K0CJH openhamclock.com · chris@cjhlighting.com

About

"The original HamClock will cease to function in June 2026. OpenHamClock aims to carry on Elwood's legacy with a modern, open-source implementation that the community can maintain and improve together."

Resources

Code of conduct

Contributing

Security policy

Stars

462 stars

Watchers

19 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Latest commit

History

2,921 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenHamClock

A real-time amateur radio dashboard for the modern operator.

OpenHamClock brings DX cluster spots, space weather, propagation predictions, POTA/SOTA/WWFF/WWBOTA activations, PSKReporter, satellite tracking, WSJT-X integration, direct rig control, an in-browser logbook, and a full emergency-communications mode into a single browser-based interface. Run it locally on a Raspberry Pi, on your desktop, in Docker, or just use the hosted site.

🌐 Live Site:openhamclock.com

📧 Contact: Chris, K0CJH — chris@cjhlighting.com

☕ Support the Project:buymeacoffee.com/k0cjh — Running openhamclock.com comes with real hosting costs including network egress, memory, CPU, and the time spent maintaining and improving the project. There is absolutely no obligation to donate — OpenHamClock is and always will be free. But if you find it useful and want to chip in, your donations are greatly appreciated and go directly toward keeping the site running and funding future development.

🔧 Get Involved: This is an open-source project and the amateur radio community is encouraged to dig into the code, fork it, and build the features you want to see. Whether it's a new panel, a data source integration, or a bug fix — PRs are welcome. See Contributing below.

📝 License: MIT — See LICENSE


Documentation

GuideWhat's in it
Quick StartUse the hosted site, or self-host on Docker, Linux/macOS, Raspberry Pi, Windows, Railway
User ManualEvery panel, map layer, keyboard shortcut, and setting explained
Docker GuideCompose, Portainer, persistence, reverse proxies
RoadmapProject history and what's coming
ContributingDev setup, code style, PR workflow
TestingUnit test guide
Security PolicyVulnerability disclosure
ArchitectureCodebase map for contributors

Release notes live in the app itself: click the version number in the header to open What's New.


Feature Highlights

  • Interactive world map in three projections — flat (Mercator), azimuthal-equidistant centered on your QTH, and a full 3D globe with real satellite models — with a dozen basemap styles and ~28 toggleable overlay layers (gray line, aurora, MUF, D-RAP, lightning, satellites, RBN, WSPR, Maidenhead grid, CQ/ITU zones, aircraft, and more), most with single-key shortcuts.
  • DX cluster spots from OpenHamClock's own cluster node (RBN + HamQTH + POTA/SOTA/WWFF + user spots, deduplicated), with band/mode/zone/watchlist filtering, worked-before and dupe badges from your log, click-to-tune, and click-to-listen via the nearest live KiwiSDR.
  • Activations — live POTA, SOTA, WWFF, and WWBOTA activator panels with map markers.
  • Native logbook — QSOs stored in your browser (IndexedDB), ADIF import/export, log-from-spot, and worked-before integration across all spot panels.
  • Propagation — browser-side ITU-R P.533-14 (VOACAP-class) predictions via WebAssembly, point-to-point reliability charts, world heatmap, MUF map, band conditions, and ionosonde-corrected real-time data.
  • Space weather — SFI/Kp/SSN with history, GOES X-ray flux, NOAA SWPC alerts, aurora forecast, solar imagery, lunar phase.
  • Satellite tracking — SGP4 tracking of amateur satellites from CelesTrak/AMSAT/SatNOGS (optionally Space-Track), orbit tracks, footprints, pass info, and 3D models on the globe.
  • Rig control — click any spot and your radio tunes, via the Rig Bridge (Yaesu, Kenwood, Icom, Elecraft, FlexRadio, flrig, rigctld, and more) with a cloud relay for hosted use.
  • Digital modes — WSJT-X/JTDX decodes on the map (UDP or cloud relay), JS8Call/MSHV control, PSKReporter TX/RX reports in real time.
  • Contest tools — contest calendar, N1MM+/DXLog QSOs plotted live on the map, band plan overlay on the rig display.
  • EmComm layout — ARES/RACES dashboard with APRS (internet + RF via local TNC), net roster, point-to-point messaging, resource token aggregation, telemetry dashboards, NWS alerts, FEMA shelters and disaster declarations, Winlink gateways and Pat client.
  • Meshtastic & MeshCom — mesh network nodes and messages on the map and in dockable panels.
  • Works your way — dockable drag-anywhere layout, Classic (original HamClock style), and EmComm layouts; five themes including a custom theme editor; named profiles; 16 languages; PWA offline mode with cached data.

Quick Start

Just want to use it? Open openhamclock.com, set your callsign and grid, done.

Self-host with Docker:

docker run -d -p 3000:3000 --name openhamclock ghcr.io/accius/openhamclock:latest

Self-host from source (Node.js 22 LTS recommended):

git clone https://github.com/accius/openhamclock.git
cd openhamclock
npm ci
npm start

Open http://localhost:3000. A setup wizard walks you through callsign and grid on first run.

One-line installers for Linux/macOS (scripts/setup.sh), Raspberry Pi kiosk (scripts/setup-pi.sh), and Windows (scripts/setup-windows.ps1) — full commands and per-platform details in the Quick Start guide.

For development with hot reload:

# Terminal 1 — Backend (http://localhost:3001)
node server.js
# Terminal 2 — Frontend (hot reload on http://localhost:3000)
npm run dev

Deployment Matrix

PlatformMethodGuide
Nothing (hosted)openhamclock.comQuick Start
Docker / Portainerdocker compose up -d or ghcr.io/accius/openhamclock:latestdocs/DOCKER.md
Linux / macOS / FreeBSDscripts/setup.sh (add --service for systemd on Linux)Quick Start
Raspberry Pi (3B–5)scripts/setup-pi.sh (--kiosk for a dedicated display)Quick Start
Windowsscripts/setup-windows.ps1Quick Start
Railway (cloud)railway up or connect the GitHub repoQuick Start
Desktop appnpm run electron (experimental)

Hardware: the server side is light (~100–150 MB RAM); it's the browser rendering the map that works a machine. A Pi 4 (2 GB+) or Pi 5 makes a smooth kiosk; a Pi 3B+ is best as a headless server or with Low Memory Mode enabled in Settings. The 3D globe wants WebGL — without it the app falls back to the flat map automatically.


Configuration

All configuration lives in .env (auto-created from .env.example on first run) — and almost everything can also be changed in the in-app Settings panel, which takes priority. The only two lines most people touch:

CALLSIGN=K0CJH
LOCATOR=EN10

Files starting with a dot are hidden by default — ls -la in a terminal, Ctrl+H in a Linux file manager, Cmd+Shift+. in macOS Finder.

Settings priority: browser Settings panel (localStorage) → .env → built-in defaults. Your .env is never overwritten by updates. Self-hosted single-operator installs can set SETTINGS_SYNC=true to store UI settings on the server so every device gets the same setup.

Common variables

The complete annotated list lives in .env.example. Highlights:

VariableDefaultDescription
CALLSIGNN0CALLYour callsign — used for DX cluster login, PSKReporter queries, and "my spots" tracking
LOCATORFN31Maidenhead grid (4 or 6 characters); LATITUDE/LONGITUDE override the derived coordinates
PORT3001 (dev)Backend port. Containers run on 3000; in dev, Vite owns 3000 and proxies /api to 3001
HOSTlocalhostSet 0.0.0.0 to allow other devices on your LAN
THEME / LAYOUTdark / modernStartup theme (dark, light, legacy, retro) and layout (modern, classic)
DISTUNITS / TEMPUNITS / PRESSUNITSimperialDistance, temperature, and pressure units (imperial or metric); UNITS is deprecated
TIME_FORMAT1212 or 24 hour clock
SETTINGS_SYNCfalseStore all UI settings server-side (single-operator self-host only)
WSJTX_ENABLEDtrueWSJT-X/JTDX UDP listener (legacy name WSJTX_UDP_ENABLED still honored)
WSJTX_UDP_PORT2237Must match WSJT-X Settings → Reporting → UDP Server
WSJTX_MULTICAST_ADDRESS(none)Set when WSJT-X broadcasts to a multicast group (e.g. 224.0.0.1)
WSJTX_RELAY_KEY(none)Shared secret for the WSJT-X relay agent (cloud deployments only)
AUTO_UPDATE_ENABLEDfalsePeriodic git self-update (legacy name AUTO_UPDATE still honored)
AUTO_UPDATE_INTERVAL_MINUTES60Update check interval (legacy name AUTO_UPDATE_INTERVAL still honored)
DX_CLUSTER_SOURCEautoauto, proxy, hamqth, or dxspider; see the manual
DX_CLUSTER_CALLSIGNCALLSIGN-56Cluster login (use -57 for a second/staging instance)
SPOT_RETENTION_MINUTES30How long DX spots stay in the list (5–30)
APRS_ENABLEDfalseRead-only APRS-IS feed; filter with APRS_FILTER (e.g. r/40.12/-74.82/500)
N1MM_UDP_ENABLEDfalseContest logger UDP listener on N1MM_UDP_PORT (12060) — see docs/N1MM-SETUP.md
QRZ_USERNAME/QRZ_PASSWORD, HAMQTH_USERNAME/HAMQTH_PASSWORD(none)Optional callbook credentials for better callsign lookups
OPENWEATHER_API_KEY(none)Only needed for the Cloud Layer map overlay (also set VITE_OPENWEATHER_API_KEY)
API_WRITE_KEY(none)Protects write endpoints — required for public/cloud deployments
METRICS_AUTH_KEY(none)Bearer-token auth for the Prometheus /metrics endpoint
CELESTRAK_ENABLED / AMSAT_TLE_ENABLED / SATNOGS_TLE_ENABLEDtrueSatellite element-set sources; SPACE_TRACK_USERNAME/_PASSWORD enable Space-Track as primary
ITURHFPROP_URL(built-in)External ITU-R P.533 service — only if self-hosting iturhfprop-service/
WINLINK_API_KEY(none)Winlink gateway proxy (cloud deployments; local installs use the rig-bridge plugin instead)

API Overview

The backend exposes a JSON REST API under /api, heavily cached server-side to be kind to upstream services. Notable endpoints:

EndpointDescription
GET /api/config, GET /api/versionStation config and lightweight version check (drives the update toast)
GET /api/healthLive server dashboard — uptime, visitors, sessions, per-endpoint traffic (?format=json for raw data)
GET /api/dxcluster/spots, /paths, /sourcesDX cluster spots, map paths, and available source backends
POST /api/dxcluster/spotSubmit a spot to the OHC cluster
GET /api/pota/spots, /api/sota/spots, /api/wwff/spotsActivator spots (1–2 min cache)
GET /api/solar-indices, /api/noaa/xray, /api/noaa/aurora, /api/drap, /api/swpc/alertsSpace weather feeds
GET /api/n0nbhN0NBH band conditions
GET /api/propagation, /heatmap, /mufmapPoint-to-point prediction, world heatmap, MUF map
GET /api/p533-data/:fileITU-R P.533 coefficient tables for the in-browser WASM engine
GET /api/satellites/dataMerged satellite element sets (CelesTrak / AMSAT / SatNOGS / Space-Track)
GET /api/callsign/:call, /api/ctyCallsign lookup and the AD1C cty.dat prefix database
GET /api/rbn/spots, /api/wspr/heatmapReverse Beacon Network spots and WSPR heatmap
GET /api/pskreporter/stream/:idLive PSKReporter spots over SSE (server-side MQTT proxy)
GET /api/wsjtx/decodes, POST /api/wsjtx/relayWSJT-X decodes and the cloud relay ingest
GET /api/contests, /api/dxpeditions, /api/dxnewsContest calendar, DXpeditions, DX news
GET/POST /api/contest/qsosN1MM/DXLog contest QSOs (UDP-fed, plus HTTP ingest)
GET /api/aprs/stations, /messages, /telemetry, /netAPRS stations, messaging, telemetry, net roster
GET /api/emcomm/alerts, /shelters, /disastersNWS alerts, FEMA shelters and disaster declarations
GET /api/winlink/gatewaysWinlink RMS gateways (needs WINLINK_API_KEY server-side)
GET /api/websdr/receiversNearest live KiwiSDR/WebSDR receivers for click-to-listen
GET /api/aircraft, /api/atc/sectorsADS-B aircraft (adsb.lol) and ATC sector boundaries
GET /metricsPrometheus metrics (optionally gated by METRICS_AUTH_KEY)

Write endpoints (settings, rig, rotator, spot submission, etc.) are rate-limited and honor API_WRITE_KEY when set.


Architecture

React 18 + Vite frontend, Express backend. The backend is an API proxy and data aggregator — external calls are cached server-side so any number of browsers add near-zero upstream load. Real-time data flows over SSE (DX cluster, PSKReporter, RBN), UDP (WSJT-X, N1MM), and a server-side MQTT proxy.

Companion services in this repo:

DirectoryService
rig-bridge/Local rig control bridge — 20+ plugins (radios, digital modes, APRS TNC, rotator, Winlink)
ohc-cluster/OpenHamClock's own DX cluster node (telnet :7300 + HTTP), aggregating RBN, HamQTH, POTA/SOTA/WWFF, Parks n Peaks, DX Summit, and user spots
dxspider-proxy/Persistent telnet connection to the DX Spider network, served over HTTP
iturhfprop-service/ITU-R P.533-14 propagation engine as a REST API (self-host alternative)
wasm-build/Builds the P.533 engine to WebAssembly for in-browser predictions
wsjtx-relay/WSJT-X UDP → HTTPS relay for cloud-hosted instances
fletcher/TLE fetch egress proxy used by the hosted deployment
watchtower/Cloudflare Worker uptime probe

Full codebase map: docs/ARCHITECTURE.md


Updating

  • Hosted site — nothing to do; a toast appears when a new version deploys.
  • Git installs./scripts/update.sh (Linux/macOS/Pi) or .\scripts\update.ps1 (Windows), then restart. Local installs also get an UPDATE button in the header. Optional auto-update via AUTO_UPDATE_ENABLED=true.
  • Dockerdocker compose pull && docker compose up -d.
  • Railway — push to the connected repo, or railway up.

The update scripts back up .env, pull, rebuild, and restore .env — your configuration is never lost.


FAQ

Do I need a license to use OpenHamClock? No — it's a receive-only dashboard. A callsign makes PSKReporter "my signal" views and cluster login meaningful, but anyone can watch spots and space weather.

Can multiple people use one server? Yes. Each browser keeps its own settings, filters, and DX target; the server cache means extra users add no upstream load. Shared-station operators can use Profiles (Settings → Profiles) to switch setups.

Why don't I see DX spots / PSK reports? Make sure your callsign is set. PSKReporter falls back from the live stream to HTTP automatically; check the panel footer for the active method. For clusters, check the server console and any custom DXSPIDER_PROXY_URL.

Emoji show as boxes on Linux/Pi? Install a color emoji font on the machine running the browser: sudo apt install fonts-noto-color-emoji, then restart the browser. The Pi setup script does this automatically.

Where's the .env file? In the repo root, hidden by the leading dot — ls -la shows it. Run npm start once and it's created from .env.example automatically.

More Q&A throughout the User Manual.


Monitoring

OpenHamClock exposes a Prometheus-compatible endpoint at /metrics (optionally protected with METRICS_AUTH_KEY as a bearer token) and a human-friendly health dashboard at /api/health.


Contributing

OpenHamClock is built by the ham radio community — 40+ contributors and growing. Whether it's a bug fix, a new panel, a map layer plugin, or better docs, PRs are welcome.

git clone https://github.com/accius/openhamclock.git
cd openhamclock
git checkout Staging
npm ci
node server.js # Terminal 1 — Backend on :3001
npm run dev # Terminal 2 — Frontend on :3000

Open pull requests against Staging, not main. Read CONTRIBUTING.md for the workflow, code style, and the documentation policy, and docs/ARCHITECTURE.md for the codebase map.

Community:


Credits

  • K0CJH (Chris Hetherington) — Creator and maintainer — chris@cjhlighting.com
  • Elwood Downey, WB0OEW (SK) — Creator of the original HamClock that inspired this project. OpenHamClock is dedicated to his memory.
  • Claude AI (Anthropic) — Accelerated development by assisting with bug fixes, code structure, and feature implementation
  • Keith, G6NHU — DX Spider cluster operator at dxspider.co.uk
  • NOAA Space Weather Prediction Center — Space weather data (SFI, Kp, SSN, X-ray flux, aurora, D-RAP)
  • N0NBH (Paul Herrman) — Real-time band conditions data feed
  • POTA / SOTA / WWFF / WWBOTA — Activator spot APIs
  • PSKReporter — Digital mode reception report network
  • Reverse Beacon Network — CW/RTTY/FT skimmer spots
  • Open-Meteo — Free weather API
  • Leaflet — Open-source mapping library
  • CelesTrak · AMSAT · SatNOGS — Satellite orbital element data
  • NASA — Imagery, EONET hazards data, and the ISS 3D model (NASA/VTAD)
  • KC2G / GIRO — Ionospheric sounding data (acknowledgements)
  • AD1C — cty.dat DXCC entity database
  • NG3K — DXpedition listing
  • DXNews.com / DX-World — DX news headlines
  • WA7BNM — Contest calendar data
  • adsb.lol — Community ADS-B aircraft feed

And thank you to every contributor — the full wall lives in the app under Settings → Community.


License

MIT License — See LICENSE file.


73 de K0CJH openhamclock.com · chris@cjhlighting.com

About

"The original HamClock will cease to function in June 2026. OpenHamClock aims to carry on Elwood's legacy with a modern, open-source implementation that the community can maintain and improve together."

Resources

Code of conduct

Contributing

Security policy

Stars

462 stars

Watchers

19 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

2,921 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenHamClock

A real-time amateur radio dashboard for the modern operator.

OpenHamClock brings DX cluster spots, space weather, propagation predictions, POTA/SOTA/WWFF/WWBOTA activations, PSKReporter, satellite tracking, WSJT-X integration, direct rig control, an in-browser logbook, and a full emergency-communications mode into a single browser-based interface. Run it locally on a Raspberry Pi, on your desktop, in Docker, or just use the hosted site.

🌐 Live Site:openhamclock.com

📧 Contact: Chris, K0CJH — chris@cjhlighting.com

☕ Support the Project:buymeacoffee.com/k0cjh — Running openhamclock.com comes with real hosting costs including network egress, memory, CPU, and the time spent maintaining and improving the project. There is absolutely no obligation to donate — OpenHamClock is and always will be free. But if you find it useful and want to chip in, your donations are greatly appreciated and go directly toward keeping the site running and funding future development.

🔧 Get Involved: This is an open-source project and the amateur radio community is encouraged to dig into the code, fork it, and build the features you want to see. Whether it's a new panel, a data source integration, or a bug fix — PRs are welcome. See Contributing below.

📝 License: MIT — See LICENSE


Documentation

GuideWhat's in it
Quick StartUse the hosted site, or self-host on Docker, Linux/macOS, Raspberry Pi, Windows, Railway
User ManualEvery panel, map layer, keyboard shortcut, and setting explained
Docker GuideCompose, Portainer, persistence, reverse proxies
RoadmapProject history and what's coming
ContributingDev setup, code style, PR workflow
TestingUnit test guide
Security PolicyVulnerability disclosure
ArchitectureCodebase map for contributors

Release notes live in the app itself: click the version number in the header to open What's New.


Feature Highlights

  • Interactive world map in three projections — flat (Mercator), azimuthal-equidistant centered on your QTH, and a full 3D globe with real satellite models — with a dozen basemap styles and ~28 toggleable overlay layers (gray line, aurora, MUF, D-RAP, lightning, satellites, RBN, WSPR, Maidenhead grid, CQ/ITU zones, aircraft, and more), most with single-key shortcuts.
  • DX cluster spots from OpenHamClock's own cluster node (RBN + HamQTH + POTA/SOTA/WWFF + user spots, deduplicated), with band/mode/zone/watchlist filtering, worked-before and dupe badges from your log, click-to-tune, and click-to-listen via the nearest live KiwiSDR.
  • Activations — live POTA, SOTA, WWFF, and WWBOTA activator panels with map markers.
  • Native logbook — QSOs stored in your browser (IndexedDB), ADIF import/export, log-from-spot, and worked-before integration across all spot panels.
  • Propagation — browser-side ITU-R P.533-14 (VOACAP-class) predictions via WebAssembly, point-to-point reliability charts, world heatmap, MUF map, band conditions, and ionosonde-corrected real-time data.
  • Space weather — SFI/Kp/SSN with history, GOES X-ray flux, NOAA SWPC alerts, aurora forecast, solar imagery, lunar phase.
  • Satellite tracking — SGP4 tracking of amateur satellites from CelesTrak/AMSAT/SatNOGS (optionally Space-Track), orbit tracks, footprints, pass info, and 3D models on the globe.
  • Rig control — click any spot and your radio tunes, via the Rig Bridge (Yaesu, Kenwood, Icom, Elecraft, FlexRadio, flrig, rigctld, and more) with a cloud relay for hosted use.
  • Digital modes — WSJT-X/JTDX decodes on the map (UDP or cloud relay), JS8Call/MSHV control, PSKReporter TX/RX reports in real time.
  • Contest tools — contest calendar, N1MM+/DXLog QSOs plotted live on the map, band plan overlay on the rig display.
  • EmComm layout — ARES/RACES dashboard with APRS (internet + RF via local TNC), net roster, point-to-point messaging, resource token aggregation, telemetry dashboards, NWS alerts, FEMA shelters and disaster declarations, Winlink gateways and Pat client.
  • Meshtastic & MeshCom — mesh network nodes and messages on the map and in dockable panels.
  • Works your way — dockable drag-anywhere layout, Classic (original HamClock style), and EmComm layouts; five themes including a custom theme editor; named profiles; 16 languages; PWA offline mode with cached data.

Quick Start

Just want to use it? Open openhamclock.com, set your callsign and grid, done.

Self-host with Docker:

docker run -d -p 3000:3000 --name openhamclock ghcr.io/accius/openhamclock:latest

Self-host from source (Node.js 22 LTS recommended):

git clone https://github.com/accius/openhamclock.git
cd openhamclock
npm ci
npm start

Open http://localhost:3000. A setup wizard walks you through callsign and grid on first run.

One-line installers for Linux/macOS (scripts/setup.sh), Raspberry Pi kiosk (scripts/setup-pi.sh), and Windows (scripts/setup-windows.ps1) — full commands and per-platform details in the Quick Start guide.

For development with hot reload:

# Terminal 1 — Backend (http://localhost:3001)
node server.js
# Terminal 2 — Frontend (hot reload on http://localhost:3000)
npm run dev

Deployment Matrix

PlatformMethodGuide
Nothing (hosted)openhamclock.comQuick Start
Docker / Portainerdocker compose up -d or ghcr.io/accius/openhamclock:latestdocs/DOCKER.md
Linux / macOS / FreeBSDscripts/setup.sh (add --service for systemd on Linux)Quick Start
Raspberry Pi (3B–5)scripts/setup-pi.sh (--kiosk for a dedicated display)Quick Start
Windowsscripts/setup-windows.ps1Quick Start
Railway (cloud)railway up or connect the GitHub repoQuick Start
Desktop appnpm run electron (experimental)

Hardware: the server side is light (~100–150 MB RAM); it's the browser rendering the map that works a machine. A Pi 4 (2 GB+) or Pi 5 makes a smooth kiosk; a Pi 3B+ is best as a headless server or with Low Memory Mode enabled in Settings. The 3D globe wants WebGL — without it the app falls back to the flat map automatically.


Configuration

All configuration lives in .env (auto-created from .env.example on first run) — and almost everything can also be changed in the in-app Settings panel, which takes priority. The only two lines most people touch:

CALLSIGN=K0CJH
LOCATOR=EN10

Files starting with a dot are hidden by default — ls -la in a terminal, Ctrl+H in a Linux file manager, Cmd+Shift+. in macOS Finder.

Settings priority: browser Settings panel (localStorage) → .env → built-in defaults. Your .env is never overwritten by updates. Self-hosted single-operator installs can set SETTINGS_SYNC=true to store UI settings on the server so every device gets the same setup.

Common variables

The complete annotated list lives in .env.example. Highlights:

VariableDefaultDescription
CALLSIGNN0CALLYour callsign — used for DX cluster login, PSKReporter queries, and "my spots" tracking
LOCATORFN31Maidenhead grid (4 or 6 characters); LATITUDE/LONGITUDE override the derived coordinates
PORT3001 (dev)Backend port. Containers run on 3000; in dev, Vite owns 3000 and proxies /api to 3001
HOSTlocalhostSet 0.0.0.0 to allow other devices on your LAN
THEME / LAYOUTdark / modernStartup theme (dark, light, legacy, retro) and layout (modern, classic)
DISTUNITS / TEMPUNITS / PRESSUNITSimperialDistance, temperature, and pressure units (imperial or metric); UNITS is deprecated
TIME_FORMAT1212 or 24 hour clock
SETTINGS_SYNCfalseStore all UI settings server-side (single-operator self-host only)
WSJTX_ENABLEDtrueWSJT-X/JTDX UDP listener (legacy name WSJTX_UDP_ENABLED still honored)
WSJTX_UDP_PORT2237Must match WSJT-X Settings → Reporting → UDP Server
WSJTX_MULTICAST_ADDRESS(none)Set when WSJT-X broadcasts to a multicast group (e.g. 224.0.0.1)
WSJTX_RELAY_KEY(none)Shared secret for the WSJT-X relay agent (cloud deployments only)
AUTO_UPDATE_ENABLEDfalsePeriodic git self-update (legacy name AUTO_UPDATE still honored)
AUTO_UPDATE_INTERVAL_MINUTES60Update check interval (legacy name AUTO_UPDATE_INTERVAL still honored)
DX_CLUSTER_SOURCEautoauto, proxy, hamqth, or dxspider; see the manual
DX_CLUSTER_CALLSIGNCALLSIGN-56Cluster login (use -57 for a second/staging instance)
SPOT_RETENTION_MINUTES30How long DX spots stay in the list (5–30)
APRS_ENABLEDfalseRead-only APRS-IS feed; filter with APRS_FILTER (e.g. r/40.12/-74.82/500)
N1MM_UDP_ENABLEDfalseContest logger UDP listener on N1MM_UDP_PORT (12060) — see docs/N1MM-SETUP.md
QRZ_USERNAME/QRZ_PASSWORD, HAMQTH_USERNAME/HAMQTH_PASSWORD(none)Optional callbook credentials for better callsign lookups
OPENWEATHER_API_KEY(none)Only needed for the Cloud Layer map overlay (also set VITE_OPENWEATHER_API_KEY)
API_WRITE_KEY(none)Protects write endpoints — required for public/cloud deployments
METRICS_AUTH_KEY(none)Bearer-token auth for the Prometheus /metrics endpoint
CELESTRAK_ENABLED / AMSAT_TLE_ENABLED / SATNOGS_TLE_ENABLEDtrueSatellite element-set sources; SPACE_TRACK_USERNAME/_PASSWORD enable Space-Track as primary
ITURHFPROP_URL(built-in)External ITU-R P.533 service — only if self-hosting iturhfprop-service/
WINLINK_API_KEY(none)Winlink gateway proxy (cloud deployments; local installs use the rig-bridge plugin instead)

API Overview

The backend exposes a JSON REST API under /api, heavily cached server-side to be kind to upstream services. Notable endpoints:

EndpointDescription
GET /api/config, GET /api/versionStation config and lightweight version check (drives the update toast)
GET /api/healthLive server dashboard — uptime, visitors, sessions, per-endpoint traffic (?format=json for raw data)
GET /api/dxcluster/spots, /paths, /sourcesDX cluster spots, map paths, and available source backends
POST /api/dxcluster/spotSubmit a spot to the OHC cluster
GET /api/pota/spots, /api/sota/spots, /api/wwff/spotsActivator spots (1–2 min cache)
GET /api/solar-indices, /api/noaa/xray, /api/noaa/aurora, /api/drap, /api/swpc/alertsSpace weather feeds
GET /api/n0nbhN0NBH band conditions
GET /api/propagation, /heatmap, /mufmapPoint-to-point prediction, world heatmap, MUF map
GET /api/p533-data/:fileITU-R P.533 coefficient tables for the in-browser WASM engine
GET /api/satellites/dataMerged satellite element sets (CelesTrak / AMSAT / SatNOGS / Space-Track)
GET /api/callsign/:call, /api/ctyCallsign lookup and the AD1C cty.dat prefix database
GET /api/rbn/spots, /api/wspr/heatmapReverse Beacon Network spots and WSPR heatmap
GET /api/pskreporter/stream/:idLive PSKReporter spots over SSE (server-side MQTT proxy)
GET /api/wsjtx/decodes, POST /api/wsjtx/relayWSJT-X decodes and the cloud relay ingest
GET /api/contests, /api/dxpeditions, /api/dxnewsContest calendar, DXpeditions, DX news
GET/POST /api/contest/qsosN1MM/DXLog contest QSOs (UDP-fed, plus HTTP ingest)
GET /api/aprs/stations, /messages, /telemetry, /netAPRS stations, messaging, telemetry, net roster
GET /api/emcomm/alerts, /shelters, /disastersNWS alerts, FEMA shelters and disaster declarations
GET /api/winlink/gatewaysWinlink RMS gateways (needs WINLINK_API_KEY server-side)
GET /api/websdr/receiversNearest live KiwiSDR/WebSDR receivers for click-to-listen
GET /api/aircraft, /api/atc/sectorsADS-B aircraft (adsb.lol) and ATC sector boundaries
GET /metricsPrometheus metrics (optionally gated by METRICS_AUTH_KEY)

Write endpoints (settings, rig, rotator, spot submission, etc.) are rate-limited and honor API_WRITE_KEY when set.


Architecture

React 18 + Vite frontend, Express backend. The backend is an API proxy and data aggregator — external calls are cached server-side so any number of browsers add near-zero upstream load. Real-time data flows over SSE (DX cluster, PSKReporter, RBN), UDP (WSJT-X, N1MM), and a server-side MQTT proxy.

Companion services in this repo:

DirectoryService
rig-bridge/Local rig control bridge — 20+ plugins (radios, digital modes, APRS TNC, rotator, Winlink)
ohc-cluster/OpenHamClock's own DX cluster node (telnet :7300 + HTTP), aggregating RBN, HamQTH, POTA/SOTA/WWFF, Parks n Peaks, DX Summit, and user spots
dxspider-proxy/Persistent telnet connection to the DX Spider network, served over HTTP
iturhfprop-service/ITU-R P.533-14 propagation engine as a REST API (self-host alternative)
wasm-build/Builds the P.533 engine to WebAssembly for in-browser predictions
wsjtx-relay/WSJT-X UDP → HTTPS relay for cloud-hosted instances
fletcher/TLE fetch egress proxy used by the hosted deployment
watchtower/Cloudflare Worker uptime probe

Full codebase map: docs/ARCHITECTURE.md


Updating

  • Hosted site — nothing to do; a toast appears when a new version deploys.
  • Git installs./scripts/update.sh (Linux/macOS/Pi) or .\scripts\update.ps1 (Windows), then restart. Local installs also get an UPDATE button in the header. Optional auto-update via AUTO_UPDATE_ENABLED=true.
  • Dockerdocker compose pull && docker compose up -d.
  • Railway — push to the connected repo, or railway up.

The update scripts back up .env, pull, rebuild, and restore .env — your configuration is never lost.


FAQ

Do I need a license to use OpenHamClock? No — it's a receive-only dashboard. A callsign makes PSKReporter "my signal" views and cluster login meaningful, but anyone can watch spots and space weather.

Can multiple people use one server? Yes. Each browser keeps its own settings, filters, and DX target; the server cache means extra users add no upstream load. Shared-station operators can use Profiles (Settings → Profiles) to switch setups.

Why don't I see DX spots / PSK reports? Make sure your callsign is set. PSKReporter falls back from the live stream to HTTP automatically; check the panel footer for the active method. For clusters, check the server console and any custom DXSPIDER_PROXY_URL.

Emoji show as boxes on Linux/Pi? Install a color emoji font on the machine running the browser: sudo apt install fonts-noto-color-emoji, then restart the browser. The Pi setup script does this automatically.

Where's the .env file? In the repo root, hidden by the leading dot — ls -la shows it. Run npm start once and it's created from .env.example automatically.

More Q&A throughout the User Manual.


Monitoring

OpenHamClock exposes a Prometheus-compatible endpoint at /metrics (optionally protected with METRICS_AUTH_KEY as a bearer token) and a human-friendly health dashboard at /api/health.


Contributing

OpenHamClock is built by the ham radio community — 40+ contributors and growing. Whether it's a bug fix, a new panel, a map layer plugin, or better docs, PRs are welcome.

git clone https://github.com/accius/openhamclock.git
cd openhamclock
git checkout Staging
npm ci
node server.js # Terminal 1 — Backend on :3001
npm run dev # Terminal 2 — Frontend on :3000

Open pull requests against Staging, not main. Read CONTRIBUTING.md for the workflow, code style, and the documentation policy, and docs/ARCHITECTURE.md for the codebase map.

Community:


Credits

  • K0CJH (Chris Hetherington) — Creator and maintainer — chris@cjhlighting.com
  • Elwood Downey, WB0OEW (SK) — Creator of the original HamClock that inspired this project. OpenHamClock is dedicated to his memory.
  • Claude AI (Anthropic) — Accelerated development by assisting with bug fixes, code structure, and feature implementation
  • Keith, G6NHU — DX Spider cluster operator at dxspider.co.uk
  • NOAA Space Weather Prediction Center — Space weather data (SFI, Kp, SSN, X-ray flux, aurora, D-RAP)
  • N0NBH (Paul Herrman) — Real-time band conditions data feed
  • POTA / SOTA / WWFF / WWBOTA — Activator spot APIs
  • PSKReporter — Digital mode reception report network
  • Reverse Beacon Network — CW/RTTY/FT skimmer spots
  • Open-Meteo — Free weather API
  • Leaflet — Open-source mapping library
  • CelesTrak · AMSAT · SatNOGS — Satellite orbital element data
  • NASA — Imagery, EONET hazards data, and the ISS 3D model (NASA/VTAD)
  • KC2G / GIRO — Ionospheric sounding data (acknowledgements)
  • AD1C — cty.dat DXCC entity database
  • NG3K — DXpedition listing
  • DXNews.com / DX-World — DX news headlines
  • WA7BNM — Contest calendar data
  • adsb.lol — Community ADS-B aircraft feed

And thank you to every contributor — the full wall lives in the app under Settings → Community.


License

MIT License — See LICENSE file.


73 de K0CJH openhamclock.com · chris@cjhlighting.com

About

"The original HamClock will cease to function in June 2026. OpenHamClock aims to carry on Elwood's legacy with a modern, open-source implementation that the community can maintain and improve together."

Resources

Code of conduct

Contributing

Security policy

Stars

462 stars

Watchers

19 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Latest commit

History

2,921 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenHamClock

A real-time amateur radio dashboard for the modern operator.

OpenHamClock brings DX cluster spots, space weather, propagation predictions, POTA/SOTA/WWFF/WWBOTA activations, PSKReporter, satellite tracking, WSJT-X integration, direct rig control, an in-browser logbook, and a full emergency-communications mode into a single browser-based interface. Run it locally on a Raspberry Pi, on your desktop, in Docker, or just use the hosted site.

🌐 Live Site:openhamclock.com

📧 Contact: Chris, K0CJH — chris@cjhlighting.com

☕ Support the Project:buymeacoffee.com/k0cjh — Running openhamclock.com comes with real hosting costs including network egress, memory, CPU, and the time spent maintaining and improving the project. There is absolutely no obligation to donate — OpenHamClock is and always will be free. But if you find it useful and want to chip in, your donations are greatly appreciated and go directly toward keeping the site running and funding future development.

🔧 Get Involved: This is an open-source project and the amateur radio community is encouraged to dig into the code, fork it, and build the features you want to see. Whether it's a new panel, a data source integration, or a bug fix — PRs are welcome. See Contributing below.

📝 License: MIT — See LICENSE


Documentation

GuideWhat's in it
Quick StartUse the hosted site, or self-host on Docker, Linux/macOS, Raspberry Pi, Windows, Railway
User ManualEvery panel, map layer, keyboard shortcut, and setting explained
Docker GuideCompose, Portainer, persistence, reverse proxies
RoadmapProject history and what's coming
ContributingDev setup, code style, PR workflow
TestingUnit test guide
Security PolicyVulnerability disclosure
ArchitectureCodebase map for contributors

Release notes live in the app itself: click the version number in the header to open What's New.


Feature Highlights

  • Interactive world map in three projections — flat (Mercator), azimuthal-equidistant centered on your QTH, and a full 3D globe with real satellite models — with a dozen basemap styles and ~28 toggleable overlay layers (gray line, aurora, MUF, D-RAP, lightning, satellites, RBN, WSPR, Maidenhead grid, CQ/ITU zones, aircraft, and more), most with single-key shortcuts.
  • DX cluster spots from OpenHamClock's own cluster node (RBN + HamQTH + POTA/SOTA/WWFF + user spots, deduplicated), with band/mode/zone/watchlist filtering, worked-before and dupe badges from your log, click-to-tune, and click-to-listen via the nearest live KiwiSDR.
  • Activations — live POTA, SOTA, WWFF, and WWBOTA activator panels with map markers.
  • Native logbook — QSOs stored in your browser (IndexedDB), ADIF import/export, log-from-spot, and worked-before integration across all spot panels.
  • Propagation — browser-side ITU-R P.533-14 (VOACAP-class) predictions via WebAssembly, point-to-point reliability charts, world heatmap, MUF map, band conditions, and ionosonde-corrected real-time data.
  • Space weather — SFI/Kp/SSN with history, GOES X-ray flux, NOAA SWPC alerts, aurora forecast, solar imagery, lunar phase.
  • Satellite tracking — SGP4 tracking of amateur satellites from CelesTrak/AMSAT/SatNOGS (optionally Space-Track), orbit tracks, footprints, pass info, and 3D models on the globe.
  • Rig control — click any spot and your radio tunes, via the Rig Bridge (Yaesu, Kenwood, Icom, Elecraft, FlexRadio, flrig, rigctld, and more) with a cloud relay for hosted use.
  • Digital modes — WSJT-X/JTDX decodes on the map (UDP or cloud relay), JS8Call/MSHV control, PSKReporter TX/RX reports in real time.
  • Contest tools — contest calendar, N1MM+/DXLog QSOs plotted live on the map, band plan overlay on the rig display.
  • EmComm layout — ARES/RACES dashboard with APRS (internet + RF via local TNC), net roster, point-to-point messaging, resource token aggregation, telemetry dashboards, NWS alerts, FEMA shelters and disaster declarations, Winlink gateways and Pat client.
  • Meshtastic & MeshCom — mesh network nodes and messages on the map and in dockable panels.
  • Works your way — dockable drag-anywhere layout, Classic (original HamClock style), and EmComm layouts; five themes including a custom theme editor; named profiles; 16 languages; PWA offline mode with cached data.

Quick Start

Just want to use it? Open openhamclock.com, set your callsign and grid, done.

Self-host with Docker:

docker run -d -p 3000:3000 --name openhamclock ghcr.io/accius/openhamclock:latest

Self-host from source (Node.js 22 LTS recommended):

git clone https://github.com/accius/openhamclock.git
cd openhamclock
npm ci
npm start

Open http://localhost:3000. A setup wizard walks you through callsign and grid on first run.

One-line installers for Linux/macOS (scripts/setup.sh), Raspberry Pi kiosk (scripts/setup-pi.sh), and Windows (scripts/setup-windows.ps1) — full commands and per-platform details in the Quick Start guide.

For development with hot reload:

# Terminal 1 — Backend (http://localhost:3001)
node server.js
# Terminal 2 — Frontend (hot reload on http://localhost:3000)
npm run dev

Deployment Matrix

PlatformMethodGuide
Nothing (hosted)openhamclock.comQuick Start
Docker / Portainerdocker compose up -d or ghcr.io/accius/openhamclock:latestdocs/DOCKER.md
Linux / macOS / FreeBSDscripts/setup.sh (add --service for systemd on Linux)Quick Start
Raspberry Pi (3B–5)scripts/setup-pi.sh (--kiosk for a dedicated display)Quick Start
Windowsscripts/setup-windows.ps1Quick Start
Railway (cloud)railway up or connect the GitHub repoQuick Start
Desktop appnpm run electron (experimental)

Hardware: the server side is light (~100–150 MB RAM); it's the browser rendering the map that works a machine. A Pi 4 (2 GB+) or Pi 5 makes a smooth kiosk; a Pi 3B+ is best as a headless server or with Low Memory Mode enabled in Settings. The 3D globe wants WebGL — without it the app falls back to the flat map automatically.


Configuration

All configuration lives in .env (auto-created from .env.example on first run) — and almost everything can also be changed in the in-app Settings panel, which takes priority. The only two lines most people touch:

CALLSIGN=K0CJH
LOCATOR=EN10

Files starting with a dot are hidden by default — ls -la in a terminal, Ctrl+H in a Linux file manager, Cmd+Shift+. in macOS Finder.

Settings priority: browser Settings panel (localStorage) → .env → built-in defaults. Your .env is never overwritten by updates. Self-hosted single-operator installs can set SETTINGS_SYNC=true to store UI settings on the server so every device gets the same setup.

Common variables

The complete annotated list lives in .env.example. Highlights:

VariableDefaultDescription
CALLSIGNN0CALLYour callsign — used for DX cluster login, PSKReporter queries, and "my spots" tracking
LOCATORFN31Maidenhead grid (4 or 6 characters); LATITUDE/LONGITUDE override the derived coordinates
PORT3001 (dev)Backend port. Containers run on 3000; in dev, Vite owns 3000 and proxies /api to 3001
HOSTlocalhostSet 0.0.0.0 to allow other devices on your LAN
THEME / LAYOUTdark / modernStartup theme (dark, light, legacy, retro) and layout (modern, classic)
DISTUNITS / TEMPUNITS / PRESSUNITSimperialDistance, temperature, and pressure units (imperial or metric); UNITS is deprecated
TIME_FORMAT1212 or 24 hour clock
SETTINGS_SYNCfalseStore all UI settings server-side (single-operator self-host only)
WSJTX_ENABLEDtrueWSJT-X/JTDX UDP listener (legacy name WSJTX_UDP_ENABLED still honored)
WSJTX_UDP_PORT2237Must match WSJT-X Settings → Reporting → UDP Server
WSJTX_MULTICAST_ADDRESS(none)Set when WSJT-X broadcasts to a multicast group (e.g. 224.0.0.1)
WSJTX_RELAY_KEY(none)Shared secret for the WSJT-X relay agent (cloud deployments only)
AUTO_UPDATE_ENABLEDfalsePeriodic git self-update (legacy name AUTO_UPDATE still honored)
AUTO_UPDATE_INTERVAL_MINUTES60Update check interval (legacy name AUTO_UPDATE_INTERVAL still honored)
DX_CLUSTER_SOURCEautoauto, proxy, hamqth, or dxspider; see the manual
DX_CLUSTER_CALLSIGNCALLSIGN-56Cluster login (use -57 for a second/staging instance)
SPOT_RETENTION_MINUTES30How long DX spots stay in the list (5–30)
APRS_ENABLEDfalseRead-only APRS-IS feed; filter with APRS_FILTER (e.g. r/40.12/-74.82/500)
N1MM_UDP_ENABLEDfalseContest logger UDP listener on N1MM_UDP_PORT (12060) — see docs/N1MM-SETUP.md
QRZ_USERNAME/QRZ_PASSWORD, HAMQTH_USERNAME/HAMQTH_PASSWORD(none)Optional callbook credentials for better callsign lookups
OPENWEATHER_API_KEY(none)Only needed for the Cloud Layer map overlay (also set VITE_OPENWEATHER_API_KEY)
API_WRITE_KEY(none)Protects write endpoints — required for public/cloud deployments
METRICS_AUTH_KEY(none)Bearer-token auth for the Prometheus /metrics endpoint
CELESTRAK_ENABLED / AMSAT_TLE_ENABLED / SATNOGS_TLE_ENABLEDtrueSatellite element-set sources; SPACE_TRACK_USERNAME/_PASSWORD enable Space-Track as primary
ITURHFPROP_URL(built-in)External ITU-R P.533 service — only if self-hosting iturhfprop-service/
WINLINK_API_KEY(none)Winlink gateway proxy (cloud deployments; local installs use the rig-bridge plugin instead)

API Overview

The backend exposes a JSON REST API under /api, heavily cached server-side to be kind to upstream services. Notable endpoints:

EndpointDescription
GET /api/config, GET /api/versionStation config and lightweight version check (drives the update toast)
GET /api/healthLive server dashboard — uptime, visitors, sessions, per-endpoint traffic (?format=json for raw data)
GET /api/dxcluster/spots, /paths, /sourcesDX cluster spots, map paths, and available source backends
POST /api/dxcluster/spotSubmit a spot to the OHC cluster
GET /api/pota/spots, /api/sota/spots, /api/wwff/spotsActivator spots (1–2 min cache)
GET /api/solar-indices, /api/noaa/xray, /api/noaa/aurora, /api/drap, /api/swpc/alertsSpace weather feeds
GET /api/n0nbhN0NBH band conditions
GET /api/propagation, /heatmap, /mufmapPoint-to-point prediction, world heatmap, MUF map
GET /api/p533-data/:fileITU-R P.533 coefficient tables for the in-browser WASM engine
GET /api/satellites/dataMerged satellite element sets (CelesTrak / AMSAT / SatNOGS / Space-Track)
GET /api/callsign/:call, /api/ctyCallsign lookup and the AD1C cty.dat prefix database
GET /api/rbn/spots, /api/wspr/heatmapReverse Beacon Network spots and WSPR heatmap
GET /api/pskreporter/stream/:idLive PSKReporter spots over SSE (server-side MQTT proxy)
GET /api/wsjtx/decodes, POST /api/wsjtx/relayWSJT-X decodes and the cloud relay ingest
GET /api/contests, /api/dxpeditions, /api/dxnewsContest calendar, DXpeditions, DX news
GET/POST /api/contest/qsosN1MM/DXLog contest QSOs (UDP-fed, plus HTTP ingest)
GET /api/aprs/stations, /messages, /telemetry, /netAPRS stations, messaging, telemetry, net roster
GET /api/emcomm/alerts, /shelters, /disastersNWS alerts, FEMA shelters and disaster declarations
GET /api/winlink/gatewaysWinlink RMS gateways (needs WINLINK_API_KEY server-side)
GET /api/websdr/receiversNearest live KiwiSDR/WebSDR receivers for click-to-listen
GET /api/aircraft, /api/atc/sectorsADS-B aircraft (adsb.lol) and ATC sector boundaries
GET /metricsPrometheus metrics (optionally gated by METRICS_AUTH_KEY)

Write endpoints (settings, rig, rotator, spot submission, etc.) are rate-limited and honor API_WRITE_KEY when set.


Architecture

React 18 + Vite frontend, Express backend. The backend is an API proxy and data aggregator — external calls are cached server-side so any number of browsers add near-zero upstream load. Real-time data flows over SSE (DX cluster, PSKReporter, RBN), UDP (WSJT-X, N1MM), and a server-side MQTT proxy.

Companion services in this repo:

DirectoryService
rig-bridge/Local rig control bridge — 20+ plugins (radios, digital modes, APRS TNC, rotator, Winlink)
ohc-cluster/OpenHamClock's own DX cluster node (telnet :7300 + HTTP), aggregating RBN, HamQTH, POTA/SOTA/WWFF, Parks n Peaks, DX Summit, and user spots
dxspider-proxy/Persistent telnet connection to the DX Spider network, served over HTTP
iturhfprop-service/ITU-R P.533-14 propagation engine as a REST API (self-host alternative)
wasm-build/Builds the P.533 engine to WebAssembly for in-browser predictions
wsjtx-relay/WSJT-X UDP → HTTPS relay for cloud-hosted instances
fletcher/TLE fetch egress proxy used by the hosted deployment
watchtower/Cloudflare Worker uptime probe

Full codebase map: docs/ARCHITECTURE.md


Updating

  • Hosted site — nothing to do; a toast appears when a new version deploys.
  • Git installs./scripts/update.sh (Linux/macOS/Pi) or .\scripts\update.ps1 (Windows), then restart. Local installs also get an UPDATE button in the header. Optional auto-update via AUTO_UPDATE_ENABLED=true.
  • Dockerdocker compose pull && docker compose up -d.
  • Railway — push to the connected repo, or railway up.

The update scripts back up .env, pull, rebuild, and restore .env — your configuration is never lost.


FAQ

Do I need a license to use OpenHamClock? No — it's a receive-only dashboard. A callsign makes PSKReporter "my signal" views and cluster login meaningful, but anyone can watch spots and space weather.

Can multiple people use one server? Yes. Each browser keeps its own settings, filters, and DX target; the server cache means extra users add no upstream load. Shared-station operators can use Profiles (Settings → Profiles) to switch setups.

Why don't I see DX spots / PSK reports? Make sure your callsign is set. PSKReporter falls back from the live stream to HTTP automatically; check the panel footer for the active method. For clusters, check the server console and any custom DXSPIDER_PROXY_URL.

Emoji show as boxes on Linux/Pi? Install a color emoji font on the machine running the browser: sudo apt install fonts-noto-color-emoji, then restart the browser. The Pi setup script does this automatically.

Where's the .env file? In the repo root, hidden by the leading dot — ls -la shows it. Run npm start once and it's created from .env.example automatically.

More Q&A throughout the User Manual.


Monitoring

OpenHamClock exposes a Prometheus-compatible endpoint at /metrics (optionally protected with METRICS_AUTH_KEY as a bearer token) and a human-friendly health dashboard at /api/health.


Contributing

OpenHamClock is built by the ham radio community — 40+ contributors and growing. Whether it's a bug fix, a new panel, a map layer plugin, or better docs, PRs are welcome.

git clone https://github.com/accius/openhamclock.git
cd openhamclock
git checkout Staging
npm ci
node server.js # Terminal 1 — Backend on :3001
npm run dev # Terminal 2 — Frontend on :3000

Open pull requests against Staging, not main. Read CONTRIBUTING.md for the workflow, code style, and the documentation policy, and docs/ARCHITECTURE.md for the codebase map.

Community:


Credits

  • K0CJH (Chris Hetherington) — Creator and maintainer — chris@cjhlighting.com
  • Elwood Downey, WB0OEW (SK) — Creator of the original HamClock that inspired this project. OpenHamClock is dedicated to his memory.
  • Claude AI (Anthropic) — Accelerated development by assisting with bug fixes, code structure, and feature implementation
  • Keith, G6NHU — DX Spider cluster operator at dxspider.co.uk
  • NOAA Space Weather Prediction Center — Space weather data (SFI, Kp, SSN, X-ray flux, aurora, D-RAP)
  • N0NBH (Paul Herrman) — Real-time band conditions data feed
  • POTA / SOTA / WWFF / WWBOTA — Activator spot APIs
  • PSKReporter — Digital mode reception report network
  • Reverse Beacon Network — CW/RTTY/FT skimmer spots
  • Open-Meteo — Free weather API
  • Leaflet — Open-source mapping library
  • CelesTrak · AMSAT · SatNOGS — Satellite orbital element data
  • NASA — Imagery, EONET hazards data, and the ISS 3D model (NASA/VTAD)
  • KC2G / GIRO — Ionospheric sounding data (acknowledgements)
  • AD1C — cty.dat DXCC entity database
  • NG3K — DXpedition listing
  • DXNews.com / DX-World — DX news headlines
  • WA7BNM — Contest calendar data
  • adsb.lol — Community ADS-B aircraft feed

And thank you to every contributor — the full wall lives in the app under Settings → Community.


License

MIT License — See LICENSE file.


73 de K0CJH openhamclock.com · chris@cjhlighting.com

About

"The original HamClock will cease to function in June 2026. OpenHamClock aims to carry on Elwood's legacy with a modern, open-source implementation that the community can maintain and improve together."

Resources

Code of conduct

Contributing

Security policy

Stars

462 stars

Watchers

19 watching

Forks

Releases

Packages

Used by

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Latest commit

History

2,921 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

OpenHamClock

A real-time amateur radio dashboard for the modern operator.

OpenHamClock brings DX cluster spots, space weather, propagation predictions, POTA/SOTA/WWFF/WWBOTA activations, PSKReporter, satellite tracking, WSJT-X integration, direct rig control, an in-browser logbook, and a full emergency-communications mode into a single browser-based interface. Run it locally on a Raspberry Pi, on your desktop, in Docker, or just use the hosted site.

🌐 Live Site:openhamclock.com

📧 Contact: Chris, K0CJH — chris@cjhlighting.com

☕ Support the Project:buymeacoffee.com/k0cjh — Running openhamclock.com comes with real hosting costs including network egress, memory, CPU, and the time spent maintaining and improving the project. There is absolutely no obligation to donate — OpenHamClock is and always will be free. But if you find it useful and want to chip in, your donations are greatly appreciated and go directly toward keeping the site running and funding future development.

🔧 Get Involved: This is an open-source project and the amateur radio community is encouraged to dig into the code, fork it, and build the features you want to see. Whether it's a new panel, a data source integration, or a bug fix — PRs are welcome. See Contributing below.

📝 License: MIT — See LICENSE


Documentation

GuideWhat's in it
Quick StartUse the hosted site, or self-host on Docker, Linux/macOS, Raspberry Pi, Windows, Railway
User ManualEvery panel, map layer, keyboard shortcut, and setting explained
Docker GuideCompose, Portainer, persistence, reverse proxies
RoadmapProject history and what's coming
ContributingDev setup, code style, PR workflow
TestingUnit test guide
Security PolicyVulnerability disclosure
ArchitectureCodebase map for contributors

Release notes live in the app itself: click the version number in the header to open What's New.


Feature Highlights

  • Interactive world map in three projections — flat (Mercator), azimuthal-equidistant centered on your QTH, and a full 3D globe with real satellite models — with a dozen basemap styles and ~28 toggleable overlay layers (gray line, aurora, MUF, D-RAP, lightning, satellites, RBN, WSPR, Maidenhead grid, CQ/ITU zones, aircraft, and more), most with single-key shortcuts.
  • DX cluster spots from OpenHamClock's own cluster node (RBN + HamQTH + POTA/SOTA/WWFF + user spots, deduplicated), with band/mode/zone/watchlist filtering, worked-before and dupe badges from your log, click-to-tune, and click-to-listen via the nearest live KiwiSDR.
  • Activations — live POTA, SOTA, WWFF, and WWBOTA activator panels with map markers.
  • Native logbook — QSOs stored in your browser (IndexedDB), ADIF import/export, log-from-spot, and worked-before integration across all spot panels.
  • Propagation — browser-side ITU-R P.533-14 (VOACAP-class) predictions via WebAssembly, point-to-point reliability charts, world heatmap, MUF map, band conditions, and ionosonde-corrected real-time data.
  • Space weather — SFI/Kp/SSN with history, GOES X-ray flux, NOAA SWPC alerts, aurora forecast, solar imagery, lunar phase.
  • Satellite tracking — SGP4 tracking of amateur satellites from CelesTrak/AMSAT/SatNOGS (optionally Space-Track), orbit tracks, footprints, pass info, and 3D models on the globe.
  • Rig control — click any spot and your radio tunes, via the Rig Bridge (Yaesu, Kenwood, Icom, Elecraft, FlexRadio, flrig, rigctld, and more) with a cloud relay for hosted use.
  • Digital modes — WSJT-X/JTDX decodes on the map (UDP or cloud relay), JS8Call/MSHV control, PSKReporter TX/RX reports in real time.
  • Contest tools — contest calendar, N1MM+/DXLog QSOs plotted live on the map, band plan overlay on the rig display.
  • EmComm layout — ARES/RACES dashboard with APRS (internet + RF via local TNC), net roster, point-to-point messaging, resource token aggregation, telemetry dashboards, NWS alerts, FEMA shelters and disaster declarations, Winlink gateways and Pat client.
  • Meshtastic & MeshCom — mesh network nodes and messages on the map and in dockable panels.
  • Works your way — dockable drag-anywhere layout, Classic (original HamClock style), and EmComm layouts; five themes including a custom theme editor; named profiles; 16 languages; PWA offline mode with cached data.

Quick Start

Just want to use it? Open openhamclock.com, set your callsign and grid, done.

Self-host with Docker:

docker run -d -p 3000:3000 --name openhamclock ghcr.io/accius/openhamclock:latest

Self-host from source (Node.js 22 LTS recommended):

git clone https://github.com/accius/openhamclock.git
cd openhamclock
npm ci
npm start

Open http://localhost:3000. A setup wizard walks you through callsign and grid on first run.

One-line installers for Linux/macOS (scripts/setup.sh), Raspberry Pi kiosk (scripts/setup-pi.sh), and Windows (scripts/setup-windows.ps1) — full commands and per-platform details in the Quick Start guide.

For development with hot reload:

# Terminal 1 — Backend (http://localhost:3001)
node server.js
# Terminal 2 — Frontend (hot reload on http://localhost:3000)
npm run dev

Deployment Matrix

PlatformMethodGuide
Nothing (hosted)openhamclock.comQuick Start
Docker / Portainerdocker compose up -d or ghcr.io/accius/openhamclock:latestdocs/DOCKER.md
Linux / macOS / FreeBSDscripts/setup.sh (add --service for systemd on Linux)Quick Start
Raspberry Pi (3B–5)scripts/setup-pi.sh (--kiosk for a dedicated display)Quick Start
Windowsscripts/setup-windows.ps1Quick Start
Railway (cloud)railway up or connect the GitHub repoQuick Start
Desktop appnpm run electron (experimental)

Hardware: the server side is light (~100–150 MB RAM); it's the browser rendering the map that works a machine. A Pi 4 (2 GB+) or Pi 5 makes a smooth kiosk; a Pi 3B+ is best as a headless server or with Low Memory Mode enabled in Settings. The 3D globe wants WebGL — without it the app falls back to the flat map automatically.


Configuration

All configuration lives in .env (auto-created from .env.example on first run) — and almost everything can also be changed in the in-app Settings panel, which takes priority. The only two lines most people touch:

CALLSIGN=K0CJH
LOCATOR=EN10

Files starting with a dot are hidden by default — ls -la in a terminal, Ctrl+H in a Linux file manager, Cmd+Shift+. in macOS Finder.

Settings priority: browser Settings panel (localStorage) → .env → built-in defaults. Your .env is never overwritten by updates. Self-hosted single-operator installs can set SETTINGS_SYNC=true to store UI settings on the server so every device gets the same setup.

Common variables

The complete annotated list lives in .env.example. Highlights:

VariableDefaultDescription
CALLSIGNN0CALLYour callsign — used for DX cluster login, PSKReporter queries, and "my spots" tracking
LOCATORFN31Maidenhead grid (4 or 6 characters); LATITUDE/LONGITUDE override the derived coordinates
PORT3001 (dev)Backend port. Containers run on 3000; in dev, Vite owns 3000 and proxies /api to 3001
HOSTlocalhostSet 0.0.0.0 to allow other devices on your LAN
THEME / LAYOUTdark / modernStartup theme (dark, light, legacy, retro) and layout (modern, classic)
DISTUNITS / TEMPUNITS / PRESSUNITSimperialDistance, temperature, and pressure units (imperial or metric); UNITS is deprecated
TIME_FORMAT1212 or 24 hour clock
SETTINGS_SYNCfalseStore all UI settings server-side (single-operator self-host only)
WSJTX_ENABLEDtrueWSJT-X/JTDX UDP listener (legacy name WSJTX_UDP_ENABLED still honored)
WSJTX_UDP_PORT2237Must match WSJT-X Settings → Reporting → UDP Server
WSJTX_MULTICAST_ADDRESS(none)Set when WSJT-X broadcasts to a multicast group (e.g. 224.0.0.1)
WSJTX_RELAY_KEY(none)Shared secret for the WSJT-X relay agent (cloud deployments only)
AUTO_UPDATE_ENABLEDfalsePeriodic git self-update (legacy name AUTO_UPDATE still honored)
AUTO_UPDATE_INTERVAL_MINUTES60Update check interval (legacy name AUTO_UPDATE_INTERVAL still honored)
DX_CLUSTER_SOURCEautoauto, proxy, hamqth, or dxspider; see the manual
DX_CLUSTER_CALLSIGNCALLSIGN-56Cluster login (use -57 for a second/staging instance)
SPOT_RETENTION_MINUTES30How long DX spots stay in the list (5–30)
APRS_ENABLEDfalseRead-only APRS-IS feed; filter with APRS_FILTER (e.g. r/40.12/-74.82/500)
N1MM_UDP_ENABLEDfalseContest logger UDP listener on N1MM_UDP_PORT (12060) — see docs/N1MM-SETUP.md
QRZ_USERNAME/QRZ_PASSWORD, HAMQTH_USERNAME/HAMQTH_PASSWORD(none)Optional callbook credentials for better callsign lookups
OPENWEATHER_API_KEY(none)Only needed for the Cloud Layer map overlay (also set VITE_OPENWEATHER_API_KEY)
API_WRITE_KEY(none)Protects write endpoints — required for public/cloud deployments
METRICS_AUTH_KEY(none)Bearer-token auth for the Prometheus /metrics endpoint
CELESTRAK_ENABLED / AMSAT_TLE_ENABLED / SATNOGS_TLE_ENABLEDtrueSatellite element-set sources; SPACE_TRACK_USERNAME/_PASSWORD enable Space-Track as primary
ITURHFPROP_URL(built-in)External ITU-R P.533 service — only if self-hosting iturhfprop-service/
WINLINK_API_KEY(none)Winlink gateway proxy (cloud deployments; local installs use the rig-bridge plugin instead)

API Overview

The backend exposes a JSON REST API under /api, heavily cached server-side to be kind to upstream services. Notable endpoints:

EndpointDescription
GET /api/config, GET /api/versionStation config and lightweight version check (drives the update toast)
GET /api/healthLive server dashboard — uptime, visitors, sessions, per-endpoint traffic (?format=json for raw data)
GET /api/dxcluster/spots, /paths, /sourcesDX cluster spots, map paths, and available source backends
POST /api/dxcluster/spotSubmit a spot to the OHC cluster
GET /api/pota/spots, /api/sota/spots, /api/wwff/spotsActivator spots (1–2 min cache)
GET /api/solar-indices, /api/noaa/xray, /api/noaa/aurora, /api/drap, /api/swpc/alertsSpace weather feeds
GET /api/n0nbhN0NBH band conditions
GET /api/propagation, /heatmap, /mufmapPoint-to-point prediction, world heatmap, MUF map
GET /api/p533-data/:fileITU-R P.533 coefficient tables for the in-browser WASM engine
GET /api/satellites/dataMerged satellite element sets (CelesTrak / AMSAT / SatNOGS / Space-Track)
GET /api/callsign/:call, /api/ctyCallsign lookup and the AD1C cty.dat prefix database
GET /api/rbn/spots, /api/wspr/heatmapReverse Beacon Network spots and WSPR heatmap
GET /api/pskreporter/stream/:idLive PSKReporter spots over SSE (server-side MQTT proxy)
GET /api/wsjtx/decodes, POST /api/wsjtx/relayWSJT-X decodes and the cloud relay ingest
GET /api/contests, /api/dxpeditions, /api/dxnewsContest calendar, DXpeditions, DX news
GET/POST /api/contest/qsosN1MM/DXLog contest QSOs (UDP-fed, plus HTTP ingest)
GET /api/aprs/stations, /messages, /telemetry, /netAPRS stations, messaging, telemetry, net roster
GET /api/emcomm/alerts, /shelters, /disastersNWS alerts, FEMA shelters and disaster declarations
GET /api/winlink/gatewaysWinlink RMS gateways (needs WINLINK_API_KEY server-side)
GET /api/websdr/receiversNearest live KiwiSDR/WebSDR receivers for click-to-listen
GET /api/aircraft, /api/atc/sectorsADS-B aircraft (adsb.lol) and ATC sector boundaries
GET /metricsPrometheus metrics (optionally gated by METRICS_AUTH_KEY)

Write endpoints (settings, rig, rotator, spot submission, etc.) are rate-limited and honor API_WRITE_KEY when set.


Architecture

React 18 + Vite frontend, Express backend. The backend is an API proxy and data aggregator — external calls are cached server-side so any number of browsers add near-zero upstream load. Real-time data flows over SSE (DX cluster, PSKReporter, RBN), UDP (WSJT-X, N1MM), and a server-side MQTT proxy.

Companion services in this repo:

DirectoryService
rig-bridge/Local rig control bridge — 20+ plugins (radios, digital modes, APRS TNC, rotator, Winlink)
ohc-cluster/OpenHamClock's own DX cluster node (telnet :7300 + HTTP), aggregating RBN, HamQTH, POTA/SOTA/WWFF, Parks n Peaks, DX Summit, and user spots
dxspider-proxy/Persistent telnet connection to the DX Spider network, served over HTTP
iturhfprop-service/ITU-R P.533-14 propagation engine as a REST API (self-host alternative)
wasm-build/Builds the P.533 engine to WebAssembly for in-browser predictions
wsjtx-relay/WSJT-X UDP → HTTPS relay for cloud-hosted instances
fletcher/TLE fetch egress proxy used by the hosted deployment
watchtower/Cloudflare Worker uptime probe

Full codebase map: docs/ARCHITECTURE.md


Updating

  • Hosted site — nothing to do; a toast appears when a new version deploys.
  • Git installs./scripts/update.sh (Linux/macOS/Pi) or .\scripts\update.ps1 (Windows), then restart. Local installs also get an UPDATE button in the header. Optional auto-update via AUTO_UPDATE_ENABLED=true.
  • Dockerdocker compose pull && docker compose up -d.
  • Railway — push to the connected repo, or railway up.

The update scripts back up .env, pull, rebuild, and restore .env — your configuration is never lost.


FAQ

Do I need a license to use OpenHamClock? No — it's a receive-only dashboard. A callsign makes PSKReporter "my signal" views and cluster login meaningful, but anyone can watch spots and space weather.

Can multiple people use one server? Yes. Each browser keeps its own settings, filters, and DX target; the server cache means extra users add no upstream load. Shared-station operators can use Profiles (Settings → Profiles) to switch setups.

Why don't I see DX spots / PSK reports? Make sure your callsign is set. PSKReporter falls back from the live stream to HTTP automatically; check the panel footer for the active method. For clusters, check the server console and any custom DXSPIDER_PROXY_URL.

Emoji show as boxes on Linux/Pi? Install a color emoji font on the machine running the browser: sudo apt install fonts-noto-color-emoji, then restart the browser. The Pi setup script does this automatically.

Where's the .env file? In the repo root, hidden by the leading dot — ls -la shows it. Run npm start once and it's created from .env.example automatically.

More Q&A throughout the User Manual.


Monitoring

OpenHamClock exposes a Prometheus-compatible endpoint at /metrics (optionally protected with METRICS_AUTH_KEY as a bearer token) and a human-friendly health dashboard at /api/health.


Contributing

OpenHamClock is built by the ham radio community — 40+ contributors and growing. Whether it's a bug fix, a new panel, a map layer plugin, or better docs, PRs are welcome.

git clone https://github.com/accius/openhamclock.git
cd openhamclock
git checkout Staging
npm ci
node server.js # Terminal 1 — Backend on :3001
npm run dev # Terminal 2 — Frontend on :3000

Open pull requests against Staging, not main. Read CONTRIBUTING.md for the workflow, code style, and the documentation policy, and docs/ARCHITECTURE.md for the codebase map.

Community:


Credits

  • K0CJH (Chris Hetherington) — Creator and maintainer — chris@cjhlighting.com
  • Elwood Downey, WB0OEW (SK) — Creator of the original HamClock that inspired this project. OpenHamClock is dedicated to his memory.
  • Claude AI (Anthropic) — Accelerated development by assisting with bug fixes, code structure, and feature implementation
  • Keith, G6NHU — DX Spider cluster operator at dxspider.co.uk
  • NOAA Space Weather Prediction Center — Space weather data (SFI, Kp, SSN, X-ray flux, aurora, D-RAP)
  • N0NBH (Paul Herrman) — Real-time band conditions data feed
  • POTA / SOTA / WWFF / WWBOTA — Activator spot APIs
  • PSKReporter — Digital mode reception report network
  • Reverse Beacon Network — CW/RTTY/FT skimmer spots
  • Open-Meteo — Free weather API
  • Leaflet — Open-source mapping library
  • CelesTrak · AMSAT · SatNOGS — Satellite orbital element data
  • NASA — Imagery, EONET hazards data, and the ISS 3D model (NASA/VTAD)
  • KC2G / GIRO — Ionospheric sounding data (acknowledgements)
  • AD1C — cty.dat DXCC entity database
  • NG3K — DXpedition listing
  • DXNews.com / DX-World — DX news headlines
  • WA7BNM — Contest calendar data
  • adsb.lol — Community ADS-B aircraft feed

And thank you to every contributor — the full wall lives in the app under Settings → Community.


License

MIT License — See LICENSE file.


73 de K0CJH openhamclock.com · chris@cjhlighting.com

About

"The original HamClock will cease to function in June 2026. OpenHamClock aims to carry on Elwood's legacy with a modern, open-source implementation that the community can maintain and improve together."

Resources

Code of conduct

Contributing

Security policy

Stars

462 stars

Watchers

19 watching

Forks

Releases

Packages

Used by

Contributors

Languages