hlarcher HF Staff commited on
Commit
02d3589
·
unverified ·
1 Parent(s): 5b026eb

refactor: improve layout and styling for bandwidth test interface. Handle auto-stop

Browse files
src/app.css CHANGED
@@ -2,29 +2,33 @@
2
  @plugin '@tailwindcss/typography';
3
 
4
  .progress-bar {
5
- height: 9px;
6
- border-radius: 4px;
7
- background: linear-gradient(90deg, #4f46e5 0%, #10b981 50%, #f59e0b 100%);
8
- transition: width 0.3s ease;
9
  }
10
  .wave {
11
- position: relative;
12
- overflow: hidden;
13
  }
14
  .wave::after {
15
- content: "";
16
- position: absolute;
17
- top: 0;
18
- left: 0;
19
- right: 0;
20
- bottom: 0;
21
- background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
22
- animation: wave 2s linear infinite;
23
  }
24
  @keyframes wave {
25
- 0% { transform: translateX(-100%); }
26
- 100% { transform: translateX(100%); }
 
 
 
 
27
  }
28
  .glow {
29
- box-shadow: 0 0 15px rgba(79, 70, 229, 0.5);
30
- }
 
2
  @plugin '@tailwindcss/typography';
3
 
4
  .progress-bar {
5
+ height: 9px;
6
+ border-radius: 4px;
7
+ background: linear-gradient(90deg, #4f46e5 0%, #10b981 50%, #f59e0b 100%);
8
+ transition: width 0.3s ease;
9
  }
10
  .wave {
11
+ position: relative;
12
+ overflow: hidden;
13
  }
14
  .wave::after {
15
+ content: '';
16
+ position: absolute;
17
+ top: 0;
18
+ left: 0;
19
+ right: 0;
20
+ bottom: 0;
21
+ background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
22
+ animation: wave 2s linear infinite;
23
  }
24
  @keyframes wave {
25
+ 0% {
26
+ transform: translateX(-100%);
27
+ }
28
+ 100% {
29
+ transform: translateX(100%);
30
+ }
31
  }
32
  .glow {
33
+ box-shadow: 0 0 15px rgba(79, 70, 229, 0.5);
34
+ }
src/app.html CHANGED
@@ -1,18 +1,18 @@
1
  <!doctype html>
2
  <html lang="en">
3
- <head>
4
- <meta charset="utf-8" />
5
- <title>Hugging Face bandwidth test</title>
6
- <meta name="viewport" content="width=device-width, initial-scale=1" />
7
- <link rel="icon" type="image/png" href="%sveltekit.assets%/favicon-96x96.png" sizes="96x96" />
8
- <link rel="icon" type="image/svg+xml" href="%sveltekit.assets%/favicon.svg" />
9
- <link rel="shortcut icon" href="%sveltekit.assets%/favicon.ico" />
10
- <link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/apple-touch-icon.png" />
11
- <meta name="apple-mobile-web-app-title" content="Hugging Face fast" />
12
- <link rel="manifest" href="%sveltekit.assets%/site.webmanifest" />
13
- %sveltekit.head%
14
- </head>
15
- <body data-sveltekit-preload-data="hover" class="bg-gray-50 min-h-screen">
16
- <div class="container mx-auto px-4 py-8">%sveltekit.body%</div>
17
- </body>
18
  </html>
 
1
  <!doctype html>
2
  <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <title>Hugging Face bandwidth test</title>
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+ <link rel="icon" type="image/png" href="%sveltekit.assets%/favicon-96x96.png" sizes="96x96" />
8
+ <link rel="icon" type="image/svg+xml" href="%sveltekit.assets%/favicon.svg" />
9
+ <link rel="shortcut icon" href="%sveltekit.assets%/favicon.ico" />
10
+ <link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/apple-touch-icon.png" />
11
+ <meta name="apple-mobile-web-app-title" content="Hugging Face fast" />
12
+ <link rel="manifest" href="%sveltekit.assets%/site.webmanifest" />
13
+ %sveltekit.head%
14
+ </head>
15
+ <body data-sveltekit-preload-data="hover" class="min-h-screen bg-gray-50">
16
+ <div class="container mx-auto px-4 py-8">%sveltekit.body%</div>
17
+ </body>
18
  </html>
src/lib/icao.ts CHANGED
@@ -7,230 +7,229 @@ type MajorAirportIATAsWithCountry = {
7
  [iataCode: string]: AirportDetails;
8
  };
9
 
10
- export const majorAirportIATAs:MajorAirportIATAsWithCountry = {
11
- // USA
12
- "LAX": { "city": "Los Angeles", "country": "US" },
13
- "JFK": { "city": "New York", "country": "US" },
14
- "ORD": { "city": "Chicago", "country": "US" },
15
- "ATL": { "city": "Atlanta", "country": "US" },
16
- "DFW": { "city": "Dallas", "country": "US" },
17
- "DEN": { "city": "Denver", "country": "US" },
18
- "SFO": { "city": "San Francisco", "country": "US" },
19
- "SEA": { "city": "Seattle", "country": "US" },
20
- "MIA": { "city": "Miami", "country": "US" },
21
- "LAS": { "city": "Las Vegas", "country": "US" },
22
- "MCO": { "city": "Orlando", "country": "US" },
23
- "EWR": { "city": "Newark", "country": "US" },
24
- "CLT": { "city": "Charlotte", "country": "US" },
25
- "PHX": { "city": "Phoenix", "country": "US" },
26
- "IAH": { "city": "Houston", "country": "US" },
27
- "BOS": { "city": "Boston", "country": "US" },
28
- "MSP": { "city": "Minneapolis", "country": "US" },
29
- "DTW": { "city": "Detroit", "country": "US" },
30
- "PHL": { "city": "Philadelphia", "country": "US" },
31
- "LGA": { "city": "New York", "country": "US" },
32
- "BWI": { "city": "Baltimore", "country": "US" },
33
- "SLC": { "city": "Salt Lake City", "country": "US" },
34
- "IAD": { "city": "Washington D.C.", "country": "US" },
35
- "DCA": { "city": "Washington D.C.", "country": "US" },
36
- "SAN": { "city": "San Diego", "country": "US" },
37
- "TPA": { "city": "Tampa", "country": "US" },
38
- "HNL": { "city": "Honolulu", "country": "US" },
39
- // Canada
40
- "YYZ": { "city": "Toronto", "country": "CA" },
41
- "YVR": { "city": "Vancouver", "country": "CA" },
42
- "YUL": { "city": "Montreal", "country": "CA" },
43
- "YYC": { "city": "Calgary", "country": "CA" },
44
- "YEG": { "city": "Edmonton", "country": "CA" },
45
- "YOW": { "city": "Ottawa", "country": "CA" },
46
- "YWG": { "city": "Winnipeg", "country": "CA" },
47
- "YHZ": { "city": "Halifax", "country": "CA" },
48
- // United Kingdom
49
- "LHR": { "city": "London", "country": "GB" },
50
- "LGW": { "city": "London", "country": "GB" },
51
- "STN": { "city": "London", "country": "GB" },
52
- "LTN": { "city": "London", "country": "GB" },
53
- "MAN": { "city": "Manchester", "country": "GB" },
54
- "BHX": { "city": "Birmingham", "country": "GB" },
55
- "EDI": { "city": "Edinburgh", "country": "GB" },
56
- "GLA": { "city": "Glasgow", "country": "GB" },
57
- // France
58
- "CDG": { "city": "Paris", "country": "FR" },
59
- "ORY": { "city": "Paris", "country": "FR" },
60
- "NCE": { "city": "Nice", "country": "FR" },
61
- "LYS": { "city": "Lyon", "country": "FR" },
62
- "MRS": { "city": "Marseille", "country": "FR" },
63
- "TLS": { "city": "Toulouse", "country": "FR" },
64
- "NTE": { "city": "Nantes", "country": "FR" },
65
- "BOD": { "city": "Bordeaux", "country": "FR" },
66
- // Germany
67
- "FRA": { "city": "Frankfurt", "country": "DE" },
68
- "MUC": { "city": "Munich", "country": "DE" },
69
- "BER": { "city": "Berlin", "country": "DE" },
70
- "DUS": { "city": "Düsseldorf", "country": "DE" },
71
- "HAM": { "city": "Hamburg", "country": "DE" },
72
- "CGN": { "city": "Cologne", "country": "DE" },
73
- "STR": { "city": "Stuttgart", "country": "DE" },
74
- // China (Mainland)
75
- "PEK": { "city": "Beijing", "country": "CN" },
76
- "PKX": { "city": "Beijing", "country": "CN" },
77
- "PVG": { "city": "Shanghai", "country": "CN" },
78
- "SHA": { "city": "Shanghai", "country": "CN" },
79
- "CAN": { "city": "Guangzhou", "country": "CN" },
80
- "CTU": { "city": "Chengdu", "country": "CN" }, // Shuangliu
81
- "TFU": { "city": "Chengdu", "country": "CN" }, // Tianfu
82
- "SZX": { "city": "Shenzhen", "country": "CN" },
83
- "CKG": { "city": "Chongqing", "country": "CN" },
84
- "WUH": { "city": "Wuhan", "country": "CN" },
85
- "XIY": { "city": "Xi'an", "country": "CN" },
86
- "HGH": { "city": "Hangzhou", "country": "CN" },
87
- // India
88
- "DEL": { "city": "Delhi", "country": "IN" },
89
- "BOM": { "city": "Mumbai", "country": "IN" },
90
- "BLR": { "city": "Bengaluru", "country": "IN" },
91
- "MAA": { "city": "Chennai", "country": "IN" },
92
- "CCU": { "city": "Kolkata", "country": "IN" },
93
- "HYD": { "city": "Hyderabad", "country": "IN" },
94
- // Brazil
95
- "GRU": { "city": "Sao Paulo", "country": "BR" },
96
- "GIG": { "city": "Rio de Janeiro", "country": "BR" },
97
- "BSB": { "city": "Brasilia", "country": "BR" },
98
- "CNF": { "city": "Belo Horizonte", "country": "BR" },
99
- "SSA": { "city": "Salvador", "country": "BR" },
100
- "FOR": { "city": "Fortaleza", "country": "BR" },
101
- "POA": { "city": "Porto Alegre", "country": "BR" },
102
- "REC": { "city": "Recife", "country": "BR" },
103
- "CWB": { "city": "Curitiba", "country": "BR" },
104
- // Australia
105
- "SYD": { "city": "Sydney", "country": "AU" },
106
- "MEL": { "city": "Melbourne", "country": "AU" },
107
- "BNE": { "city": "Brisbane", "country": "AU" },
108
- "PER": { "city": "Perth", "country": "AU" },
109
- "ADL": { "city": "Adelaide", "country": "AU" },
110
- "CBR": { "city": "Canberra", "country": "AU" },
111
- // Japan
112
- "NRT": { "city": "Tokyo", "country": "JP" }, // Narita
113
- "HND": { "city": "Tokyo", "country": "JP" }, // Haneda
114
- "KIX": { "city": "Osaka", "country": "JP" }, // Kansai
115
- "ITM": { "city": "Osaka", "country": "JP" }, // Itami
116
- "CTS": { "city": "Sapporo", "country": "JP" }, // New Chitose
117
- "FUK": { "city": "Fukuoka", "country": "JP" },
118
- "OKA": { "city": "Okinawa", "country": "JP" }, // Naha
119
- "NGO": { "city": "Nagoya", "country": "JP" }, // Chubu Centrair
120
- // South Africa
121
- "JNB": { "city": "Johannesburg", "country": "ZA" },
122
- "CPT": { "city": "Cape Town", "country": "ZA" },
123
- "DUR": { "city": "Durban", "country": "ZA" }, // King Shaka
124
- // Netherlands
125
- "AMS": { "city": "Amsterdam", "country": "NL" },
126
- // Spain
127
- "MAD": { "city": "Madrid", "country": "ES" },
128
- "BCN": { "city": "Barcelona", "country": "ES" },
129
- "PMI": { "city": "Palma de Mallorca", "country": "ES" },
130
- "AGP": { "city": "Malaga", "country": "ES" },
131
- "VLC": { "city": "Valencia", "country": "ES" },
132
- // Italy
133
- "FCO": { "city": "Rome", "country": "IT" }, // Fiumicino
134
- "MXP": { "city": "Milan", "country": "IT" }, // Malpensa
135
- "LIN": { "city": "Milan", "country": "IT" }, // Linate
136
- "BLQ": { "city": "Bologna", "country": "IT" },
137
- "NAP": { "city": "Naples", "country": "IT" },
138
- "VCE": { "city": "Venice", "country": "IT" }, // Marco Polo
139
- "PSA": { "city": "Pisa", "country": "IT" },
140
- // Russia
141
- "SVO": { "city": "Moscow", "country": "RU" }, // Sheremetyevo
142
- "DME": { "city": "Moscow", "country": "RU" }, // Domodedovo
143
- "VKO": { "city": "Moscow", "country": "RU" }, // Vnukovo
144
- "LED": { "city": "Saint Petersburg", "country": "RU" }, // Pulkovo
145
- "AER": { "city": "Sochi", "country": "RU" },
146
- // United Arab Emirates
147
- "DXB": { "city": "Dubai", "country": "AE" },
148
- "AUH": { "city": "Abu Dhabi", "country": "AE" },
149
- // Singapore
150
- "SIN": { "city": "Singapore", "country": "SG" },
151
- // Hong Kong
152
- "HKG": { "city": "Hong Kong", "country": "HK" },
153
- // South Korea
154
- "ICN": { "city": "Seoul", "country": "KR" }, // Incheon
155
- "GMP": { "city": "Seoul", "country": "KR" }, // Gimpo
156
- "CJU": { "city": "Jeju", "country": "KR" },
157
- // Turkey
158
- "IST": { "city": "Istanbul", "country": "TR" }, // Istanbul Airport
159
- "SAW": { "city": "Istanbul", "country": "TR" }, // Sabiha Gökçen
160
- "AYT": { "city": "Antalya", "country": "TR" },
161
- "ESB": { "city": "Ankara", "country": "TR" },
162
- "ADB": { "city": "Izmir", "country": "TR" },
163
- // Switzerland
164
- "ZRH": { "city": "Zurich", "country": "CH" },
165
- "GVA": { "city": "Geneva", "country": "CH" },
166
- // Argentina
167
- "EZE": { "city": "Buenos Aires", "country": "AR" }, // Ezeiza
168
- "AEP": { "city": "Buenos Aires", "country": "AR" }, // Aeroparque
169
- // Mexico
170
- "MEX": { "city": "Mexico City", "country": "MX" },
171
- "CUN": { "city": "Cancun", "country": "MX" },
172
- "GDL": { "city": "Guadalajara", "country": "MX" },
173
- "MTY": { "city": "Monterrey", "country": "MX" },
174
- // Thailand
175
- "BKK": { "city": "Bangkok", "country": "TH" }, // Suvarnabhumi
176
- "DMK": { "city": "Bangkok", "country": "TH" }, // Don Mueang
177
- "HKT": { "city": "Phuket", "country": "TH" },
178
- "CNX": { "city": "Chiang Mai", "country": "TH" },
179
- // Malaysia
180
- "KUL": { "city": "Kuala Lumpur", "country": "MY" },
181
- // Ireland
182
- "DUB": { "city": "Dublin", "country": "IE" },
183
- "SNN": { "city": "Shannon", "country": "IE" },
184
- // Portugal
185
- "LIS": { "city": "Lisbon", "country": "PT" },
186
- "OPO": { "city": "Porto", "country": "PT" },
187
- "FAO": { "city": "Faro", "country": "PT" },
188
- // New Zealand
189
- "AKL": { "city": "Auckland", "country": "NZ" },
190
- "CHC": { "city": "Christchurch", "country": "NZ" },
191
- "WLG": { "city": "Wellington", "country": "NZ" },
192
- // Qatar
193
- "DOH": { "city": "Doha", "country": "QA" },
194
- // Saudi Arabia
195
- "JED": { "city": "Jeddah", "country": "SA" },
196
- "RUH": { "city": "Riyadh", "country": "SA" },
197
- "DMM": { "city": "Dammam", "country": "SA" },
198
- // Egypt
199
- "CAI": { "city": "Cairo", "country": "EG" },
200
- // Nigeria
201
- "LOS": { "city": "Lagos", "country": "NG" },
202
- "ABV": { "city": "Abuja", "country": "NG" },
203
- // Kenya
204
- "NBO": { "city": "Nairobi", "country": "KE" }, // Jomo Kenyatta
205
- // Ethiopia
206
- "ADD": { "city": "Addis Ababa", "country": "ET" },
207
- // Colombia
208
- "BOG": { "city": "Bogota", "country": "CO" },
209
- "MDE": { "city": "Medellin", "country": "CO" }, // José María Córdova
210
- // Chile
211
- "SCL": { "city": "Santiago", "country": "CL" },
212
- // Peru
213
- "LIM": { "city": "Lima", "country": "PE" },
214
- // Austria
215
- "VIE": { "city": "Vienna", "country": "AT" },
216
- // Belgium
217
- "BRU": { "city": "Brussels", "country": "BE" },
218
- // Czech Republic
219
- "PRG": { "city": "Prague", "country": "CZ" },
220
- // Denmark
221
- "CPH": { "city": "Copenhagen", "country": "DK" },
222
- // Finland
223
- "HEL": { "city": "Helsinki", "country": "FI" },
224
- // Greece
225
- "ATH": { "city": "Athens", "country": "GR" },
226
- // Hungary
227
- "BUD": { "city": "Budapest", "country": "HU" },
228
- // Norway
229
- "OSL": { "city": "Oslo", "country": "NO" },
230
- // Poland
231
- "WAW": { "city": "Warsaw", "country": "PL" }, // Chopin
232
- "KRK": { "city": "Krakow", "country": "PL" },
233
- // Sweden
234
- "ARN": { "city": "Stockholm", "country": "SE" } // Arlanda
235
- };
236
-
 
7
  [iataCode: string]: AirportDetails;
8
  };
9
 
10
+ export const majorAirportIATAs: MajorAirportIATAsWithCountry = {
11
+ // USA
12
+ LAX: { city: 'Los Angeles', country: 'US' },
13
+ JFK: { city: 'New York', country: 'US' },
14
+ ORD: { city: 'Chicago', country: 'US' },
15
+ ATL: { city: 'Atlanta', country: 'US' },
16
+ DFW: { city: 'Dallas', country: 'US' },
17
+ DEN: { city: 'Denver', country: 'US' },
18
+ SFO: { city: 'San Francisco', country: 'US' },
19
+ SEA: { city: 'Seattle', country: 'US' },
20
+ MIA: { city: 'Miami', country: 'US' },
21
+ LAS: { city: 'Las Vegas', country: 'US' },
22
+ MCO: { city: 'Orlando', country: 'US' },
23
+ EWR: { city: 'Newark', country: 'US' },
24
+ CLT: { city: 'Charlotte', country: 'US' },
25
+ PHX: { city: 'Phoenix', country: 'US' },
26
+ IAH: { city: 'Houston', country: 'US' },
27
+ BOS: { city: 'Boston', country: 'US' },
28
+ MSP: { city: 'Minneapolis', country: 'US' },
29
+ DTW: { city: 'Detroit', country: 'US' },
30
+ PHL: { city: 'Philadelphia', country: 'US' },
31
+ LGA: { city: 'New York', country: 'US' },
32
+ BWI: { city: 'Baltimore', country: 'US' },
33
+ SLC: { city: 'Salt Lake City', country: 'US' },
34
+ IAD: { city: 'Washington D.C.', country: 'US' },
35
+ DCA: { city: 'Washington D.C.', country: 'US' },
36
+ SAN: { city: 'San Diego', country: 'US' },
37
+ TPA: { city: 'Tampa', country: 'US' },
38
+ HNL: { city: 'Honolulu', country: 'US' },
39
+ // Canada
40
+ YYZ: { city: 'Toronto', country: 'CA' },
41
+ YVR: { city: 'Vancouver', country: 'CA' },
42
+ YUL: { city: 'Montreal', country: 'CA' },
43
+ YYC: { city: 'Calgary', country: 'CA' },
44
+ YEG: { city: 'Edmonton', country: 'CA' },
45
+ YOW: { city: 'Ottawa', country: 'CA' },
46
+ YWG: { city: 'Winnipeg', country: 'CA' },
47
+ YHZ: { city: 'Halifax', country: 'CA' },
48
+ // United Kingdom
49
+ LHR: { city: 'London', country: 'GB' },
50
+ LGW: { city: 'London', country: 'GB' },
51
+ STN: { city: 'London', country: 'GB' },
52
+ LTN: { city: 'London', country: 'GB' },
53
+ MAN: { city: 'Manchester', country: 'GB' },
54
+ BHX: { city: 'Birmingham', country: 'GB' },
55
+ EDI: { city: 'Edinburgh', country: 'GB' },
56
+ GLA: { city: 'Glasgow', country: 'GB' },
57
+ // France
58
+ CDG: { city: 'Paris', country: 'FR' },
59
+ ORY: { city: 'Paris', country: 'FR' },
60
+ NCE: { city: 'Nice', country: 'FR' },
61
+ LYS: { city: 'Lyon', country: 'FR' },
62
+ MRS: { city: 'Marseille', country: 'FR' },
63
+ TLS: { city: 'Toulouse', country: 'FR' },
64
+ NTE: { city: 'Nantes', country: 'FR' },
65
+ BOD: { city: 'Bordeaux', country: 'FR' },
66
+ // Germany
67
+ FRA: { city: 'Frankfurt', country: 'DE' },
68
+ MUC: { city: 'Munich', country: 'DE' },
69
+ BER: { city: 'Berlin', country: 'DE' },
70
+ DUS: { city: 'Düsseldorf', country: 'DE' },
71
+ HAM: { city: 'Hamburg', country: 'DE' },
72
+ CGN: { city: 'Cologne', country: 'DE' },
73
+ STR: { city: 'Stuttgart', country: 'DE' },
74
+ // China (Mainland)
75
+ PEK: { city: 'Beijing', country: 'CN' },
76
+ PKX: { city: 'Beijing', country: 'CN' },
77
+ PVG: { city: 'Shanghai', country: 'CN' },
78
+ SHA: { city: 'Shanghai', country: 'CN' },
79
+ CAN: { city: 'Guangzhou', country: 'CN' },
80
+ CTU: { city: 'Chengdu', country: 'CN' }, // Shuangliu
81
+ TFU: { city: 'Chengdu', country: 'CN' }, // Tianfu
82
+ SZX: { city: 'Shenzhen', country: 'CN' },
83
+ CKG: { city: 'Chongqing', country: 'CN' },
84
+ WUH: { city: 'Wuhan', country: 'CN' },
85
+ XIY: { city: "Xi'an", country: 'CN' },
86
+ HGH: { city: 'Hangzhou', country: 'CN' },
87
+ // India
88
+ DEL: { city: 'Delhi', country: 'IN' },
89
+ BOM: { city: 'Mumbai', country: 'IN' },
90
+ BLR: { city: 'Bengaluru', country: 'IN' },
91
+ MAA: { city: 'Chennai', country: 'IN' },
92
+ CCU: { city: 'Kolkata', country: 'IN' },
93
+ HYD: { city: 'Hyderabad', country: 'IN' },
94
+ // Brazil
95
+ GRU: { city: 'Sao Paulo', country: 'BR' },
96
+ GIG: { city: 'Rio de Janeiro', country: 'BR' },
97
+ BSB: { city: 'Brasilia', country: 'BR' },
98
+ CNF: { city: 'Belo Horizonte', country: 'BR' },
99
+ SSA: { city: 'Salvador', country: 'BR' },
100
+ FOR: { city: 'Fortaleza', country: 'BR' },
101
+ POA: { city: 'Porto Alegre', country: 'BR' },
102
+ REC: { city: 'Recife', country: 'BR' },
103
+ CWB: { city: 'Curitiba', country: 'BR' },
104
+ // Australia
105
+ SYD: { city: 'Sydney', country: 'AU' },
106
+ MEL: { city: 'Melbourne', country: 'AU' },
107
+ BNE: { city: 'Brisbane', country: 'AU' },
108
+ PER: { city: 'Perth', country: 'AU' },
109
+ ADL: { city: 'Adelaide', country: 'AU' },
110
+ CBR: { city: 'Canberra', country: 'AU' },
111
+ // Japan
112
+ NRT: { city: 'Tokyo', country: 'JP' }, // Narita
113
+ HND: { city: 'Tokyo', country: 'JP' }, // Haneda
114
+ KIX: { city: 'Osaka', country: 'JP' }, // Kansai
115
+ ITM: { city: 'Osaka', country: 'JP' }, // Itami
116
+ CTS: { city: 'Sapporo', country: 'JP' }, // New Chitose
117
+ FUK: { city: 'Fukuoka', country: 'JP' },
118
+ OKA: { city: 'Okinawa', country: 'JP' }, // Naha
119
+ NGO: { city: 'Nagoya', country: 'JP' }, // Chubu Centrair
120
+ // South Africa
121
+ JNB: { city: 'Johannesburg', country: 'ZA' },
122
+ CPT: { city: 'Cape Town', country: 'ZA' },
123
+ DUR: { city: 'Durban', country: 'ZA' }, // King Shaka
124
+ // Netherlands
125
+ AMS: { city: 'Amsterdam', country: 'NL' },
126
+ // Spain
127
+ MAD: { city: 'Madrid', country: 'ES' },
128
+ BCN: { city: 'Barcelona', country: 'ES' },
129
+ PMI: { city: 'Palma de Mallorca', country: 'ES' },
130
+ AGP: { city: 'Malaga', country: 'ES' },
131
+ VLC: { city: 'Valencia', country: 'ES' },
132
+ // Italy
133
+ FCO: { city: 'Rome', country: 'IT' }, // Fiumicino
134
+ MXP: { city: 'Milan', country: 'IT' }, // Malpensa
135
+ LIN: { city: 'Milan', country: 'IT' }, // Linate
136
+ BLQ: { city: 'Bologna', country: 'IT' },
137
+ NAP: { city: 'Naples', country: 'IT' },
138
+ VCE: { city: 'Venice', country: 'IT' }, // Marco Polo
139
+ PSA: { city: 'Pisa', country: 'IT' },
140
+ // Russia
141
+ SVO: { city: 'Moscow', country: 'RU' }, // Sheremetyevo
142
+ DME: { city: 'Moscow', country: 'RU' }, // Domodedovo
143
+ VKO: { city: 'Moscow', country: 'RU' }, // Vnukovo
144
+ LED: { city: 'Saint Petersburg', country: 'RU' }, // Pulkovo
145
+ AER: { city: 'Sochi', country: 'RU' },
146
+ // United Arab Emirates
147
+ DXB: { city: 'Dubai', country: 'AE' },
148
+ AUH: { city: 'Abu Dhabi', country: 'AE' },
149
+ // Singapore
150
+ SIN: { city: 'Singapore', country: 'SG' },
151
+ // Hong Kong
152
+ HKG: { city: 'Hong Kong', country: 'HK' },
153
+ // South Korea
154
+ ICN: { city: 'Seoul', country: 'KR' }, // Incheon
155
+ GMP: { city: 'Seoul', country: 'KR' }, // Gimpo
156
+ CJU: { city: 'Jeju', country: 'KR' },
157
+ // Turkey
158
+ IST: { city: 'Istanbul', country: 'TR' }, // Istanbul Airport
159
+ SAW: { city: 'Istanbul', country: 'TR' }, // Sabiha Gökçen
160
+ AYT: { city: 'Antalya', country: 'TR' },
161
+ ESB: { city: 'Ankara', country: 'TR' },
162
+ ADB: { city: 'Izmir', country: 'TR' },
163
+ // Switzerland
164
+ ZRH: { city: 'Zurich', country: 'CH' },
165
+ GVA: { city: 'Geneva', country: 'CH' },
166
+ // Argentina
167
+ EZE: { city: 'Buenos Aires', country: 'AR' }, // Ezeiza
168
+ AEP: { city: 'Buenos Aires', country: 'AR' }, // Aeroparque
169
+ // Mexico
170
+ MEX: { city: 'Mexico City', country: 'MX' },
171
+ CUN: { city: 'Cancun', country: 'MX' },
172
+ GDL: { city: 'Guadalajara', country: 'MX' },
173
+ MTY: { city: 'Monterrey', country: 'MX' },
174
+ // Thailand
175
+ BKK: { city: 'Bangkok', country: 'TH' }, // Suvarnabhumi
176
+ DMK: { city: 'Bangkok', country: 'TH' }, // Don Mueang
177
+ HKT: { city: 'Phuket', country: 'TH' },
178
+ CNX: { city: 'Chiang Mai', country: 'TH' },
179
+ // Malaysia
180
+ KUL: { city: 'Kuala Lumpur', country: 'MY' },
181
+ // Ireland
182
+ DUB: { city: 'Dublin', country: 'IE' },
183
+ SNN: { city: 'Shannon', country: 'IE' },
184
+ // Portugal
185
+ LIS: { city: 'Lisbon', country: 'PT' },
186
+ OPO: { city: 'Porto', country: 'PT' },
187
+ FAO: { city: 'Faro', country: 'PT' },
188
+ // New Zealand
189
+ AKL: { city: 'Auckland', country: 'NZ' },
190
+ CHC: { city: 'Christchurch', country: 'NZ' },
191
+ WLG: { city: 'Wellington', country: 'NZ' },
192
+ // Qatar
193
+ DOH: { city: 'Doha', country: 'QA' },
194
+ // Saudi Arabia
195
+ JED: { city: 'Jeddah', country: 'SA' },
196
+ RUH: { city: 'Riyadh', country: 'SA' },
197
+ DMM: { city: 'Dammam', country: 'SA' },
198
+ // Egypt
199
+ CAI: { city: 'Cairo', country: 'EG' },
200
+ // Nigeria
201
+ LOS: { city: 'Lagos', country: 'NG' },
202
+ ABV: { city: 'Abuja', country: 'NG' },
203
+ // Kenya
204
+ NBO: { city: 'Nairobi', country: 'KE' }, // Jomo Kenyatta
205
+ // Ethiopia
206
+ ADD: { city: 'Addis Ababa', country: 'ET' },
207
+ // Colombia
208
+ BOG: { city: 'Bogota', country: 'CO' },
209
+ MDE: { city: 'Medellin', country: 'CO' }, // José María Córdova
210
+ // Chile
211
+ SCL: { city: 'Santiago', country: 'CL' },
212
+ // Peru
213
+ LIM: { city: 'Lima', country: 'PE' },
214
+ // Austria
215
+ VIE: { city: 'Vienna', country: 'AT' },
216
+ // Belgium
217
+ BRU: { city: 'Brussels', country: 'BE' },
218
+ // Czech Republic
219
+ PRG: { city: 'Prague', country: 'CZ' },
220
+ // Denmark
221
+ CPH: { city: 'Copenhagen', country: 'DK' },
222
+ // Finland
223
+ HEL: { city: 'Helsinki', country: 'FI' },
224
+ // Greece
225
+ ATH: { city: 'Athens', country: 'GR' },
226
+ // Hungary
227
+ BUD: { city: 'Budapest', country: 'HU' },
228
+ // Norway
229
+ OSL: { city: 'Oslo', country: 'NO' },
230
+ // Poland
231
+ WAW: { city: 'Warsaw', country: 'PL' }, // Chopin
232
+ KRK: { city: 'Krakow', country: 'PL' },
233
+ // Sweden
234
+ ARN: { city: 'Stockholm', country: 'SE' } // Arlanda
235
+ };
 
src/lib/index.ts CHANGED
@@ -22,16 +22,21 @@ export async function bandwidthTest(
22
  const url = 'https://cdn-test-cloudfront.hf.co/5gb.safetensors';
23
  // const url = 'https://cdn-test-cloudfront.hf.co/15mb.json';
24
 
25
- // issue a HEAD request to estimate latency (round trip time)
26
- let startTime = performance.now();
27
- const latencyResponse = await fetch(url, { method: 'HEAD' });
28
- if (!latencyResponse.ok) {
29
- throw new Error(`Network response was not ok: ${latencyResponse.status}`);
 
 
 
 
 
 
30
  }
31
- const latency = performance.now() - startTime;
32
- onLatency(latency);
33
 
34
- startTime = performance.now();
35
  const response = await fetch(url);
36
  if (!response.ok) {
37
  throw new Error(`Network response was not ok: ${response.status}`);
@@ -72,7 +77,7 @@ export async function bandwidthTest(
72
  let lastTimestamp = performance.now();
73
  let lastLoaded = 0;
74
  const REPORT_INTERVAL_MS = 500;
75
- onProgress(latency, loadedBytes, totalBytes, 0, false);
76
  let bytesPerSecond = 0;
77
  while (true) {
78
  const { done, value } = await reader.read();
 
22
  const url = 'https://cdn-test-cloudfront.hf.co/5gb.safetensors';
23
  // const url = 'https://cdn-test-cloudfront.hf.co/15mb.json';
24
 
25
+ // issue HEAD requests to estimate latency (round trip time), and average
26
+ let latencySum = 0;
27
+ const numLatencyTests = 5;
28
+ for (let i = 0; i < numLatencyTests; i++) {
29
+ const startTime = performance.now();
30
+ const response = await fetch(url, { method: 'HEAD' });
31
+ if (!response.ok) {
32
+ throw new Error(`Network response was not ok: ${response.status}`);
33
+ }
34
+ const latency = performance.now() - startTime;
35
+ latencySum += latency;
36
  }
37
+ onLatency(latencySum / numLatencyTests);
 
38
 
39
+ const startTime = performance.now();
40
  const response = await fetch(url);
41
  if (!response.ok) {
42
  throw new Error(`Network response was not ok: ${response.status}`);
 
77
  let lastTimestamp = performance.now();
78
  let lastLoaded = 0;
79
  const REPORT_INTERVAL_MS = 500;
80
+ onProgress(0, loadedBytes, totalBytes, 0, false);
81
  let bytesPerSecond = 0;
82
  while (true) {
83
  const { done, value } = await reader.read();
src/routes/+layout.svelte CHANGED
@@ -1,17 +1,21 @@
1
  <script lang="ts">
2
  import '../app.css';
3
- import '@fortawesome/fontawesome-free/css/all.min.css'
4
 
5
  let { children } = $props();
6
  </script>
7
 
8
- <div class="max-w-4xl mx-auto">
9
- <header class="text-center mb-10">
10
- <div class="flex justify-center items-center mb-4">
11
- <img src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg" alt="Hugging Face Logo" class="h-12 mr-3">
12
- <h1 class="text-3xl md:text-4xl font-bold text-gray-800">Bandwidth Test</h1>
 
 
 
 
13
  </div>
14
- <p class="text-gray-600 max-w-2xl mx-auto">
15
  Measure your connection speed to Hugging Face's servers in real-time
16
  </p>
17
  </header>
 
1
  <script lang="ts">
2
  import '../app.css';
3
+ import '@fortawesome/fontawesome-free/css/all.min.css';
4
 
5
  let { children } = $props();
6
  </script>
7
 
8
+ <div class="mx-auto max-w-4xl">
9
+ <header class="mb-10 text-center">
10
+ <div class="mb-4 flex items-center justify-center">
11
+ <img
12
+ src="https://huggingface.co/front/assets/huggingface_logo-noborder.svg"
13
+ alt="Hugging Face Logo"
14
+ class="mr-3 h-12"
15
+ />
16
+ <h1 class="text-3xl font-bold text-gray-800 md:text-4xl">Bandwidth Test</h1>
17
  </div>
18
+ <p class="mx-auto max-w-2xl text-gray-600">
19
  Measure your connection speed to Hugging Face's servers in real-time
20
  </p>
21
  </header>
src/routes/+layout.ts CHANGED
@@ -1 +0,0 @@
1
- export const prerender = true;
 
 
src/routes/+page.svelte CHANGED
@@ -9,6 +9,8 @@
9
  const MaxTestDurationSec = 20;
10
 
11
  let currentBandwidth = $state('0');
 
 
12
  let currentLatency = $state(0);
13
  let serverLocation = $state('-');
14
  let clientIp = $state('Detecting...');
@@ -26,10 +28,26 @@
26
  });
27
 
28
  // define callbacks
29
- let bandwidthCallback = (elapsedMs: number, loadedBytes: number, totalBytes: number, bw: number, done: boolean) => {
30
- let mbps = (bw / 1000000 * 8); // convert Bps to Mbps
31
- // update the bandwidth state
32
- currentBandwidth = mbps.toFixed(2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
  // update the bandwidth measurements array
34
  bandwidthMeasurements.push(mbps); // convert Bps to Mbps
35
  timeMeasurements.push((elapsedMs / 1000).toFixed(1)); // convert ms to seconds
@@ -38,11 +56,10 @@
38
  bandwidthMeasurements.shift();
39
  timeMeasurements.shift();
40
  }
41
- // update the progress state
42
- progress = (loadedBytes / totalBytes) * 100;
43
- if (testStatus == 'Stopped') {
44
- return true;
45
- }
46
  if (done) {
47
  testStatus = 'Completed';
48
  progress = 100;
@@ -70,7 +87,9 @@
70
  currentLatency = 0;
71
  bandwidthTest(bandwidthCallback, latencyCallback, serverLocationCallback);
72
  testTimeoutHandler = setTimeout(() => {
 
73
  testStatus = 'Completed';
 
74
  }, MaxTestDurationSec * 1000);
75
  };
76
  const stopTest = () => {
@@ -82,9 +101,7 @@
82
 
83
  let canvas: HTMLCanvasElement;
84
 
85
- const chart: Action<
86
- HTMLCanvasElement
87
- > = (node) => {
88
  let speedChart: Chart;
89
 
90
  function dispatch<T>(name: string, detail: T) {
@@ -164,10 +181,13 @@
164
  }
165
  };
166
  </script>
 
167
  <!-- Main Card -->
168
- <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-8 transition-all duration-300 hover:shadow-xl">
 
 
169
  <div class="p-6 md:p-8">
170
- <div class="flex items-center justify-between mb-6">
171
  <h2 class="text-xl font-semibold text-gray-800">Connection Statistics</h2>
172
  <div id="connection-status" class="flex items-center">
173
  <span class="h-3 w-3 rounded-full {getStatusClass()} mr-2"></span>
@@ -176,46 +196,61 @@
176
  </div>
177
 
178
  <!-- Speed Display -->
179
- <div class="grid grid-cols-1 md:grid-cols-2 gap-6 mb-8">
180
- <div class="bg-gray-50 p-4 rounded-lg text-center">
181
- <div class="text-gray-500 mb-1 flex justify-center items-center">
182
  <i class="fas fa-download mr-2"></i>
183
  <span>Download Speed</span>
184
  </div>
185
  <div id="download-speed" class="text-2xl font-bold text-indigo-600">{currentBandwidth}</div>
186
  <div class="text-sm text-gray-400">Mbps</div>
187
  </div>
188
- <div class="bg-gray-50 p-4 rounded-lg text-center">
189
- <div class="text-gray-500 mb-1 flex justify-center items-center">
190
  <i class="fas fa-clock mr-2"></i>
191
  <span>Latency</span>
192
  </div>
193
- <div id="latency" class="text-2xl font-bold text-amber-500">{currentLatency}</div>
 
 
194
  <div class="text-sm text-gray-400">ms</div>
195
  </div>
196
  </div>
197
  <!-- Progress Bar -->
198
  <div class="mb-6">
199
- <div class="flex justify-between mb-2">
200
  <span class="text-sm font-medium text-gray-700">Test Progress</span>
201
- <span id="progress-percent" class="text-sm font-medium text-gray-700">{progress.toFixed(0)}%</span>
 
 
202
  </div>
203
- <div class="w-full bg-gray-200 rounded-full h-2.5">
204
- <div id="progress-bar" class="progress-bar h-2.5 rounded-full {progress<100 && progress >0? 'wave':''}"
205
- style="width: {progress}%"></div>
 
 
 
206
  </div>
207
  </div>
208
  <!-- Test Controls -->
209
- <div class="flex flex-col sm:flex-row justify-center gap-4">
210
- <button id="start-test"
211
- class="{testStatus === 'Running'?'bg-indigo-100 hover:bg-indigo-100':'bg-indigo-600 hover:bg-indigo-700 glow'} text-white font-medium py-3 px-6 rounded-lg transition-all flex items-center justify-center"
212
- onclick={startTest} disabled={testStatus!=='Idle'}>
 
 
 
 
 
213
  <i class="fas fa-play mr-2"></i>
214
  Start Test
215
  </button>
216
- <button id="stop-test"
217
- class="bg-gray-200 hover:bg-gray-300 text-gray-800 font-medium py-3 px-6 rounded-lg transition-all flex items-center justify-center"
218
- disabled={testStatus!=='Running'} onclick={stopTest}>
 
 
 
219
  <i class="fas fa-stop mr-2"></i>
220
  Stop Test
221
  </button>
@@ -223,38 +258,42 @@
223
  </div>
224
  </div>
225
  <!-- Connection Info Card -->
226
- <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-8 connection-info">
227
  <div class="p-6 md:p-8">
228
- <h2 class="text-xl font-semibold text-gray-800 mb-6">Connection Information</h2>
229
- <div class="grid grid-cols-1 md:grid-cols-2 gap-6">
230
  <div>
231
- <h3 class="text-sm font-medium text-gray-500 mb-2">CLIENT INFORMATION</h3>
232
- <div class="flex items-center mb-3">
233
- <i class="fas fa-laptop text-indigo-500 mr-3"></i>
234
  <div>
235
  <div class="text-sm text-gray-500">IP Address</div>
236
  <div id="client-ip" class="text-lg font-medium text-gray-800">{clientIp}</div>
237
  </div>
238
  </div>
239
  <div class="flex items-center">
240
- <i class="fas fa-map-marker-alt text-indigo-500 mr-3"></i>
241
  <div>
242
  <div class="text-sm text-gray-500">Approximate Location</div>
243
- <div id="client-location" class="text-lg font-medium text-gray-800">{clientLocation}</div>
 
 
244
  </div>
245
  </div>
246
  </div>
247
  <div>
248
- <h3 class="text-sm font-medium text-gray-500 mb-2">SERVER INFORMATION</h3>
249
- <div class="flex items-center mb-3">
250
- <i class="fas fa-server text-emerald-500 mr-3"></i>
251
  <div>
252
  <div class="text-sm text-gray-500">Server Location</div>
253
- <div id="server-location" class="text-lg font-medium text-gray-800">{serverLocation}</div>
 
 
254
  </div>
255
  </div>
256
  <div class="flex items-center">
257
- <i class="fas fa-network-wired text-emerald-500 mr-3"></i>
258
  <div>
259
  <div class="text-sm text-gray-500">Test Server</div>
260
  <div class="text-lg font-medium text-gray-800">huggingface.co</div>
@@ -265,31 +304,35 @@
265
  </div>
266
  </div>
267
  <!-- Results Graph -->
268
- <div class="bg-white rounded-xl shadow-lg overflow-hidden mb-8">
269
  <div class="p-6 md:p-8">
270
- <h2 class="text-xl font-semibold text-gray-800 mb-6">Speed Over Time</h2>
271
- <div class="h-64 relative">
272
  <canvas id="speed-chart" bind:this={canvas} use:chart></canvas>
273
  </div>
274
  </div>
275
  </div>
276
  <!-- Information Section -->
277
- <div class="bg-white rounded-xl shadow-lg overflow-hidden">
278
  <div class="p-6 md:p-8">
279
- <h2 class="text-xl font-semibold text-gray-800 mb-4">About This Test</h2>
280
  <div class="prose prose-indigo max-w-none text-gray-600">
281
  <p>
282
- This bandwidth test measures your connection speed to Hugging Face's servers by downloading and uploading sample
283
- files.
284
- The test calculates:
285
  </p>
286
- <ul class="list-disc pl-5 mt-2 space-y-1">
287
- <li><strong>Download speed:</strong> How fast data can be transferred from Hugging Face to your device</li>
288
- <li><strong>Latency:</strong> The time it takes to establish connection to Hugging Face server</li>
 
 
 
 
 
289
  </ul>
290
  <p class="mt-4">
291
- For accurate results, close other bandwidth-intensive applications and ensure you're not on a VPN unless testing
292
- through it.
293
  </p>
294
  </div>
295
  </div>
 
9
  const MaxTestDurationSec = 20;
10
 
11
  let currentBandwidth = $state('0');
12
+ let accumulatedBandwidth = 0;
13
+ let numBandwidthMeasurements = 0;
14
  let currentLatency = $state(0);
15
  let serverLocation = $state('-');
16
  let clientIp = $state('Detecting...');
 
28
  });
29
 
30
  // define callbacks
31
+ let bandwidthCallback = (
32
+ elapsedMs: number,
33
+ loadedBytes: number,
34
+ totalBytes: number,
35
+ bw: number,
36
+ done: boolean
37
+ ) => {
38
+ if (testStatus == 'Stopped' || testStatus == 'Completed') {
39
+ return true;
40
+ }
41
+ let mbps = (bw / 1000000) * 8; // convert Bps to Mbps
42
+ // update the accumulated bandwidth
43
+ accumulatedBandwidth += mbps;
44
+ numBandwidthMeasurements++;
45
+ // calculate the average bandwidth
46
+ if (numBandwidthMeasurements > 0) {
47
+ currentBandwidth = (accumulatedBandwidth / numBandwidthMeasurements).toFixed(2);
48
+ } else {
49
+ currentBandwidth = '0';
50
+ }
51
  // update the bandwidth measurements array
52
  bandwidthMeasurements.push(mbps); // convert Bps to Mbps
53
  timeMeasurements.push((elapsedMs / 1000).toFixed(1)); // convert ms to seconds
 
56
  bandwidthMeasurements.shift();
57
  timeMeasurements.shift();
58
  }
59
+ // update the progress state. It is the max between the byte progress and the time progress
60
+ let timeProgress = (elapsedMs / (MaxTestDurationSec * 1000)) * 100;
61
+ let byteProgress = (loadedBytes / totalBytes) * 100;
62
+ progress = Math.max(timeProgress, byteProgress);
 
63
  if (done) {
64
  testStatus = 'Completed';
65
  progress = 100;
 
87
  currentLatency = 0;
88
  bandwidthTest(bandwidthCallback, latencyCallback, serverLocationCallback);
89
  testTimeoutHandler = setTimeout(() => {
90
+ console.log('Test timed out after', MaxTestDurationSec, 'seconds');
91
  testStatus = 'Completed';
92
+ progress = 100;
93
  }, MaxTestDurationSec * 1000);
94
  };
95
  const stopTest = () => {
 
101
 
102
  let canvas: HTMLCanvasElement;
103
 
104
+ const chart: Action<HTMLCanvasElement> = (node) => {
 
 
105
  let speedChart: Chart;
106
 
107
  function dispatch<T>(name: string, detail: T) {
 
181
  }
182
  };
183
  </script>
184
+
185
  <!-- Main Card -->
186
+ <div
187
+ class="mb-8 overflow-hidden rounded-xl bg-white shadow-lg transition-all duration-300 hover:shadow-xl"
188
+ >
189
  <div class="p-6 md:p-8">
190
+ <div class="mb-6 flex items-center justify-between">
191
  <h2 class="text-xl font-semibold text-gray-800">Connection Statistics</h2>
192
  <div id="connection-status" class="flex items-center">
193
  <span class="h-3 w-3 rounded-full {getStatusClass()} mr-2"></span>
 
196
  </div>
197
 
198
  <!-- Speed Display -->
199
+ <div class="mb-8 grid grid-cols-1 gap-6 md:grid-cols-2">
200
+ <div class="rounded-lg bg-gray-50 p-4 text-center">
201
+ <div class="mb-1 flex items-center justify-center text-gray-500">
202
  <i class="fas fa-download mr-2"></i>
203
  <span>Download Speed</span>
204
  </div>
205
  <div id="download-speed" class="text-2xl font-bold text-indigo-600">{currentBandwidth}</div>
206
  <div class="text-sm text-gray-400">Mbps</div>
207
  </div>
208
+ <div class="rounded-lg bg-gray-50 p-4 text-center">
209
+ <div class="mb-1 flex items-center justify-center text-gray-500">
210
  <i class="fas fa-clock mr-2"></i>
211
  <span>Latency</span>
212
  </div>
213
+ <div id="latency" class="text-2xl font-bold text-amber-500">
214
+ {currentLatency.toFixed(0)}
215
+ </div>
216
  <div class="text-sm text-gray-400">ms</div>
217
  </div>
218
  </div>
219
  <!-- Progress Bar -->
220
  <div class="mb-6">
221
+ <div class="mb-2 flex justify-between">
222
  <span class="text-sm font-medium text-gray-700">Test Progress</span>
223
+ <span id="progress-percent" class="text-sm font-medium text-gray-700"
224
+ >{progress.toFixed(0)}%</span
225
+ >
226
  </div>
227
+ <div class="h-2.5 w-full rounded-full bg-gray-200">
228
+ <div
229
+ id="progress-bar"
230
+ class="progress-bar h-2.5 rounded-full {progress < 100 && progress > 0 ? 'wave' : ''}"
231
+ style="width: {progress}%"
232
+ ></div>
233
  </div>
234
  </div>
235
  <!-- Test Controls -->
236
+ <div class="flex flex-col justify-center gap-4 sm:flex-row">
237
+ <button
238
+ id="start-test"
239
+ class="{testStatus === 'Running'
240
+ ? 'bg-indigo-100 hover:bg-indigo-100'
241
+ : 'glow bg-indigo-600 hover:bg-indigo-700'} flex items-center justify-center rounded-lg px-6 py-3 font-medium text-white transition-all"
242
+ onclick={startTest}
243
+ disabled={testStatus !== 'Idle' && testStatus !== 'Stopped'}
244
+ >
245
  <i class="fas fa-play mr-2"></i>
246
  Start Test
247
  </button>
248
+ <button
249
+ id="stop-test"
250
+ class="flex items-center justify-center rounded-lg bg-gray-200 px-6 py-3 font-medium text-gray-800 transition-all hover:bg-gray-300"
251
+ disabled={testStatus !== 'Running'}
252
+ onclick={stopTest}
253
+ >
254
  <i class="fas fa-stop mr-2"></i>
255
  Stop Test
256
  </button>
 
258
  </div>
259
  </div>
260
  <!-- Connection Info Card -->
261
+ <div class="connection-info mb-8 overflow-hidden rounded-xl bg-white shadow-lg">
262
  <div class="p-6 md:p-8">
263
+ <h2 class="mb-6 text-xl font-semibold text-gray-800">Connection Information</h2>
264
+ <div class="grid grid-cols-1 gap-6 md:grid-cols-2">
265
  <div>
266
+ <h3 class="mb-2 text-sm font-medium text-gray-500">CLIENT INFORMATION</h3>
267
+ <div class="mb-3 flex items-center">
268
+ <i class="fas fa-laptop mr-3 text-indigo-500"></i>
269
  <div>
270
  <div class="text-sm text-gray-500">IP Address</div>
271
  <div id="client-ip" class="text-lg font-medium text-gray-800">{clientIp}</div>
272
  </div>
273
  </div>
274
  <div class="flex items-center">
275
+ <i class="fas fa-map-marker-alt mr-3 text-indigo-500"></i>
276
  <div>
277
  <div class="text-sm text-gray-500">Approximate Location</div>
278
+ <div id="client-location" class="text-lg font-medium text-gray-800">
279
+ {clientLocation}
280
+ </div>
281
  </div>
282
  </div>
283
  </div>
284
  <div>
285
+ <h3 class="mb-2 text-sm font-medium text-gray-500">SERVER INFORMATION</h3>
286
+ <div class="mb-3 flex items-center">
287
+ <i class="fas fa-server mr-3 text-emerald-500"></i>
288
  <div>
289
  <div class="text-sm text-gray-500">Server Location</div>
290
+ <div id="server-location" class="text-lg font-medium text-gray-800">
291
+ {serverLocation}
292
+ </div>
293
  </div>
294
  </div>
295
  <div class="flex items-center">
296
+ <i class="fas fa-network-wired mr-3 text-emerald-500"></i>
297
  <div>
298
  <div class="text-sm text-gray-500">Test Server</div>
299
  <div class="text-lg font-medium text-gray-800">huggingface.co</div>
 
304
  </div>
305
  </div>
306
  <!-- Results Graph -->
307
+ <div class="mb-8 overflow-hidden rounded-xl bg-white shadow-lg">
308
  <div class="p-6 md:p-8">
309
+ <h2 class="mb-6 text-xl font-semibold text-gray-800">Speed Over Time</h2>
310
+ <div class="relative h-64">
311
  <canvas id="speed-chart" bind:this={canvas} use:chart></canvas>
312
  </div>
313
  </div>
314
  </div>
315
  <!-- Information Section -->
316
+ <div class="overflow-hidden rounded-xl bg-white shadow-lg">
317
  <div class="p-6 md:p-8">
318
+ <h2 class="mb-4 text-xl font-semibold text-gray-800">About This Test</h2>
319
  <div class="prose prose-indigo max-w-none text-gray-600">
320
  <p>
321
+ This bandwidth test measures your connection speed to Hugging Face's servers by downloading
322
+ a sample file. The test calculates:
 
323
  </p>
324
+ <ul class="mt-2 list-disc space-y-1 pl-5">
325
+ <li>
326
+ <strong>Download speed:</strong> How fast data can be transferred from Hugging Face to your
327
+ device
328
+ </li>
329
+ <li>
330
+ <strong>Latency:</strong> The time it takes to establish connection to Hugging Face server
331
+ </li>
332
  </ul>
333
  <p class="mt-4">
334
+ For accurate results, close other bandwidth-intensive applications and ensure you're not on
335
+ a VPN unless testing through it.
336
  </p>
337
  </div>
338
  </div>
src/routes/+page.ts CHANGED
@@ -1,7 +1 @@
1
- import type { PageLoad } from './$types';
2
-
3
  export const ssr = false;
4
-
5
- export const load: PageLoad = ({ params }) => {
6
- return {};
7
- };
 
 
 
1
  export const ssr = false;
 
 
 
 
static/site.webmanifest CHANGED
@@ -1,21 +1,21 @@
1
  {
2
- "name": "Hugging Face Fast",
3
- "short_name": "HF Fast",
4
- "icons": [
5
- {
6
- "src": "/assets/web-app-manifest-192x192.png",
7
- "sizes": "192x192",
8
- "type": "image/png",
9
- "purpose": "maskable"
10
- },
11
- {
12
- "src": "/assets/web-app-manifest-512x512.png",
13
- "sizes": "512x512",
14
- "type": "image/png",
15
- "purpose": "maskable"
16
- }
17
- ],
18
- "theme_color": "#ffffff",
19
- "background_color": "#ffffff",
20
- "display": "standalone"
21
- }
 
1
  {
2
+ "name": "Hugging Face Fast",
3
+ "short_name": "HF Fast",
4
+ "icons": [
5
+ {
6
+ "src": "/assets/web-app-manifest-192x192.png",
7
+ "sizes": "192x192",
8
+ "type": "image/png",
9
+ "purpose": "maskable"
10
+ },
11
+ {
12
+ "src": "/assets/web-app-manifest-512x512.png",
13
+ "sizes": "512x512",
14
+ "type": "image/png",
15
+ "purpose": "maskable"
16
+ }
17
+ ],
18
+ "theme_color": "#ffffff",
19
+ "background_color": "#ffffff",
20
+ "display": "standalone"
21
+ }