feat(i18n): nine languages, each at its own address; release v6.3.0
The site now speaks German, French, Spanish, Ukrainian, Russian, Chinese, Korean and Hindi alongside English — 623 strings per language, 5,607 translations, covering the landing page, the key exchange, the chat, group calls and every error along the way. Each locale is a real page at a real URL (/de/, /fr/, …), generated at build time from locales/*.json. That is the whole point: the app is client-rendered, so a language that only swaps strings at runtime has no address for a crawler to index and no link anyone can share. Each page carries its own canonical, a reciprocal hreflang cluster and translated schema.org. The URL decides the language, always. A stored preference only applies where the address does not say, and nothing ever redirects on Accept-Language — that is how sites become invisible to search engines outside one country. robots.txt and sitemap.xml did not exist before; both are generated now. Bugs found on the way, each with a test that would have caught it: - partner logos used page-relative paths and 404'd from any /xx/ page - post-build stamped ?v= only into the root shell, leaving locales behind - "Back online" appeared on every page load, not just after being offline - update timestamps were hard-coded to US format for every reader - t() threw on a partial window, taking whole components down with it
This commit is contained in:
+265
@@ -0,0 +1,265 @@
|
||||
<!DOCTYPE html>
|
||||
<!-- Generated by scripts/build-i18n.js from templates/index.template.html and
|
||||
locales/*.json. Edits made here are overwritten by the next build. -->
|
||||
<html lang="es">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<!-- viewport-fit=cover is what makes env(safe-area-inset-*) resolve to anything
|
||||
other than 0 on notched iPhones; the composer already pads for it.
|
||||
interactive-widget=resizes-content is honoured by Chrome/Android; iOS
|
||||
ignores it, which is why the shell also tracks visualViewport in JS. -->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover, interactive-widget=resizes-content">
|
||||
<meta http-equiv="Content-Security-Policy"
|
||||
content="default-src 'self';
|
||||
script-src 'self';
|
||||
style-src 'self' 'unsafe-inline';
|
||||
font-src 'self' data:;
|
||||
connect-src 'self' stun: stuns: turn: turns:;
|
||||
img-src 'self' data:;
|
||||
media-src 'self' blob:;
|
||||
object-src 'none';
|
||||
frame-src 'none';
|
||||
worker-src 'self';
|
||||
manifest-src 'self';
|
||||
form-action 'self';
|
||||
base-uri 'none';
|
||||
upgrade-insecure-requests;">
|
||||
<meta http-equiv="X-Content-Type-Options" content="nosniff">
|
||||
<meta http-equiv="X-XSS-Protection" content="1; mode=block">
|
||||
<meta http-equiv="Referrer-Policy" content="strict-origin-when-cross-origin">
|
||||
|
||||
<!-- PWA Manifest -->
|
||||
<link rel="manifest" href="/es/manifest.json">
|
||||
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788021796445">
|
||||
|
||||
<!-- PWA Meta Tags -->
|
||||
<meta name="mobile-web-app-capable" content="yes">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
<meta name="format-detection" content="telephone=no">
|
||||
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
||||
<meta name="apple-mobile-web-app-title" content="SecureBit">
|
||||
<meta name="application-name" content="SecureBit">
|
||||
<meta name="msapplication-TileColor" content="#ff6b35">
|
||||
<meta name="msapplication-config" content="/browserconfig.xml">
|
||||
|
||||
<!-- iOS Splash Screens - Полная конфигурация с генератора -->
|
||||
<!-- Landscape -->
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 440px) and (device-height: 956px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_17_Pro_Max__iPhone_16_Pro_Max_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 402px) and (device-height: 874px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_17_Pro__iPhone_17__iPhone_16_Pro_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_16_Plus__iPhone_15_Pro_Max__iPhone_15_Plus__iPhone_14_Pro_Max_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 420px) and (device-height: 912px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_Air_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_16__iPhone_15_Pro__iPhone_15__iPhone_14_Pro_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_14_Plus__iPhone_13_Pro_Max__iPhone_12_Pro_Max_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_16e__iPhone_14__iPhone_13_Pro__iPhone_13__iPhone_12_Pro__iPhone_12_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_13_mini__iPhone_12_mini__iPhone_11_Pro__iPhone_XS__iPhone_X_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_11_Pro_Max__iPhone_XS_Max_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_11__iPhone_XR_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_8_Plus__iPhone_7_Plus__iPhone_6s_Plus__iPhone_6_Plus_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/iPhone_8__iPhone_7__iPhone_6s__iPhone_6__4.7__iPhone_SE_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/4__iPhone_SE__iPod_touch_5th_generation_and_later_landscape.png">
|
||||
|
||||
<!-- iPad Landscape -->
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 1032px) and (device-height: 1376px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/13__iPad_Pro_M4_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/12.9__iPad_Pro_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1210px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/11__iPad_Pro_M4_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/11__iPad_Pro__10.5__iPad_Pro_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/10.9__iPad_Air_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/10.5__iPad_Air_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/10.2__iPad_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/9.7__iPad_Pro__7.9__iPad_mini__9.7__iPad_Air__9.7__iPad_landscape.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: landscape)" href="/logo/splash/splash_screens/8.3__iPad_Mini_landscape.png">
|
||||
|
||||
<!-- Portrait -->
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 440px) and (device-height: 956px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_17_Pro_Max__iPhone_16_Pro_Max_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 402px) and (device-height: 874px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_17_Pro__iPhone_17__iPhone_16_Pro_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 430px) and (device-height: 932px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_16_Plus__iPhone_15_Pro_Max__iPhone_15_Plus__iPhone_14_Pro_Max_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 420px) and (device-height: 912px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_Air_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 393px) and (device-height: 852px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_16__iPhone_15_Pro__iPhone_15__iPhone_14_Pro_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 428px) and (device-height: 926px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_14_Plus__iPhone_13_Pro_Max__iPhone_12_Pro_Max_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 390px) and (device-height: 844px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_16e__iPhone_14__iPhone_13_Pro__iPhone_13__iPhone_12_Pro__iPhone_12_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 375px) and (device-height: 812px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_13_mini__iPhone_12_mini__iPhone_11_Pro__iPhone_XS__iPhone_X_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_11_Pro_Max__iPhone_XS_Max_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 896px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_11__iPhone_XR_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 414px) and (device-height: 736px) and (-webkit-device-pixel-ratio: 3) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_8_Plus__iPhone_7_Plus__iPhone_6s_Plus__iPhone_6_Plus_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 375px) and (device-height: 667px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/iPhone_8__iPhone_7__iPhone_6s__iPhone_6__4.7__iPhone_SE_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 320px) and (device-height: 568px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/4__iPhone_SE__iPod_touch_5th_generation_and_later_portrait.png">
|
||||
|
||||
<!-- iPad Portrait -->
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 1032px) and (device-height: 1376px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/13__iPad_Pro_M4_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 1024px) and (device-height: 1366px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/12.9__iPad_Pro_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1210px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/11__iPad_Pro_M4_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1194px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/11__iPad_Pro__10.5__iPad_Pro_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 820px) and (device-height: 1180px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/10.9__iPad_Air_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 834px) and (device-height: 1112px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/10.5__iPad_Air_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 810px) and (device-height: 1080px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/10.2__iPad_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 768px) and (device-height: 1024px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/9.7__iPad_Pro__7.9__iPad_mini__9.7__iPad_Air__9.7__iPad_portrait.png">
|
||||
<link rel="apple-touch-startup-image" media="screen and (device-width: 744px) and (device-height: 1133px) and (-webkit-device-pixel-ratio: 2) and (orientation: portrait)" href="/logo/splash/splash_screens/8.3__iPad_Mini_portrait.png">
|
||||
|
||||
<!-- Apple Touch Icons -->
|
||||
<link rel="apple-touch-icon" href="/logo/icon-180x180.png?v=1788021796445">
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="/logo/icon-57x57.png">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="/logo/icon-60x60.png">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="/logo/icon-72x72.png">
|
||||
<link rel="apple-touch-icon" sizes="76x76" href="/logo/icon-76x76.png">
|
||||
<link rel="apple-touch-icon" sizes="114x114" href="/logo/icon-114x114.png">
|
||||
<link rel="apple-touch-icon" sizes="120x120" href="/logo/icon-120x120.png">
|
||||
<link rel="apple-touch-icon" sizes="144x144" href="/logo/icon-144x144.png">
|
||||
<link rel="apple-touch-icon" sizes="152x152" href="/logo/icon-152x152.png">
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/logo/icon-180x180.png?v=1788021796445">
|
||||
|
||||
<!-- Microsoft Tiles -->
|
||||
<meta name="msapplication-TileColor" content="#ff6b35">
|
||||
<meta name="msapplication-TileImage" content="./logo/icon-144x144.png">
|
||||
<meta name="msapplication-config" content="/browserconfig.xml">
|
||||
|
||||
<!-- Theme colors -->
|
||||
<meta name="theme-color" content="#ff6b35">
|
||||
<meta name="msapplication-navbutton-color" content="#ff6b35">
|
||||
|
||||
<!-- Security Headers for PWA - CSP is already defined above -->
|
||||
|
||||
|
||||
<!-- SEO -->
|
||||
<title>SecureBit.chat - Mensajería privada y cifrada</title>
|
||||
<meta name="description" content="SecureBit.chat es un mensajero entre pares, gratuito y cifrado de extremo a extremo, que funciona por completo en tu navegador. Sin cuentas y sin servidores que guarden tus mensajes: ECDH P-384, AES-256-GCM y verificación SAS en persona.">
|
||||
<meta name="keywords" content="mensajería cifrada, cifrado de extremo a extremo, chat entre pares, mensajero P2P, ECDH, DTLS, verificación SAS, WebRTC, chat privado, chat seguro, sin servidores, sin cuentas, protección MITM, PFS">
|
||||
<meta name="author" content="Volodymyr">
|
||||
<meta name="robots" content="index, follow, max-image-preview:large, max-snippet:-1">
|
||||
<link rel="canonical" href="https://securebit.chat/es/">
|
||||
<link rel="alternate" hreflang="en" href="https://securebit.chat/">
|
||||
<link rel="alternate" hreflang="de" href="https://securebit.chat/de/">
|
||||
<link rel="alternate" hreflang="fr" href="https://securebit.chat/fr/">
|
||||
<link rel="alternate" hreflang="es" href="https://securebit.chat/es/">
|
||||
<link rel="alternate" hreflang="uk" href="https://securebit.chat/uk/">
|
||||
<link rel="alternate" hreflang="ru" href="https://securebit.chat/ru/">
|
||||
<link rel="alternate" hreflang="zh-Hans" href="https://securebit.chat/zh/">
|
||||
<link rel="alternate" hreflang="ko" href="https://securebit.chat/ko/">
|
||||
<link rel="alternate" hreflang="hi" href="https://securebit.chat/hi/">
|
||||
<link rel="alternate" hreflang="x-default" href="https://securebit.chat/">
|
||||
|
||||
<!-- Open Graph -->
|
||||
<meta property="og:site_name" content="SecureBit.chat">
|
||||
<meta property="og:title" content="SecureBit.chat - Chat entre pares cifrado de extremo a extremo">
|
||||
<meta property="og:description" content="Un mensajero seguro que funciona por completo en tu navegador. Sin cuentas y sin servidores que guarden tus mensajes. Usa tus propios servidores STUN/TURN: no te imponemos nada.">
|
||||
<meta property="og:url" content="https://securebit.chat/es/">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:locale" content="es_ES">
|
||||
<meta property="og:locale:alternate" content="en_US">
|
||||
<meta property="og:locale:alternate" content="de_DE">
|
||||
<meta property="og:locale:alternate" content="fr_FR">
|
||||
<meta property="og:locale:alternate" content="uk_UA">
|
||||
<meta property="og:locale:alternate" content="ru_RU">
|
||||
<meta property="og:locale:alternate" content="zh_CN">
|
||||
<meta property="og:locale:alternate" content="ko_KR">
|
||||
<meta property="og:locale:alternate" content="hi_IN">
|
||||
<meta property="og:image" content="https://securebit.chat/assets/social-card.png">
|
||||
<meta property="og:image:secure_url" content="https://securebit.chat/assets/social-card.png">
|
||||
<meta property="og:image:type" content="image/png">
|
||||
<meta property="og:image:width" content="1200">
|
||||
<meta property="og:image:height" content="630">
|
||||
<meta property="og:image:alt" content="SecureBit.chat - chat entre pares cifrado de extremo a extremo">
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="SecureBit.chat - Chat entre pares cifrado de extremo a extremo">
|
||||
<meta name="twitter:description" content="Un mensajero seguro que funciona por completo en tu navegador. Sin cuentas y sin servidores que guarden tus mensajes.">
|
||||
<meta name="twitter:image" content="https://securebit.chat/assets/social-card.png">
|
||||
<meta name="twitter:image:alt" content="SecureBit.chat - chat entre pares cifrado de extremo a extremo">
|
||||
|
||||
<!-- Structured data (schema.org) -->
|
||||
<script type="application/ld+json">
|
||||
{
|
||||
"@context": "https://schema.org",
|
||||
"@graph": [
|
||||
{
|
||||
"@type": "WebSite",
|
||||
"@id": "https://securebit.chat/#website",
|
||||
"name": "SecureBit.chat",
|
||||
"url": "https://securebit.chat/",
|
||||
"description": "Chat entre pares cifrado de extremo a extremo que funciona por completo en el navegador.",
|
||||
"inLanguage": "es"
|
||||
},
|
||||
{
|
||||
"@type": "WebApplication",
|
||||
"name": "SecureBit.chat",
|
||||
"url": "https://securebit.chat/es/",
|
||||
"applicationCategory": "CommunicationApplication",
|
||||
"operatingSystem": "Cualquiera (navegador web moderno)",
|
||||
"browserRequirements": "Requiere WebRTC y la API Web Crypto",
|
||||
"description": "Un mensajero entre pares, gratuito y cifrado de extremo a extremo. Sin cuentas y sin servidores que guarden mensajes: ECDH P-384, AES-256-GCM y verificación SAS en persona.",
|
||||
"inLanguage": "es",
|
||||
"image": "https://securebit.chat/assets/social-card.png",
|
||||
"license": "https://opensource.org/licenses/MIT",
|
||||
"isAccessibleForFree": true,
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"featureList": [
|
||||
"Cifrado de extremo a extremo (ECDH P-384, AES-256-GCM)",
|
||||
"Conexión entre pares por WebRTC, sin servidores de mensajes",
|
||||
"Verificación SAS en persona frente a ataques de intermediario",
|
||||
"Servidores STUN/TURN propios y modo de privacidad solo con relay",
|
||||
"Transferencia de archivos cifrada",
|
||||
"Aplicación web progresiva instalable, con soporte sin conexión"
|
||||
],
|
||||
"sameAs": [
|
||||
"https://github.com/SecureBitChat/securebit-chat"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
</script>
|
||||
<!-- Render-blocking JS is deferred: classic deferred scripts and module scripts
|
||||
both execute in document order after parsing, so React still runs before the
|
||||
app modules below, but the parser / first paint is no longer blocked. -->
|
||||
<script defer src="/config/ice-servers.js?v=1788021796445"></script>
|
||||
<script defer src="/libs/react/react.production.min.js"></script>
|
||||
<script defer src="/libs/react-dom/react-dom.production.min.js"></script>
|
||||
<!-- Prism syntax highlighting (vendored, offline). Tokenizes code as TEXT only —
|
||||
it never executes the snippet. Loaded in manual mode (no auto-highlight).
|
||||
Its CSS is loaded async via load-async-css.js (not paint-critical). -->
|
||||
<script defer src="/libs/prism/prism.js"></script>
|
||||
<!-- Critical, paint-defining CSS stays render-blocking (avoids FOUC / layout shift). -->
|
||||
<link rel="stylesheet" href="/assets/tailwind.css?v=1788021796445">
|
||||
<link rel="icon" type="image/x-icon" href="/logo/favicon.ico?v=1788021796445">
|
||||
<!-- Preload only the fonts needed for first paint. fa-solid covers the bulk of UI
|
||||
icons; fa-regular/fa-brands are loaded on demand by their CSS (rarely on the
|
||||
first screen). Inter latin 400/700 cover body text and headings/buttons. -->
|
||||
<link rel="preload" href="/assets/fontawesome/webfonts/fa-solid-900.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-400.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="preload" href="/assets/fonts/inter/files/inter-latin-700.woff2" as="font" type="font/woff2" crossorigin>
|
||||
<link rel="stylesheet" href="/assets/fonts/inter/inter.css">
|
||||
<link rel="stylesheet" href="/src/styles/main.css?v=1788021796445">
|
||||
<link rel="stylesheet" href="/src/styles/animations.css?v=1788021796445">
|
||||
<link rel="stylesheet" href="/src/styles/components.css?v=1788021796445">
|
||||
<!-- Loads after components.css on purpose: press feedback, material weight,
|
||||
size-specific tracking and the reduced-motion / -transparency / -contrast
|
||||
answers all need to settle arguments with the sheets above on source order. -->
|
||||
<link rel="stylesheet" href="/src/styles/apple-motion.css?v=1788021796445">
|
||||
<!-- Non-critical CSS (FontAwesome ~102KB, Prism) loaded async — no longer blocks paint. -->
|
||||
<script defer src="/src/scripts/load-async-css.js?v=1788021796445"></script>
|
||||
<noscript>
|
||||
<link rel="stylesheet" href="/assets/fontawesome/css/all.min.css">
|
||||
<link rel="stylesheet" href="/libs/prism/prism.css">
|
||||
</noscript>
|
||||
<script defer src="/src/scripts/fa-check.js?v=1788021796445"></script>
|
||||
<!-- Update Manager - система принудительного обновления -->
|
||||
<script defer src="/src/utils/updateManager.js?v=1788021796445"></script>
|
||||
<script type="module" src="/src/components/UpdateChecker.jsx?v=1788021796445"></script>
|
||||
<script type="module" src="/dist/qr-local.js?v=1788021796445"></script>
|
||||
<script type="module" src="/src/components/QRScanner.js?v=1788021796445"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
<script type="module" src="/dist/app-boot.js?v=1788021796445"></script>
|
||||
<script type="module" src="/dist/app.js?v=1788021796445"></script>
|
||||
|
||||
<script defer src="/src/scripts/pwa-register.js?v=1788021796445"></script>
|
||||
<script src="/src/pwa/install-prompt.js?v=1788021796445" type="module"></script>
|
||||
<script src="/src/pwa/pwa-manager.js?v=1788021796445" type="module"></script>
|
||||
<script defer src="/src/scripts/pwa-offline-test.js?v=1788021796445"></script>
|
||||
<link rel="stylesheet" href="/src/styles/pwa.css?v=1788021796445">
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user