-
Notifications
You must be signed in to change notification settings - Fork 125
Expand file tree
/
Copy pathindex.html
More file actions
156 lines (145 loc) · 7.79 KB
/
index.html
File metadata and controls
156 lines (145 loc) · 7.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover"
/>
<title>OpenHamClock - Amateur Radio Dashboard | Live DX Cluster, Propagation, Band Conditions</title>
<!-- SEO Meta -->
<meta
name="description"
content="OpenHamClock is a free, real-time amateur radio dashboard with live DX cluster spots, PSK Reporter, Reverse Beacon Network, POTA/SOTA tracking, propagation predictions, solar indices, band conditions, satellite passes, and an interactive world map. Runs on any browser — desktop, Raspberry Pi, tablet, or phone. No login, no ads, no subscription."
/>
<meta
name="keywords"
content="ham clock, hamclock, openhamclock, open ham clock, amateur radio dashboard, ham radio dashboard, DX cluster, DX spots, PSK Reporter, Reverse Beacon Network, RBN, POTA tracker, SOTA tracker, propagation prediction, band conditions, solar flux, K-index, sunspot number, space weather, ham radio map, great circle map, satellite tracker, amateur radio, ham radio, shortwave, HF propagation, MUF map, gray line, greyline, VOACAP, ham radio tools, free ham radio software, web ham clock, raspberry pi ham clock"
/>
<meta name="author" content="Chris Hetherington, K0CJH" />
<meta name="robots" content="index, follow" />
<link rel="canonical" href="https://openhamclock.com/" />
<!-- Open Graph (Facebook, Discord, iMessage, etc.) -->
<meta property="og:type" content="website" />
<meta property="og:url" content="https://openhamclock.com/" />
<meta property="og:title" content="OpenHamClock - Free Amateur Radio Dashboard" />
<meta
property="og:description"
content="Live DX cluster spots, PSK Reporter, RBN skimmer data, POTA/SOTA tracking, propagation predictions, solar indices, band conditions, satellite passes, and an interactive world map — all in one free browser-based dashboard. No login, no ads."
/>
<meta property="og:image" content="https://openhamclock.com/icons/og-image.png" />
<meta property="og:image:width" content="1200" />
<meta property="og:image:height" content="630" />
<meta property="og:site_name" content="OpenHamClock" />
<meta property="og:locale" content="en_US" />
<!-- Twitter Card -->
<meta name="twitter:card" content="summary_large_image" />
<meta name="twitter:title" content="OpenHamClock - Free Amateur Radio Dashboard" />
<meta
name="twitter:description"
content="Live DX spots, PSK Reporter, RBN, POTA/SOTA, propagation, solar data, satellites, and world map — free for every ham. No login, no ads."
/>
<meta name="twitter:image" content="https://openhamclock.com/icons/og-image.png" />
<!-- Favicons (cache-bust with version) -->
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png?v=2" />
<link rel="icon" type="image/x-icon" href="/favicon.ico?v=2" />
<link rel="shortcut icon" href="/favicon.ico?v=2" />
<link rel="icon" type="image/png" sizes="512x512" href="/icons/icon-512.png?v=2" />
<link rel="icon" type="image/png" sizes="192x192" href="/icons/icon-192.png?v=2" />
<!-- JSON-LD Structured Data -->
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "WebApplication",
"name": "OpenHamClock",
"alternateName": ["Ham Clock", "HamClock", "Open Ham Clock", "Open HamClock"],
"url": "https://openhamclock.com",
"description": "Free, real-time amateur radio operations dashboard with live DX cluster spots, PSK Reporter decodes, Reverse Beacon Network data, POTA/SOTA activator tracking, satellite passes, propagation predictions, solar indices, band conditions, space weather, and an interactive world map with great circle paths.",
"applicationCategory": "UtilitiesApplication",
"operatingSystem": "Any (Web Browser)",
"browserRequirements": "Requires a modern web browser",
"offers": {
"@type": "Offer",
"price": "0",
"priceCurrency": "USD"
},
"author": {
"@type": "Person",
"name": "Chris Hetherington",
"callSign": "K0CJH"
},
"sameAs": [
"https://github.com/accius/openhamclock",
"https://www.facebook.com/groups/1217043013897440",
"https://www.reddit.com/r/OpenHamClock/"
],
"isAccessibleForFree": true,
"keywords": "ham clock, amateur radio dashboard, DX cluster, PSK Reporter, propagation, band conditions, POTA, SOTA, ham radio map"
}
</script>
<!-- PWA -->
<link rel="manifest" href="/manifest.json" />
<meta name="theme-color" content="#0a0e14" />
<meta name="color-scheme" content="dark light" />
<!-- iOS PWA (Add to Home Screen → fullscreen standalone) -->
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="apple-mobile-web-app-title" content="OpenHamClock" />
<link rel="apple-touch-icon" sizes="180x180" href="/icons/apple-touch-icon.png?v=2" />
<!-- Android -->
<meta name="mobile-web-app-capable" content="yes" />
<!-- Fonts (self-hosted for privacy — run: bash scripts/vendor-download.sh) -->
<link href="/vendor/fonts/fonts.css" rel="stylesheet" />
<!-- Leaflet CSS (self-hosted) -->
<link rel="stylesheet" href="/vendor/leaflet/leaflet.css" />
<!-- Leaflet JS (self-hosted) -->
<script src="/vendor/leaflet/leaflet.js"></script>
</head>
<body>
<div id="root"></div>
<script>
// Detect stale JS chunks after an update and force-reload once.
// After a server update, browsers may have old hashed JS cached.
// Old chunks import new chunks (or vice versa) → module error → blank screen.
// This catches that and reloads to get the fresh index.html + new chunk URLs.
window.addEventListener('error', function (e) {
var msg = (e.message || '') + ' ' + ((e.filename || '') + '');
if (
msg.indexOf('Failed to fetch dynamically imported module') !== -1 ||
msg.indexOf('Importing a module script failed') !== -1 ||
msg.indexOf('error loading dynamically imported module') !== -1 ||
msg.indexOf('ChunkLoadError') !== -1 ||
msg.indexOf('Loading chunk') !== -1 ||
(e.filename && e.filename.indexOf('/assets/') !== -1 && msg.indexOf('SyntaxError') !== -1)
) {
// Only auto-reload once to prevent infinite loops
if (!sessionStorage.getItem('ohc_chunk_reload')) {
sessionStorage.setItem('ohc_chunk_reload', '1');
console.warn('[OpenHamClock] Stale JS detected after update — reloading...');
window.location.reload();
}
}
});
// Clear the reload flag on successful load
window.addEventListener('load', function () {
sessionStorage.removeItem('ohc_chunk_reload');
});
// Also catch dynamic import() failures (rejected promises)
window.addEventListener('unhandledrejection', function (e) {
var msg = (e.reason && e.reason.message) || '';
if (
msg.indexOf('Failed to fetch dynamically imported module') !== -1 ||
msg.indexOf('Importing a module script failed') !== -1 ||
msg.indexOf('error loading dynamically imported module') !== -1
) {
if (!sessionStorage.getItem('ohc_chunk_reload')) {
sessionStorage.setItem('ohc_chunk_reload', '1');
console.warn('[OpenHamClock] Stale module detected — reloading...');
window.location.reload();
}
}
});
</script>
<script type="module" src="/src/main.jsx"></script>
</body>
</html>