# Progressive Web App (PWA) Guide (Українська) 🌐 **Languages:** 🇺🇸 [English](../../../../guides/PWA_GUIDE.md) · 🇪🇹 [am](../../../am/docs/guides/PWA_GUIDE.md) · 🇸🇦 [ar](../../../ar/docs/guides/PWA_GUIDE.md) · 🇦🇿 [az](../../../az/docs/guides/PWA_GUIDE.md) · 🇧🇬 [bg](../../../bg/docs/guides/PWA_GUIDE.md) · 🇧🇩 [bn](../../../bn/docs/guides/PWA_GUIDE.md) · 🇧🇦 [bs](../../../bs/docs/guides/PWA_GUIDE.md) · 🇨🇿 [cs](../../../cs/docs/guides/PWA_GUIDE.md) · 🇩🇰 [da](../../../da/docs/guides/PWA_GUIDE.md) · 🇩🇪 [de](../../../de/docs/guides/PWA_GUIDE.md) · 🇬🇷 [el](../../../el/docs/guides/PWA_GUIDE.md) · 🇪🇸 [es](../../../es/docs/guides/PWA_GUIDE.md) · 🇪🇪 [et](../../../et/docs/guides/PWA_GUIDE.md) · 🇮🇷 [fa](../../../fa/docs/guides/PWA_GUIDE.md) · 🇫🇮 [fi](../../../fi/docs/guides/PWA_GUIDE.md) · 🇫🇷 [fr](../../../fr/docs/guides/PWA_GUIDE.md) · 🇮🇪 [ga](../../../ga/docs/guides/PWA_GUIDE.md) · 🇮🇳 [gu](../../../gu/docs/guides/PWA_GUIDE.md) · 🇳🇬 [ha](../../../ha/docs/guides/PWA_GUIDE.md) · 🇮🇱 [he](../../../he/docs/guides/PWA_GUIDE.md) · 🇮🇳 [hi](../../../hi/docs/guides/PWA_GUIDE.md) · 🇭🇷 [hr](../../../hr/docs/guides/PWA_GUIDE.md) · 🇭🇺 [hu](../../../hu/docs/guides/PWA_GUIDE.md) · 🇦🇲 [hy](../../../hy/docs/guides/PWA_GUIDE.md) · 🇮🇩 [id](../../../id/docs/guides/PWA_GUIDE.md) · 🇳🇬 [ig](../../../ig/docs/guides/PWA_GUIDE.md) · 🇮🇹 [it](../../../it/docs/guides/PWA_GUIDE.md) · 🇯🇵 [ja](../../../ja/docs/guides/PWA_GUIDE.md) · 🇬🇪 [ka](../../../ka/docs/guides/PWA_GUIDE.md) · 🇰🇭 [km](../../../km/docs/guides/PWA_GUIDE.md) · 🇮🇳 [kn](../../../kn/docs/guides/PWA_GUIDE.md) · 🇰🇷 [ko](../../../ko/docs/guides/PWA_GUIDE.md) · 🇱🇹 [lt](../../../lt/docs/guides/PWA_GUIDE.md) · 🇱🇻 [lv](../../../lv/docs/guides/PWA_GUIDE.md) · 🇮🇳 [ml](../../../ml/docs/guides/PWA_GUIDE.md) · 🇮🇳 [mr](../../../mr/docs/guides/PWA_GUIDE.md) · 🇲🇾 [ms](../../../ms/docs/guides/PWA_GUIDE.md) · 🇲🇹 [mt](../../../mt/docs/guides/PWA_GUIDE.md) · 🇲🇲 [my](../../../my/docs/guides/PWA_GUIDE.md) · 🇳🇵 [ne](../../../ne/docs/guides/PWA_GUIDE.md) · 🇳🇱 [nl](../../../nl/docs/guides/PWA_GUIDE.md) · 🇳🇴 [no](../../../no/docs/guides/PWA_GUIDE.md) · 🇮🇳 [or](../../../or/docs/guides/PWA_GUIDE.md) · 🇮🇳 [pa](../../../pa/docs/guides/PWA_GUIDE.md) · 🇵🇭 [phi](../../../phi/docs/guides/PWA_GUIDE.md) · 🇵🇱 [pl](../../../pl/docs/guides/PWA_GUIDE.md) · 🇵🇹 [pt](../../../pt/docs/guides/PWA_GUIDE.md) · 🇧🇷 [pt-BR](../../../pt-BR/docs/guides/PWA_GUIDE.md) · 🇷🇴 [ro](../../../ro/docs/guides/PWA_GUIDE.md) · 🇷🇺 [ru](../../../ru/docs/guides/PWA_GUIDE.md) · 🇱🇰 [si](../../../si/docs/guides/PWA_GUIDE.md) · 🇸🇰 [sk](../../../sk/docs/guides/PWA_GUIDE.md) · 🇸🇮 [sl](../../../sl/docs/guides/PWA_GUIDE.md) · 🇷🇸 [sr](../../../sr/docs/guides/PWA_GUIDE.md) · 🇸🇪 [sv](../../../sv/docs/guides/PWA_GUIDE.md) · 🇰🇪 [sw](../../../sw/docs/guides/PWA_GUIDE.md) · 🇮🇳 [ta](../../../ta/docs/guides/PWA_GUIDE.md) · 🇮🇳 [te](../../../te/docs/guides/PWA_GUIDE.md) · 🇹🇭 [th](../../../th/docs/guides/PWA_GUIDE.md) · 🇹🇷 [tr](../../../tr/docs/guides/PWA_GUIDE.md) · 🇵🇰 [ur](../../../ur/docs/guides/PWA_GUIDE.md) · 🇺🇿 [uz](../../../uz/docs/guides/PWA_GUIDE.md) · 🇻🇳 [vi](../../../vi/docs/guides/PWA_GUIDE.md) · 🇳🇬 [yo](../../../yo/docs/guides/PWA_GUIDE.md) · 🇨🇳 [zh-CN](../../../zh-CN/docs/guides/PWA_GUIDE.md) · 🇹🇼 [zh-TW](../../../zh-TW/docs/guides/PWA_GUIDE.md) --- OmniRoute постачається як повноцінний прогресивний вебзастосунок (PWA), який можна встановити. Коли ви відкриваєте панель керування в будь-якому мобільному браузері — Android (Chrome) або iOS (Safari) — ви можете вибрати «Додати на початковий екран» і отримати взаємодію, подібну до нативного застосунку, без використання магазину застосунків. ## Що таке PWA? Прогресивний вебзастосунок перетворює вебпанель керування OmniRoute на застосунок, який виглядає та працює як нативний мобільний застосунок. Після встановлення він: - Запускається з початкового екрана за допомогою власної іконки - Відкривається на весь екран — без адресного рядка браузера чи інтерфейсу вкладок - Працює офлайн завдяки спеціальній сторінці стану підключення - Кешує статичні ресурси для швидшого завантаження - Підтримує як портретну, так і альбомну орієнтацію ## Встановлення ### Android (Chrome) 1. Відкрийте панель керування OmniRoute у Chrome: `http://YOUR_IP:20128` 2. Chrome автоматично покаже банер **«Додати OmniRoute на початковий екран»**, або: - Торкніться меню **⋮** (три крапки) → **«Додати на початковий екран»** або **«Установити застосунок»** 3. Підтвердьте запит 4. OmniRoute з’явиться на початковому екрані як окремий застосунок ### iOS (Safari) 1. Відкрийте панель керування OmniRoute у Safari: `http://YOUR_IP:20128` 2. Торкніться кнопки **«Поділитися»** (квадрат зі стрілкою) 3. Прокрутіть униз і торкніться **«На початковий екран»** 4. Укажіть назву (за замовчуванням — «OmniRoute») і торкніться **«Додати»** 5. OmniRoute з’явиться на початковому екрані з іконкою застосунку ### Комп’ютер (Chrome / Edge) 1. Відкрийте панель керування OmniRoute 2. Натисніть **іконку встановлення** в адресному рядку (або ⋮ → «Установити OmniRoute...») 3. Підтвердьте запит 4. OmniRoute відкриється як окреме вікно — без вкладок і адресного рядка ## Можливості ### Повноекранний режим Маніфест налаштовано з параметром `display: "fullscreen"`, що означає, що встановлений застосунок використовує весь екран — без елементів інтерфейсу браузера та без перекриття рядком стану. Завдяки цьому панель керування справді сприймається як нативний застосунок. ### Підтримка офлайн-режиму OmniRoute містить сервіс-воркер (`sw.js`), який забезпечує інтелектуальне кешування: | Тип ресурсу | Стратегія | Поведінка | | ------------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------------------------- | | **Оболонка застосунку** | Спочатку кеш | `/`, `/offline`, маніфест та іконки попередньо кешуються під час встановлення | | **Статичні ресурси** (CSS, JS, зображення, шрифти) | Спочатку мережа з резервним кешем | Отримує актуальні дані з мережі; за відсутності підключення використовує кеш | | **Пакети Next.js** (`/_next/`) | Спочатку мережа з оновленням кешу | Отримує дані з мережі й оновлює кеш; за відсутності підключення надає кешовану версію | | **Навігаційні запити** | Обхід (ніколи не перехоплюються) | Браузер керує переходом із HTTP/3 на HTTP/2; непрацюючий сокет QUIC не повинен перетворюватися на `Response.error()` | | **Маршрути API / панелі керування** (`/api/`, `/a2a`, `/dashboard`) | Обхід (ніколи не кешуються) | Завжди надсилаються безпосередньо на сервер — сервіс-воркер ніколи їх не перехоплює | ### Офлайн-сторінка Коли мережа недоступна й користувач переходить на нову сторінку, сервіс-воркер надає спеціальну сторінку `/offline`, яка: - Відображає зрозуміле повідомлення **«Проблема з підключенням»** - Показує актуальний **індикатор стану онлайн/офлайн**, який оновлюється в режимі реального часу - Надає кнопку **«Повторити підключення»** для перезавантаження після відновлення зв’язку - Містить посилання на **сторінку стану** для діагностики ### Іконки застосунку OmniRoute надає іконки, оптимізовані для кожної платформи: | Файл | Розмір | Використовується для | | ---------------------- | ------------------- | ----------------------------------------------- | | `icon-512.png` | 512×512 | Запит на встановлення в Android, екран-заставка | | `apple-touch-icon.png` | 180×180 | Іконка на початковому екрані iOS | | `icon-192.svg` | 192×192 (векторний) | Адаптивна іконка Android | | `apple-touch-icon.svg` | 180×180 (векторний) | Резервна іконка Apple | | `favicon.svg` | Векторний | Вкладки браузера | | `favicon.ico` | Кілька розмірів | Застарілі браузери | ### Автоматична реєстрація Сервіс-воркер реєструється автоматично через компонент `` у кореневому макеті. Жодних дій від користувача не потрібно — застосунок можна встановити щойно браузер виявить дійсний маніфест і сервіс-воркер. ## Технічна архітектура ### Маніфест вебзастосунку (`manifest.webmanifest`) Генерується Next.js через `src/app/manifest.ts`: ```json { "name": "OmniRoute", "short_name": "OmniRoute", "description": "OmniRoute is an AI gateway for multi-provider LLMs. One endpoint for all your AI providers.", "start_url": "/", "scope": "/", "display": "fullscreen", "orientation": "any", "background_color": "#0b0f1a", "theme_color": "#0b0f1a", "icons": [ { "src": "/icon-512.png", "sizes": "512x512", "type": "image/png", "purpose": "any maskable" }, { "src": "/apple-touch-icon.png", "sizes": "180x180", "type": "image/png" } ] } ``` ### Сервіс-воркер (`public/sw.js`) Звичайний сервіс-воркер (без залежностей від фреймворків), який має: - **Фазу встановлення**: попередньо кешує оболонку застосунку (кореневу сторінку, сторінку для автономного режиму, маніфест та іконки) - **Фазу активації**: видаляє старі версії кешу й перебирає керування всіма клієнтами - **Фазу отримання**: інтелектуально маршрутизує запити залежно від їхнього типу (навігація, статичний ресурс, API) - **Версіонування кешу**: `omniroute-pwa-v3` — збільште версію, щоб примусово створити новий кеш після оновлення ### Метадані макета (`src/app/layout.tsx`) Кореневий макет надає всі метатеги, необхідні для відповідності вимогам PWA: - Посилання `manifest` на `/manifest.webmanifest` - `apple-web-app-capable: true` для автономного режиму в iOS - `apple-web-app-status-bar-style: black-translucent` - `mobile-web-app-capable: yes` для Chrome на Android - `theme-color: #0b0f1a` - `viewport-fit: cover` для відображення від краю до краю ### Компонент: `PwaRegister` Розташований у `src/shared/components/PwaRegister.tsx`. Цей клієнтський компонент: 1. Запускається під час монтування (лише на стороні клієнта) 2. Перевіряє підтримку `serviceWorker` у браузері 3. Непомітно реєструє `/sw.js` (помилки ігноруються, щоб не блокувати застосунок) 4. Нічого не відображає (`return null`) — цей компонент призначений лише для побічного ефекту ## Використання з Termux (Android) Під час запуску OmniRoute на Android через Termux PWA працює без додаткових налаштувань: 1. Запустіть OmniRoute у Termux: `npx omniroute` 2. Відкрийте Chrome на тому самому телефоні: `http://localhost:20128` 3. Установіть PWA через «Додати на головний екран» 4. PWA підключиться до локального сервера Termux — усе працюватиме безпосередньо на пристрої Це поєднання означає, що ваш телефон Android одночасно є **сервером** (Termux) і **клієнтом** (PWA) — повністю автономним ШІ-шлюзом. ## Використання з інших пристроїв Установіть PWA на будь-якому пристрої, браузер якого має доступ до вашого сервера OmniRoute: - **Інший телефон або планшет**: перейдіть до `http://PHONE_IP:20128` та встановіть PWA - **Ноутбук**: відкрийте Chrome або Edge і встановіть його як настільний PWA - **Смарттелевізор із браузером**: відкрийте панель керування в повноекранному режимі ## Налаштування ### Назва екземпляра Назва PWA враховує параметр **Назва екземпляра** з `Панель керування → Налаштування`. Якщо перейменувати екземпляр на «Мій ШІ-шлюз», установлений PWA відображатиме цю назву. ### Власний фавікон Якщо завантажити власний фавікон через `Панель керування → Налаштування`, іконка PWA на настільному комп’ютері відображатиме власне зображення. Для іконок на головному екрані мобільних пристроїв використовуються заздалегідь підготовлені файли `icon-512.png` та `apple-touch-icon.png`. ## Обмеження - **Без push-сповіщень** — Сервіс-воркер не реалізує Push API. Натомість сповіщення обробляє застосунок Electron. - **Без фонової синхронізації** — Офлайн-дії не ставляться в чергу для повторного виконання. PWA призначений насамперед для перегляду інформаційної панелі. - **Обмеження iOS** — Safari на iOS підтримує не всі функції PWA (наприклад, запити на встановлення потрібно виконувати вручну, а робота сервіс-воркерів у фоновому режимі обмежена). - **Розмір кешу** — Сервіс-воркер кешує лише статичні ресурси. Великі корисні навантаження відповідей із маршрутів `/api/` ніколи не кешуються. - **Власні іконки на мобільних пристроях** — Зміна фавікона в налаштуваннях не оновлює іконку на головному екрані мобільного пристрою (для цього потрібно повторно згенерувати іконки PWA). ## Довідник файлів | Файл | Призначення | | --------------------------------------- | ------------------------------------------------------------------- | | `src/app/manifest.ts` | Маршрут маніфесту Next.js (генерує `manifest.webmanifest`) | | `public/sw.js` | Сервіс-воркер із логікою кешування | | `src/shared/components/PwaRegister.tsx` | Клієнтський компонент, який реєструє сервіс-воркер | | `src/app/offline/page.tsx` | Резервна офлайн-сторінка з індикатором стану в реальному часі | | `src/app/layout.tsx` | Кореневий макет із метаданими PWA (apple-web-app, theme-color тощо) | | `public/icon-512.png` | Іконка PNG 512×512 (Android, екран-заставка) | | `public/apple-touch-icon.png` | Іконка PNG 180×180 (головний екран iOS) | | `public/icon-192.svg` | Іконка SVG 192×192 (адаптивна іконка Android) | | `public/apple-touch-icon.svg` | Іконка SVG 180×180 (резервна іконка Apple) |