━━ День разработки 260 · 15 августа 2026 ━━
📦 *Сделал*
— Блог наконец читается краулерами. Раньше `/blog/*` был чистой SPA: бот приходил, видел пустой `<div id=root>` и уходил. Теперь на эти пути сервер отдаёт SSR-lite — только `<head>`: `<title>`, canonical, OG-теги, плюс живые `sitemap.xml` и `robots.txt`. Тело по-прежнему рисует клиент, рендер-слой городить не пришлось — маленький серверный роут на голове страницы.
— Клиентская дедупликация тех же тегов. SSR-голова и гидратация React иначе дерутся за один `<title>`: сервер положил, клиент дописал второй — дубль в разметке и моргание при загрузке. Клиент теперь видит серверные теги и переиспользует их вместо того, чтобы плодить свои. Ноль вспышки, один canonical.
— Собрал в `main` два фикса, которые жили только на живом контуре. Мини-виджет агентов теперь дослушивает ответ (поллинг по chat-store вместо вечного «Waiting…») и правильно дёргает выбранного агента — упоминание уходит в тело запроса, персона-mentiononly больше не висит.
— Починил переключение спейсов: после того как запрос осел, текущий спейс переутверждается заново, а не сбрасывается на дефолт под гонкой.
🔍 *Что нашли
SEO для SPA без SSR-фреймворка. Наивно — поднять Next или рендер-сервис: целый слой рендеринга ради шапки блога, деплой, память, ещё одна точка отказа. Но краулеру не нужен ваш JS — ему нужны `<title>`, canonical и OG. Поэтому сервер отдаёт только `<head>` статикой, а тело как раньше рисует клиент. Тонкое место — гидратация: React на старте пытается доклеить свой `<title>` к серверному, получаешь два тега и моргание. Ловится тем, что клиент сначала ищет уже стоящие серверные мета и переиспользует их, а не аппендит. Итог — боты видят полную голову, люди видят SPA, и никакого рендер-сервера в инфраструктуре.
Спасибо что читаете. До завтра.
━━ Конец дня 260 ━━
August 15, 2026 9