---
name: avtero_public_site
description: "avtero публичный сайт https://avtero.codoceh.ru = Next.js-приложение local.avtero-frontend (kodoceh-web/apps/avtero, :20410) через codoceh VPS-edge; templates/index.html на :8201 — легаси. Правишь публичный UI → Next.js page.tsx + rm -rf .next && npm run build + kickstart"
metadata: 
  node_type: memory
  type: project
  originSessionId: 4eea915e-3b47-4cd5-8a0e-bfa29b78a87c
---

**АКТУАЛЬНО (2026-07-07): два фронта, не перепутать.** Публичный `https://avtero.codoceh.ru` обслуживает **Next.js-приложение** `local.avtero-frontend` — `~/Разработки/kodoceh-web/apps/avtero` (`npm run start`, NODE_ENV=production, слушает :20410), наружу через **codoceh VPS-edge** (Caddy+rathole 195.133.147.176, домен через «c», см. [[codoceh_vps_edge]]) — НЕ через localtunnel. Рендер отчёта/подбора = `apps/avtero/app/app/page.tsx` (клиентский компонент: `Result`/`PartCard`/`OemList`). Правишь публичный UI → правь этот `page.tsx`, затем `PATH=/opt/homebrew/bin rm -rf .next && npm run build` + `launchctl kickstart -k gui/$(id -u)/local.avtero-frontend` (иначе stale-бандл; content-hash чанка меняется → кэш-бастинг автоматом). Второй, ЛЕГАСИ фронт — `~/Services/avtero/templates/index.html`, отдаётся FastAPI :8201 (Jinja2 `TemplateResponse`, auto_reload по mtime — рестарт не нужен); держим для паритета/встройки. Общий API — :8201 `/api/*`, фронт ходит по относительному `/api`. Тест залогиненного рендера headless: сессионная кука `pk_session`=`webauth.make_session({'tg_id':8688355181})`, онбординг пропускается `localStorage cbr_onb_avtero=1`. См. [[avtero_overview]].

**Ниже — ИСТОРИЧЕСКОЕ (localtunnel-эра, до перехода на codoceh VPS-edge; актуально только как fallback без VPS):**

**Публичный доступ к сайту avtero — бесплатно, без VPS и без покупки домена: `https://avtero.codoceh.ru`** (localtunnel пробрасывает порт 8201 мини наружу, sticky-сабдомен `avtero`). Открывается из любой сети, **клиент-ПО не требуется** (в отличие от Tailscale). launchd `local.avtero.tunnel` (npx localtunnel, KeepAlive).

**Почему именно localtunnel:** Cloudflare quick-tunnel дал 0/10 доступности из РФ (РКН режет cloudflared edges); Tailscale Funnel тоже не годится — сам мини ходит к серверам Tailscale только через анти-цензур-прокси (ops `tailscaled` запущен с `HTTPS_PROXY=127.0.0.1:2081`), значит у РФ-посетителя ingress Tailscale не откроется. localtunnel проходит сквозь РКН — поэтому он и стоит в проде.

**Слабое место + фикс:** localtunnel периодически молча теряет sticky-имя (сваливается на случайное `*-*-NN.loca.lt`) или зависает, а launchd KeepAlive это НЕ ловит (процесс формально жив) → сайт уходит в 503. Решение (2026-06-22): вотчдог `local.avtero.tunnel-watchdog` (`~/Services/avtero/scripts/loca_watchdog.sh`, StartInterval 90c) пингует ПУБЛИЧНЫЙ `…/healthz`; не 200 → `launchctl kickstart -k local.avtero.tunnel`. Лог `~/Services/avtero/logs/loca_watchdog.log`.

Косметика: первый заход из браузера → страница-заглушка loca.lt «Continue» (один клик, дальше по куке; curl с дефолтным UA её не видит).

**VPS zbrcheck для avtero НЕЛЬЗЯ** (юзер, 2026-06-22): тот VPS/edge выделен строго под zbrcheck и сопутствующие ему проекты — `avtero.zbrcheck.ru` НЕ предлагать. avtero остаётся на loca.lt (бесплатно, без VPS, без домена). Запасной туннель без IP-заглушки — localhost.run (`lhr_tunnel` уже на мини), но на free поддомен скачущий (нет постоянного адреса) → для продукта хуже, оставляем loca.lt.

**PWA «Установить приложение» (v0.7.19, commit cabfa0f):** манифест+иконки были, добавлены `GET /sw.js` (минимальный SW в корневом scope, заголовок `Service-Worker-Allowed: /` — иначе scope `/static/`) + плавающая кнопка «📲 Установить приложение» (Android → нативный `beforeinstallprompt`; iOS Safari → инструкция Поделиться→На экран Домой, программно на iOS нельзя; скрыта если standalone). Реальный prompt тестировать на телефоне.

**API через loca.lt чинится заголовком (commit 5117970):** loca.lt отдаёт `fetch`/XHR с браузерным UA свою заглушку (HTTP 511 + HTML) вместо JSON → форма падала «Не удалось отправить запрос». Фикс: враппер `window.fetch` шлёт заголовок `bypass-tunnel-reminder` на все запросы (loca.lt такие пропускает). Навигацию по странице (первый заход, IP-заглушка) обойти для браузера нельзя. См. [[avtero_overview]], [[ceberspost_connect_product_channel]].
