Установите opolyx на телефон — и входите без пароля
opolyx теперь полноценно устанавливаемое приложение, а войти можно четырьмя способами: по ссылке, по коду из письма, через Google или Apple. Код работает везде.

Простыми словами
opolyx можно добавить на домашний экран и открывать как обычное приложение: собственная иконка, никаких панелей браузера, сразу лобби. Это уже работает на Android и iOS из меню браузера, и это та же сборка, которую мы упаковываем для магазинов приложений.
- открывается на весь экран сразу в лобби, а не на маркетинговой странице;
- сохраняет собственную иконку и заставку вместо ярлыка браузера;
- показывает нормальную страницу opolyx без интернета вместо браузерной ошибки;
- никогда не кеширует ничего из живой партии — установленное приложение так же свежо, как сайт.
Способов входа теперь четыре, и можно выбрать тот, что удобнее на вашем устройстве:
| Способ | Как это работает |
|---|---|
| Волшебная ссылка | ссылка в письме — одно нажатие, без пароля |
| Код из письма | код из 8 символов, который вы вводите на странице входа |
| обычное окно выбора аккаунта | |
| Apple | включая Hide My Email — что за ним, мы не видим |
Код из письма — тот способ, который работает абсолютно везде, в том числе внутри приложения-обёртки, где ссылка открывается в отдельном браузере и не может вернуть сессию.
Для тех, кому интересны детали
Service worker намеренно узкий. Это список разрешённого, а не «всё подряд»: навигации идут по схеме «сначала сеть» с офлайн-страницей как запасным вариантом, статические файлы с хешем — stale-while-revalidate, а всё остальное — база данных, игровой сервер, realtime, аутентификация, серверные полезные нагрузки — пропускается мимо, поэтому он не может отдать устаревшее поле или сломать живую партию.
// public/sw.js — allow-list, not catch-all
self.addEventListener('fetch', (event) => {
const url = new URL(event.request.url);
if (url.origin !== self.location.origin) return; // Supabase, daemon: untouched
if (BYPASS.some((p) => url.pathname.startsWith(p))) return; // /auth, /api, RSC
if (event.request.mode === 'navigate') return event.respondWith(networkFirst(event));
if (HASHED.test(url.pathname)) return event.respondWith(staleWhileRevalidate(event));
});Самым интересным оказался обёрнутый iOS-билд, где не срабатывал ни один способ входа, хотя во всех браузерах всё работало. Причина — настройка WebKit, которую инструмент упаковки пишет за вас: при включённых «доменах, привязанных к приложению» WebKit молча отменяет любую навигацию верхнего уровня к хосту, которого нет в списке, а первый переход в OAuth-потоке — ровно такая навигация. Отдельно Google по своей политике отказывает встроенным webview, и это не лечится никакой конфигурацией.
Волшебная ссылка там и не могла бы сработать: она открывается в системном браузере, чьё хранилище cookie webview приложения не видит. Именно поэтому ввод кода — единственный почтовый маршрут в рамках того же источника: он завершается в том самом webview, который его запросил.
Для Google санкционированный путь — выполнить поток в системном браузере и вернуть сессию обратно. Мост строит URL авторизации намеренно без PKCE, чтобы поток вернул токены во фрагменте адреса, который оболочка может прочитать: код авторизации смог бы обменять только браузер, у которого есть верификатор, а это не тот браузер.
