Bundles leaflet CSS + MarkerCluster CSS (main.tsx) and the default marker PNGs (SpotMap) instead of loading them from unpkg.com, so boot makes no third-party request; unpkg.com removed from the CSP (index.html meta + _headers + netlify.toml). Adds dns-prefetch/preconnect for relay.skate-spots.org and blossom.skate-spots.org.
94 lines
4.7 KiB
HTML
94 lines
4.7 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
|
<title>SkateSpots - Decentralized Skate Map & Community</title>
|
|
|
|
<!--
|
|
Content-Security-Policy (defense-in-depth) — shipped in the HTML so it
|
|
applies to BOTH the web build AND the native Capacitor build.
|
|
|
|
Why a <meta> tag and not just HTTP headers: Capacitor loads the bundle
|
|
from a local scheme (https://localhost on Android, capacitor://localhost
|
|
on iOS), so the server headers in public/_headers / netlify.toml never
|
|
reach the mobile WebView. The OS sandbox isolates the app from OTHER apps;
|
|
it does NOT stop a same-origin injected script from reading this app's own
|
|
IndexedDB (Cashu ecash proofs) or localStorage (nsec, NWC string, Cashu
|
|
seed). A CSP is therefore just as important on mobile as on web.
|
|
|
|
Capacitor's local origins/schemes are allowlisted below so asset loading,
|
|
the local dev server, and live-reload continue to work. Notably there is
|
|
no 'unsafe-inline'/'unsafe-eval' on script-src (only 'wasm-unsafe-eval'
|
|
for the Bitcoin/Cashu WASM), which is the directive that actually blocks
|
|
injected <script>/onerror payloads. Keep this in sync with
|
|
public/_headers and netlify.toml.
|
|
-->
|
|
<meta http-equiv="Content-Security-Policy" content="
|
|
default-src 'none';
|
|
script-src 'self' 'wasm-unsafe-eval' https://localhost capacitor://localhost ionic://localhost;
|
|
style-src 'self' 'unsafe-inline' https://localhost capacitor://localhost ionic://localhost;
|
|
img-src 'self' data: blob: https: https://localhost capacitor://localhost ionic://localhost;
|
|
font-src 'self' data: https://fonts.gstatic.com;
|
|
connect-src 'self' https: wss: https://localhost capacitor://localhost ionic://localhost;
|
|
media-src 'self' blob: https:;
|
|
frame-src 'self' https:;
|
|
worker-src 'self' blob:;
|
|
manifest-src 'self';
|
|
object-src 'none';
|
|
base-uri 'none';
|
|
form-action 'self'
|
|
">
|
|
|
|
<!-- PWA Manifest -->
|
|
<link rel="manifest" href="/manifest.webmanifest">
|
|
|
|
<!-- App Icons -->
|
|
<link rel="icon" type="image/png" href="/images/icon-1024.png">
|
|
<link rel="apple-touch-icon" href="/images/icon-1024.png">
|
|
<link rel="apple-touch-icon" sizes="152x152" href="/images/icon-1024.png">
|
|
<link rel="apple-touch-icon" sizes="180x180" href="/images/icon-1024.png">
|
|
<link rel="apple-touch-startup-image" href="/images/icon-1024.png">
|
|
|
|
<!-- Theme Color -->
|
|
<meta name="theme-color" content="#ff0040">
|
|
<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="SkateSpots">
|
|
|
|
<!-- SEO Meta Tags -->
|
|
<meta name="description" content="Discover skate spots, find coaches, join events, and connect with the skateboarding community on Nostr. Free, decentralized, censorship-resistant.">
|
|
<meta name="keywords" content="skateboarding, skate spots, skate parks, nostr, decentralized, bitcoin, lightning, zaps">
|
|
|
|
<!-- Open Graph -->
|
|
<meta property="og:type" content="website">
|
|
<meta property="og:title" content="SkateSpots - Decentralized Skate Map & Community">
|
|
<meta property="og:description" content="Discover skate spots, find coaches, join events, and connect with the skateboarding community on Nostr.">
|
|
<meta property="og:image" content="https://skate-spots.org/images/icon-1024.png">
|
|
<meta property="og:url" content="https://skate-spots.org">
|
|
|
|
<!-- Twitter Card -->
|
|
<meta name="twitter:card" content="summary_large_image">
|
|
<meta name="twitter:title" content="SkateSpots - Decentralized Skate Map">
|
|
<meta name="twitter:description" content="Discover skate spots, find coaches, join events on Nostr.">
|
|
<meta name="twitter:image" content="https://skate-spots.org/images/icon-1024.png">
|
|
|
|
<!-- Leaflet CSS is self-hosted (imported in main.tsx) — no unpkg/CDN. -->
|
|
<!-- Warm up the connections used on almost every visit: our relay + media. -->
|
|
<link rel="dns-prefetch" href="https://relay.skate-spots.org">
|
|
<link rel="dns-prefetch" href="https://blossom.skate-spots.org">
|
|
<link rel="preconnect" href="https://relay.skate-spots.org" crossorigin>
|
|
<link rel="preconnect" href="https://blossom.skate-spots.org" crossorigin>
|
|
</head>
|
|
<body>
|
|
<div id="root"></div>
|
|
|
|
<!--
|
|
BOOT CRASH GUARD (native-safe) — external so the web build can ship a
|
|
strict CSP (script-src 'self') with no 'unsafe-inline'. See boot-guard.js.
|
|
-->
|
|
<script src="/boot-guard.js"></script>
|
|
|
|
<script type="module" src="/src/main.tsx"></script>
|
|
</body>
|
|
</html>
|