- Страницы обоих брендов из блоков Payload (D-029): главная, цены, локации, поддержка, 4 юридические, 404 и 500. Коллекции pages (черновики и версии) и faq с местами показа, 12 типов блоков; поля sites — почта и Telegram поддержки, часы работы, SEO по умолчанию. - Карта и глобус рисуются на сервере (d3-geo), контуры во внешнем SVG через <use>; выбор локации синхронизирован между картой и сеткой. - Тексты сайта и юридические черновики на 5 языках: de, fr, es — перевод с глоссарием; seed создаёт страницы и FAQ, только если их нет, SEED_CONTENT=reset пересоздаёт. - SEO: title и описания, canonical, hreflang с x-default, sitemap.xml и robots.txt на каждый домен, картинки для соцсетей. - Статическая сборка и пересборка через revalidatePath из хуков Payload (D-030); /svc/internal/revalidate для проверки. - 404 — статичная страница со статусом 404 через proxy; на сайте только опубликованные страницы. - Производительность: Client Hints темы Payload только в админке, предзагрузка 2 файлов шрифтов вместо 6; Lighthouse mobile 97–99. - Контраст --ink-3 по WCAG AA, радиокнопки вместо div role=button. - Документация: итоги 1b, глоссарий de/fr/es, трактовки юридических черновиков подтверждены, переносимые вопросы — в этапах 3e–3h. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
18 KiB
07. Фронтенд
1. Макеты
- Источник — design/handoff/project/, экспорт Claude Design. Прототипы на HTML: разметка внутри
<x-dc>, логика в<script data-dc-script>, стили — inline плюс CSS-переменные в<style>.support.js— среда выполнения прототипа, в продукт не переносится. - Задача — воспроизвести внешний вид точно, читая код макетов: отступы, размеры, цвета, состояния. Внутреннюю структуру прототипа не копируем.
- Тексты макетов — на русском, английские версии — в
i18n.js(словарь «русская строка → английская»). - Бриф дизайна —
design/handoff/project/uploads/(файл «Дизайн VEILIX.md»). Где бриф расходится с прототипами или с 01-product.md, верны прототипы и 01-product.
2. Какой макет куда
| Макет | Вейликс | ВейликсВПН |
|---|---|---|
Main / MassMain |
veilix.app / |
veilixvpn.com / |
Price / MassPrice |
/pricing |
/pricing |
Locations / MassLocations |
/locations |
/locations |
Support / MassSupport |
/support |
/support |
Order / MassOrder |
my.veilix.app /order |
my.veilixvpn.com /order |
App / MassApp |
my.veilix.app: /login, /, /keys, /keys/[id], /buy, /billing, /referral |
то же на my.veilixvpn.com |
AppTG / MassAppTG |
tg.veilix.app (этап 2a) | tg.veilixvpn.com (этап 2a) |
Плюс страницы без макета: /legal/terms, /legal/privacy, /legal/refund, /legal/cookies, 404 и 500 — в стиле сайта.
3. Маршруты кабинета
| Путь | Что |
|---|---|
/login |
вход по коду |
/ |
главная: ключи, «Купить ключ», FAQ |
/keys, /keys/[id] |
список ключей, страница ключа: срок, автопродление, «Продлить сейчас», WG-конфиги (скачать, QR), ссылка Happ/Xray (копировать, QR) |
/buy |
покупка внутри кабинета: dedicated — сетка локаций с ценами, mass — «Месяц» и «Год» |
/order |
оформление заказа: шаги «Почта» и «Оплата», сводка |
/billing |
баланс, пополнение, карта, ближайшие списания, история |
/referral |
реферальная программа |
/more |
вкладка «Ещё» на узком экране: счёт, рефералы, поддержка, тема, язык |
/r/[код] |
реферальная ссылка: ставит cookie и ведёт на сайт бренда |
Навигация по макету: на широком экране — боковая панель, на узком — плавающая панель вкладок «Главная, Ключи, Купить, Ещё».
4. Темы и токены
- Tailwind v4: токены макета — CSS-переменные, подключённые в
@theme. Бренд задаёт атрибутdata-site="dedicated|mass"на<html>, тему —data-theme="light|dark". Режим «Как в системе» следуетprefers-color-scheme. - Переключатель темы — 3 режима, как в макете. Выбор хранится в localStorage (ключ
vx_theme), тема применяется скриптом в<head>до отрисовки. Новый посетитель видит «Как в системе». localStorage у каждого хоста свой: тема, выбранная на сайте, не переходит в кабинет. - Токены в OKLCH, как в макете. Ниже — для ориентира; точные значения — в
<style>прототипов, при расхождении верен прототип.
| Токен | Вейликс светлая | Вейликс тёмная | ВейликсВПН светлая | ВейликсВПН тёмная |
|---|---|---|---|---|
--bg |
99% .005 296 (#fcfbff) | 17% .022 296 (#100d18) | 99.6% .0015 215 | 23% .026 210 |
--surface |
100% 0 0 | 21% .026 296 | 100% 0 0 | 26.5% .028 210 |
--surface-2 |
97.5% .01 296 | 24% .03 296 | 98.4% .003 215 | 30% .03 210 |
--ink |
24% .04 296 (#211b30) | 96% .01 296 | 24% .04 204 | 96% .012 196 |
--ink-2 |
45% .03 296 | 79% .02 296 | 45% .03 204 | 80% .02 196 |
--ink-3 |
53% .025 296 | 66% .025 296 | 53% .025 204 | 69% .025 196 |
--border |
92% .014 296 | 31% .032 296 | 92% .014 200 | 36% .04 204 |
--accent |
45% .17 296 (#6137a6) | 74% .15 296 (#b495fe) | 48% .105 178 (#00705e) | 76% .105 190 (#52c6c0) |
--accent-hover |
38% .17 296 | 80% .13 296 | 41% .1 178 | 83% .09 190 |
--accent-soft |
95.5% .028 296 | 27% .05 296 | 95.5% .032 180 | 31% .05 190 |
--on-accent |
99% .01 296 | 17% .03 296 | 99% .01 180 | 20% .04 204 |
--glow-1/2/3 |
86% .1 296 / 89% .09 266 / 91% .08 332 | 45% / 40% / 42% | 86% .085 190 / 88% .075 205 / 89% .07 172 | 52% .09 200 / 47% .085 215 / 50% .08 180 |
--sel |
— | — | 96.5% .016 190 | 30% .03 195 |
Общие для брендов: --warn (62% .14 62 / 78% .13 62), --tg (62% .15 250 / 70% .13 250), --veil (белый 55% / 7%), --shadow, цвета карты --land, --land-line, --ocean.
В коде токены — src/styles/tokens.css, утилиты Tailwind называются так же (bg-surface, text-ink-2, bg-sel); стандартная палитра Tailwind отключена. У Вейликса --sel равен --accent-soft. Цвета карт Вейликса: глобус в hero — значения Main (они светлее), плоская карта — значения Locations (решено на этапе 1b).
5. Шрифты, иконки, логотип
- Commissioner 300–600 — весь текст; Unbounded 600 — только надпись логотипа. Подключение через
next/font: файлы скачиваются при сборке и отдаются с нашего домена, без запросов к Google Fonts. Предзагружаются только latin и cyrillic у Commissioner; остальные наборы (latin-ext с «₽») и Unbounded браузер скачивает поunicode-range, когда встречает их символы. - Иконки, флаги и логотип в макете нарисованы CSS-фигурами. Переносим их React-компонентами, сохраняя вид.
- Логотип — вариант «Слои». Фавиконы —
favicon.svgиfavicon-mass.svgиз макета.
6. Карта мира
- В макете карта строится в браузере через d3 и topojson с загрузкой данных с CDN. В продукте SVG-карта рендерится на сервере при сборке: d3-geo, проекция Natural Earth, данные
world-atlas(countries-110m) из npm. - В браузере — только интерактив: подсветка, всплывающая карточка, синхронизация с сеткой локаций.
- На узком экране карта прокручивается горизонтально, как в макете.
- Глобус в hero главной (
Main,MassMain) — ортографическая проекция, тоже рисуется на сервере, без интерактива.
7. Решения по расхождениям в макетах
- Устройств — 5, это поле тарифа. Цена продления dedicated — 2 499 ₽, цены задаются тарифами (3 уровня).
- Оформление заказа получает тариф, локацию и валюту из ссылки. В макете там всегда Нидерланды и 4 900 ₽.
- Поля номера карты из макета
Orderне делаем: карта вводится в виджете провайдера (этап 4b). В фазе 1 — демо-оплата (D-027). - Mass: в кабинете «Список ключей», без «текущей/запасной локации» и без экрана смены страны. Внутри ключа — ссылка Xray и WG-конфиги по странам.
- Статус локации показываем везде одинаково: в списках, карточках и на карте.
- Кнопка «Получить VPN» на главной ведёт к блоку цен на этой же странице, на остальных страницах — на
/pricing. - FAQ — одна коллекция с местами показа: главная, цены, поддержка (3 раздела), кабинет, MiniApp.
- Контакты поддержки берутся из настроек сайта, Telegram — ссылка на бота поддержки.
- Плашки способов оплаты в подвале — по активным платёжным системам сайта.
- Добавляем то, чего нет в макете: переключатель валюты,
<title>и мета-описания, H1 на каждой странице, поддержкуprefers-reduced-motionдля анимаций. - Количество свободных серверов показываем рядом со статусом, если поле заполнено (D-032).
- Переключатели при 5 языках и с валютой (в макете только RU/EN, валюты нет). В шапке — выпадающие списки языка и валюты. В подвале, мобильном меню и кабинете — сегменты с кодами языков (EN RU DE FR ES) и символами валют (₽ $). В оболочке кабинета валюты нет: она появится в настройках (1f).
- В подвале четыре документа: добавлена «Политика cookies». Плашек способов оплаты нет, пока нет видимых пользователю платёжных систем (пункт 9).
- Кабинет mass: подписи навигации те же, что у dedicated («Список ключей», «Купить ключ», «Ключи»). Подписи макета MassApp («Подключения», «Выбрать страну», «Подписка») не используем (пункт 4).
- Ширина надписи логотипа — по содержимому: в макете она подогнана под русское название.
- 404 и 500 (решено на этапе 1b):
a.
notFound()в Next 16 отдаёт пустую оболочку (<html id="__next_error__">) и рисует 404 в браузере: клиентская граница при серверной отрисовке не срабатывает. Поэтому proxy ведёт неизвестные адреса сайта на внутреннюю статичную страницуpage-not-foundсо статусом 404 (NextResponse.rewriteсstatus,decide.ts). Она отрисована на сервере, в шапке и подвале бренда, на языке из адреса; b.notFound()остаётся для внутренних путей и удалённых в админке страниц — там 404 по-прежнему рисуется в браузере; c. 500:error.tsxсайта (шапка и подвал на месте, кнопка «Обновить страницу») иglobal-error.tsxна случай, когда не отрисовался корневой layout (бренд — по домену, язык — по префиксу адреса). Ошибки Next по устройству рисует в браузере. - Реферальная программа (1h): бонус — дни срока ключа, а не деньги (D-025). Текст под ссылкой «Месяц начисляется вам и другу… и применяется к ближайшему списанию» заменяем на условия в днях. В истории платежей строка «Реферальный бонус» показывает «+30 дней» вместо «+2 499 ₽». Счётчик «Месяцев начислено» и статусы приглашённых остаются.
- Тексты описывают работающий продукт, а не ограничения текущего этапа: «сразу после оплаты», оплата картой, автопродление, смена страны — как в макетах (D-026).
- Тексты страниц — в Payload, страницы собираются из блоков (D-029).
- Вейликс — «индивидуальный IP»: выделенный адрес на общем сервере. Формулировки «персональный сервер», «без соседей по серверу», «персональные VPN-серверы» не используем.
- ВейликсВПН: RU-адрес входит в ключ, но страной не считается (D-031); число стран — из данных, только «Включено»; протоколы — Xray и WireGuard.
- Поддержка: сроки ответа не обещаем, часы — «с 10 до 20 по московскому времени в рабочие дни». Telegram —
@veilix_supportу обоих брендов, пока нет ботов поддержки (этап 3e). - Контраст:
--ink-3подобран до 4,5:1 (WCAG AA) на всех фонах темы, включая выделенные карточки; в макетах было 3,5–4,3:1 (таблица в разделе 4). - Карта локаций: точки расположены как в макете, клик выбирает ближайшую точку (в Европе точки перекрываются); выбор синхронизирован с сеткой карточек и отмечен кольцом на карте; всплывающая карточка — HTML поверх карты, со статусом. Контуры стран и глобуса — внешний SVG
/svc/geo/…с версией в адресе: в HTML они попали бы дважды (разметка и данные React). - Межстрочный интервал в секциях страниц —
normal, как в макетах (там он нигде не задан); у текстов с заданным интервалом — их значения. Шапка и подвал из 1a не менялись. - Текущий раздел в шапке выделен цветом текста, как в макетах: CSS по атрибуту
data-pageстраницы, без JavaScript. - Под формами — строка о согласии с политикой конфиденциальности со ссылкой; формы до этапов 3d и 3e только проверяют поля и показывают «отправлено».
8. Состояния, которых нет в макетах
Рисуем в стиле макета на соответствующих этапах:
- Вход: ошибка кода, истёкший код, таймер повторной отправки, загрузка.
- Ключ: готовится (до 24 часов), льготный период, истёк, заблокирован; пустой список ключей; ключ без подключений.
- Заказ: «ожидает оплаты», не хватает баланса, оплата не прошла (этап 1e); 3-D Secure и счёт в криптовалюте — этап 4b.
- Счёт: своя сумма пополнения, подтверждение отвязки карты, результат пополнения.
- Общие: уведомления (тосты), скелетоны загрузки, страницы 404 и 500, ошибки валидации форм.
9. Производительность и доступность
- Маркетинговые страницы: Lighthouse mobile ≥ 90 (цель 95+), LCP ≤ 2 с, CLS ≤ 0.05, INP ≤ 200 мс.
- JavaScript в браузере — только интерактивные островки: переключатели языка, валюты и темы, FAQ, выбор локации, формы, карта.
- Сторонние скрипты при первой загрузке — только Umami (асинхронно). ALTCHA подгружается только на формах.
- Доступность — WCAG 2.1 AA: контраст, видимый фокус, работа с клавиатуры для выпадающих списков, аккордеонов и шитов, области нажатия ≥ 44 px.
- Заголовки Client Hints темы (
Accept-CH,Critical-CH,Vary), которыеwithPayloadставит на все адреса, оставлены только админке (next.config.ts): на сайтеCritical-CHзаставлял Chrome повторять первый запрос страницы, Lighthouse оценивал это в 0,7 с.