МЕРА B2C: микроразметка schema.org и картинки превью ссылок #3438
No reviewers
Labels
No labels
Fable 5 ревью
GG-форсайт
admin
analytics
auth
automation
bug
business
chore
ci
compliance
data
data-moat
docs
duplicate
dx
enhancement
feedback/max
generative
needs-discussion
needs-human
observability
pause-bots
performance
priority/p0
priority/p1
priority/p2
priority/p3
scope/backend
scope/db
scope/devops
scope/frontend
scope/qa
scrapers
security
site-finder
stage/1
stage/2
status/blocked
status/done
status/needs-analysis
status/needs-fix
status/qa
status/ready
status/review
status/wip
tech-debt
tradein
ux
week ревью 1
wontfix
ИРД
вторичка
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: lekss361/gendesign#3438
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "feat/mera-schema-og"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Сайт открыт для индексации 10.09.2026, но поисковику он представлялся девятью страницами без единого структурированного факта о том, кто их публикует и что продаёт, а ссылка на него в мессенджере разворачивалась голым текстом без картинки.
Микроразметка
Конструкторы узлов вынесены в
_lib/schema.ts— чистый модуль без React, по образцу соседнего_lib/analytics.ts. Все значения берутся изcontent.ts, ни одной строки не продублировано.Organization+WebSiteодним@graphService+OfferFAQPageBreadcrumbListArticle(был)publisher: { "@id": ... }Разметка не обещает того, чего нет
Два места, где это стоило внимания:
Offer.availabilityвычисляется изPUBLIC_ESTIMATE_ENABLED. Флаг сейчасfalse, платёжного контура в коде нет, поэтому в разметку уходитPreOrder, а неInStock: цена опубликована, купить нельзя, и врать об этом поисковику нечего. Включится приём оплаты — значение сменится само.FAQPageстроится из того же массиваITEMS, который рисует<details>, а не изFAQнапрямую: вITEMSчасть вопросов заменена макетными формулировками, и разметка от сырогоFAQразошлась бы с видимым текстом молча.Выдуманных дат, рейтингов и отзывов не добавлено нигде.
Картинки
Две штуки, и это не дубль:
og-mera.png1200×630 — превью ссылки,logo-mera.png512×512 — логотип организации в разметке, который поисковик обрезает близко к квадрату и где баннер превратился бы в обрезок надписи. Исходники обеих лежат рядом вscripts/og/*.htmlвместе с командой перерисовки.Готовые PNG, а не
opengraph-image.tsx: satori внутриImageResponseрисует только переданными ему байтами шрифта и кириллицу по умолчанию не покрывает, плюс не видит ни CSS Modules, ни наших--b2c-*. Разбор — в шапкеscripts/og/og-mera.html.imagesпродублирован вtwitter: Next не переносит их изopenGraph, когда метаданные заданы объектом, и карточка обещала бы крупное превью без картинки.Периметр
Обе картинки лежат в
public/и раздаются Next'ом по basePath-корню, куда rewrite@meraPagesне достаёт — отсюда два отдельныхhandleпо образцу robots.txt. Оба названы вROOT_HANDLES_ALLOWED: корневойhandleэто вторая дверь в тот же периметр, и гейт обязан её видеть.Смоук проверяет не только 200, но и Content-Type. Перепутанный rewrite отдаёт 200 с HTML, обходчик мессенджера молча его отбрасывает, и по логам приложения этого не видно: запрос туда не доходит.
Проверено
npx tsc --noEmit,npx eslint src/app/mera-public --max-warnings=0— чистоnpx vitest run src/app/mera-public/__tests__— 18 файлов, 215 тестовnode scripts/check-mera-public-isolation.mjs— 70 файлов, закрытый контур не найденcaddy validateна эффективном конфиге — Valid configurationbash -nсмоука — чистоbasePath=/trade-inи разбор отрендеренного HTML: JSON-LD парсится на всех пяти страницах,og:imageиtwitter:imageна местеПолный
npm testдаёт два падения вsrc/app/login/__tests__/LoginPage.test.tsx— известный локальный дефект среды, воспроизводится и на нетронутом дереве, к этим правкам отношения не имеет.Ревью
code-reviewer: approve, замечаний нет.После деплоя (владельцу)
Разметку и превью имеет смысл проверить снаружи: валидатор структурированных данных Яндекса и Google Rich Results Test, плюс отправить ссылку самому себе в Телеграм и посмотреть картинку.
🤖 Generated with Claude Code
https://claude.ai/code/session_01CiUFZ3rmTNpp3DRajUo8KQ
Сайт открыт для индексации 10.09.2026, но поисковику он до сих пор представлялся девятью страницами без единого структурированного факта о том, кто их публикует и что продаёт, а ссылка на него в мессенджере разворачивалась голым текстом без картинки. МИКРОРАЗМЕТКА. Конструкторы узлов вынесены в `_lib/schema.ts` — чистый модуль без React, по образцу соседнего `_lib/analytics.ts`. Все значения берутся из `content.ts`, ни одной строки не продублировано: - `Organization` + `WebSite` одним `@graph` в layout поддерева, то есть на всех девяти страницах сразу. Остальные узлы ссылаются на организацию через `@id`, а не повторяют реквизиты у себя. - `Service` с `Offer` на лэндинге. - `FAQPage` в блоке возражений. - `BreadcrumbList` на статьях, статье, документах и странице для бизнеса — ровно по тем крошкам, что видны на экране. - Существующий `Article` переведён на ссылку `publisher: { "@id": ... }`. РАЗМЕТКА НЕ ОБЕЩАЕТ ТОГО, ЧЕГО НЕТ. Два места, где это стоило внимания: - `Offer.availability` вычисляется из `PUBLIC_ESTIMATE_ENABLED`. Флаг сейчас `false` (платёжного контура в коде нет), поэтому в разметку уходит `PreOrder`, а не `InStock`: цена опубликована, купить нельзя, и врать об этом поисковику нечего. Включится приём оплаты — значение сменится само. - `FAQPage` строится из того же массива `ITEMS`, который рисует `<details>`, а не из `FAQ` напрямую: в `ITEMS` часть вопросов заменена макетными формулировками, и разметка от сырого `FAQ` разошлась бы с видимым текстом молча. Выдуманных дат, рейтингов и отзывов не добавлено нигде. КАРТИНКИ. Две штуки, и это не дубль: `og-mera.png` 1200×630 — превью ссылки, `logo-mera.png` 512×512 — логотип организации в разметке, который поисковик обрезает близко к квадрату и где баннер превратился бы в обрезок надписи. Исходники обеих лежат рядом в `scripts/og/*.html` вместе с командой перерисовки: картинка должна оставаться правимой, а не только переоткрываемой в графическом редакторе. Готовые PNG, а не `opengraph-image.tsx`: satori внутри `ImageResponse` рисует только переданными ему байтами шрифта и кириллицу по умолчанию не покрывает, плюс не видит ни CSS Modules, ни наших `--b2c-*`. Разбор — в шапке `scripts/og/og-mera.html`. `images` продублирован в `twitter`: Next не переносит их из `openGraph`, когда метаданные заданы объектом, и карточка обещала бы крупное превью без картинки. ПЕРИМЕТР. Обе картинки лежат в `public/` и раздаются Next'ом по basePath-корню, куда rewrite `@meraPages` не достаёт, — отсюда два отдельных `handle` по образцу robots.txt. Оба названы в `ROOT_HANDLES_ALLOWED`, иначе двусторонний гейт периметра покраснел бы, и это правильно: корневой `handle` — вторая дверь в тот же периметр. Смоук проверяет не только 200, но и Content-Type: перепутанный rewrite отдаёт 200 с HTML, обходчик мессенджера молча его отбрасывает, и по логам приложения этого не видно — запрос туда не доходит. Проверено: tsc, eslint, 215 тестов mera-public, изоляция B2C-дерева, caddy validate, bash -n смоука, прод-сборка с basePath и разбор отрендеренного HTML — JSON-LD парсится, og:image и twitter:image на месте. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CiUFZ3rmTNpp3DRajUo8KQ