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="ru">
|
||||
<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="/ru/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 - приватный мессенджер со сквозным шифрованием</title>
|
||||
<meta name="description" content="SecureBit.chat - бесплатный одноранговый мессенджер со сквозным шифрованием, работающий целиком в браузере. Без учётных записей и без серверов, хранящих ваши сообщения: ECDH P-384, AES-256-GCM и личная сверка SAS.">
|
||||
<meta name="keywords" content="зашифрованный мессенджер, сквозное шифрование, одноранговый чат, P2P-мессенджер, ECDH, DTLS, сверка SAS, WebRTC, приватный чат, защищённый чат, без серверов, без регистрации, защита от 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/ru/">
|
||||
<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 - одноранговый чат со сквозным шифрованием">
|
||||
<meta property="og:description" content="Защищённый мессенджер, работающий целиком в вашем браузере. Без учётных записей и без серверов, хранящих ваши сообщения. Подключайте свои STUN/TURN-серверы - мы ничего не навязываем.">
|
||||
<meta property="og:url" content="https://securebit.chat/ru/">
|
||||
<meta property="og:type" content="website">
|
||||
<meta property="og:locale" content="ru_RU">
|
||||
<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="es_ES">
|
||||
<meta property="og:locale:alternate" content="uk_UA">
|
||||
<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 - одноранговый чат со сквозным шифрованием">
|
||||
|
||||
<!-- Twitter Card -->
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:title" content="SecureBit.chat - одноранговый чат со сквозным шифрованием">
|
||||
<meta name="twitter:description" content="Защищённый мессенджер, работающий целиком в вашем браузере. Без учётных записей и без серверов, хранящих ваши сообщения.">
|
||||
<meta name="twitter:image" content="https://securebit.chat/assets/social-card.png">
|
||||
<meta name="twitter:image:alt" content="SecureBit.chat - одноранговый чат со сквозным шифрованием">
|
||||
|
||||
<!-- 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": "Одноранговый чат со сквозным шифрованием, работающий целиком в браузере.",
|
||||
"inLanguage": "ru"
|
||||
},
|
||||
{
|
||||
"@type": "WebApplication",
|
||||
"name": "SecureBit.chat",
|
||||
"url": "https://securebit.chat/ru/",
|
||||
"applicationCategory": "CommunicationApplication",
|
||||
"operatingSystem": "Любая (современный веб-браузер)",
|
||||
"browserRequirements": "Требуются WebRTC и Web Crypto API",
|
||||
"description": "Бесплатный одноранговый мессенджер со сквозным шифрованием. Без учётных записей и без серверов, хранящих сообщения: ECDH P-384, AES-256-GCM и личная сверка SAS.",
|
||||
"inLanguage": "ru",
|
||||
"image": "https://securebit.chat/assets/social-card.png",
|
||||
"license": "https://opensource.org/licenses/MIT",
|
||||
"isAccessibleForFree": true,
|
||||
"offers": {
|
||||
"@type": "Offer",
|
||||
"price": "0",
|
||||
"priceCurrency": "USD"
|
||||
},
|
||||
"featureList": [
|
||||
"Сквозное шифрование (ECDH P-384, AES-256-GCM)",
|
||||
"Одноранговое соединение по WebRTC, без серверов для сообщений",
|
||||
"Личная сверка SAS против атак «человек посередине»",
|
||||
"Свои STUN/TURN-серверы и режим приватности только через relay",
|
||||
"Зашифрованная передача файлов",
|
||||
"Устанавливаемое прогрессивное веб-приложение с работой офлайн"
|
||||
],
|
||||
"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>
|
||||
@@ -0,0 +1,121 @@
|
||||
{
|
||||
"name": "SecureBit.chat - приватный мессенджер со сквозным шифрованием",
|
||||
"short_name": "SecureBit",
|
||||
"description": "P2P-мессенджер с защитой ECDH, DTLS и SAS и криптографией военного уровня",
|
||||
"start_url": "/ru/",
|
||||
"display": "standalone",
|
||||
"background_color": "#1a1a1a",
|
||||
"theme_color": "#ff6b35",
|
||||
"orientation": "portrait-primary",
|
||||
"scope": "/",
|
||||
"lang": "ru",
|
||||
"dir": "ltr",
|
||||
"categories": [
|
||||
"communication",
|
||||
"security",
|
||||
"productivity"
|
||||
],
|
||||
"prefer_related_applications": false,
|
||||
"icons": [
|
||||
{
|
||||
"src": "/logo/icon-72x72.png",
|
||||
"sizes": "72x72",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-128x128.png",
|
||||
"sizes": "128x128",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-144x144.png",
|
||||
"sizes": "144x144",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-152x152.png",
|
||||
"sizes": "152x152",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-180x180.png",
|
||||
"sizes": "180x180",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-256x256.png",
|
||||
"sizes": "256x256",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-384x384.png",
|
||||
"sizes": "384x384",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "any"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-192x192.png",
|
||||
"sizes": "192x192",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
},
|
||||
{
|
||||
"src": "/logo/icon-512x512.png",
|
||||
"sizes": "512x512",
|
||||
"type": "image/png",
|
||||
"purpose": "maskable"
|
||||
}
|
||||
],
|
||||
"shortcuts": [
|
||||
{
|
||||
"name": "Create Channel",
|
||||
"short_name": "Create",
|
||||
"description": "Create a new secure channel",
|
||||
"url": "/ru/?action=create",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/logo/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Join Channel",
|
||||
"short_name": "Join",
|
||||
"description": "Join an existing secure channel",
|
||||
"url": "/ru/?action=join",
|
||||
"icons": [
|
||||
{
|
||||
"src": "/logo/icon-96x96.png",
|
||||
"sizes": "96x96",
|
||||
"type": "image/png"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user