perf: CoinGecko proxy, font-display optional, contrast fix
- Route CoinGecko API through /api/rates.php to avoid CORS blocks - font-display: optional eliminates font-swap layout shifts (CLS ~0) - Disabled button contrast: #bbb on #5a3520 (5.8:1 ratio) - Nginx font caching: 1 year, immutable
This commit is contained in:
22
api/rates.php
Normal file
22
api/rates.php
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
header('Cache-Control: public, max-age=60');
|
||||||
|
|
||||||
|
$url = 'https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=eur,usd,chf';
|
||||||
|
|
||||||
|
$ch = curl_init($url);
|
||||||
|
curl_setopt_array($ch, [
|
||||||
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
|
CURLOPT_TIMEOUT => 10,
|
||||||
|
CURLOPT_HTTPHEADER => ['Accept: application/json'],
|
||||||
|
]);
|
||||||
|
$response = curl_exec($ch);
|
||||||
|
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
||||||
|
curl_close($ch);
|
||||||
|
|
||||||
|
if ($response !== false && $httpCode === 200) {
|
||||||
|
echo $response;
|
||||||
|
} else {
|
||||||
|
http_response_code(502);
|
||||||
|
echo json_encode(['error' => 'Failed to fetch rates']);
|
||||||
|
}
|
||||||
2
app.js
2
app.js
@@ -2,7 +2,7 @@
|
|||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// --- Config ---
|
// --- Config ---
|
||||||
const COINGECKO_API = 'https://api.coingecko.com/api/v3/simple/price?ids=monero&vs_currencies=eur,usd,chf';
|
const COINGECKO_API = '/api/rates.php';
|
||||||
// Standard address (4..., 95 chars), Subaddress (8..., 95 chars), Integrated address (4..., 106 chars)
|
// Standard address (4..., 95 chars), Subaddress (8..., 95 chars), Integrated address (4..., 106 chars)
|
||||||
const XMR_STANDARD_REGEX = /^[48][1-9A-HJ-NP-Za-km-z]{94}$/;
|
const XMR_STANDARD_REGEX = /^[48][1-9A-HJ-NP-Za-km-z]{94}$/;
|
||||||
const XMR_INTEGRATED_REGEX = /^4[1-9A-HJ-NP-Za-km-z]{105}$/;
|
const XMR_INTEGRATED_REGEX = /^4[1-9A-HJ-NP-Za-km-z]{105}$/;
|
||||||
|
|||||||
2
app.min.js
vendored
2
app.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -2,7 +2,7 @@
|
|||||||
font-family: 'Inter';
|
font-family: 'Inter';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 100 900;
|
font-weight: 100 900;
|
||||||
font-display: swap;
|
font-display: optional;
|
||||||
src: url('fonts/inter-400.woff2') format('woff2');
|
src: url('fonts/inter-400.woff2') format('woff2');
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
font-family: 'JetBrains Mono';
|
font-family: 'JetBrains Mono';
|
||||||
font-style: normal;
|
font-style: normal;
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-display: swap;
|
font-display: optional;
|
||||||
src: url('fonts/jetbrains-400.woff2') format('woff2');
|
src: url('fonts/jetbrains-400.woff2') format('woff2');
|
||||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||||
}
|
}
|
||||||
@@ -320,8 +320,8 @@ textarea {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.btn-primary:disabled {
|
.btn-primary:disabled {
|
||||||
background: #804020;
|
background: #5a3520;
|
||||||
color: #ccc;
|
color: #bbb;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
4
sw.js
4
sw.js
@@ -35,8 +35,8 @@ self.addEventListener('activate', function (e) {
|
|||||||
self.addEventListener('fetch', function (e) {
|
self.addEventListener('fetch', function (e) {
|
||||||
var url = new URL(e.request.url);
|
var url = new URL(e.request.url);
|
||||||
|
|
||||||
// External APIs and RPC proxy — network only, don't cache
|
// API calls — network only, don't cache
|
||||||
if (url.hostname !== location.hostname || url.pathname.startsWith('/api/')) {
|
if (url.pathname.startsWith('/api/')) {
|
||||||
e.respondWith(fetch(e.request));
|
e.respondWith(fetch(e.request));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user