К содержимому
Генеральные партнёры
Партнёры

Техническая документация

Дизайн-система, реестры и правила разработки

Раздел для разработки и подрядчиков. Описание проекта простым языком — в «Как устроен проект». Живая витрина компонентов — дизайн-система.

Реестры на этой странице рендерятся из тех же данных, что и сайт. Добавили тему в src/data/moods.ts — она появилась здесь сама; переписывать таблицы руками не нужно и нельзя.

Содержание

Дизайн-система

Компонент не использует сырых значений — только токены. Значения ниже собраны из src/styles/tokens/*.css; таблица-источник — docs/design/TOKENS.md.

Цвет — сырые шкалы

ТокенЗначениеТокенЗначение
--c-brand-950#050F26--c-ice-0#FFFFFF
--c-brand-900#081B3F--c-ice-50#F8FAFF
--c-brand-800#0E2A63--c-ice-100#EFF3FB
--c-brand-700#14357F--c-ice-200#E1E9F5
--c-brand-600#1E40AF--c-ice-300#C9D6E8
--c-brand-500#2563EB--c-ice-400#9DAFC7
--c-brand-400#3B82F6--c-ice-500#6D7F98
--c-brand-300#7DA9FF--c-ice-600#4A5A73
--c-brand-200#B4CCFF--c-ice-700#2E3D54
--c-brand-100#DCE7FF--c-ice-800#1A2537
--c-brand-50#F1F6FF--c-ice-900#0C1421
ТокенЗначение
--c-gold-600#A8801F
--c-gold-500#C9A84C
--c-gold-400#DCC077
--c-gold-300#EBD9A6
--c-live#E11D48
--c-success#0FA968
--c-warning#E8A33D
--c-danger#DC2626

Семантика

Компоненты работают только с ней. Тёмная тема — атрибут секции (<section data-theme="dark">), а не переключатель пользователя: атом внутри тёмной секции перекрашивается сам.

ТокенОбразец
--color-bg#F8FAFF· var(--c-ice-50)
--color-bg-subtle#EFF3FB· var(--c-ice-100)
--color-surface#FFFFFF· var(--c-ice-0)
--color-surface-2#F8FAFF· var(--c-ice-50)
--color-text#0C1421· var(--c-ice-900)
--color-text-muted#4A5A73· var(--c-ice-600)
--color-border#C9D6E8· var(--c-ice-300)
--color-accent#1E40AF· var(--c-brand-600)
--color-accent-hover#14357F· var(--c-brand-700)
--color-accent-soft#F1F6FF· var(--c-brand-50)
--color-focus#3B82F6· var(--c-brand-400)
--color-gold#C9A84C· var(--c-gold-500)

Типографика

РольРазмер
display-1clamp(2.75rem, 1.2rem + 6.4vw, 6.5rem)
display-2clamp(2.25rem, 1.3rem + 4.2vw, 4rem)
h1clamp(2rem, 1.35rem + 2.6vw, 3rem)
h2clamp(1.6rem, 1.25rem + 1.6vw, 2.25rem)
h3clamp(1.25rem, 1.1rem + 0.8vw, 1.5rem)
leadclamp(1.06rem, 1rem + 0.4vw, 1.25rem)
body1rem
sm0.875rem
label0.75rem / tracking .08em

Пространство, радиусы, тени, слои

Шаг
1 · 4px
2 · 8px
3 · 12px
4 · 16px
5 · 24px
6 · 32px
7 · 48px
8 · 64px
9 · 96px
10 · 128px
РадиусТокен
--r-xs
--r-sm
--r-md
--r-lg
--r-xl
--r-full
ТеньТокен
--shadow-1
--shadow-2
--shadow-3
--glow-accent
--glow-gold
Слой
--z-base · 0
--z-sticky · 100
--z-header · 200
--z-dropdown · 300
--z-overlay · 400
--z-modal · 500
--z-toast · 600

Движение

ДлительностьЗначение
--dur-instant120ms
--dur-fast200ms
--dur-base320ms
--dur-slow520ms
--dur-cine820ms
КриваяЗначение
--ease-standardcubic-bezier(.2,.6,.2,1)
--ease-entercubic-bezier(0,.7,.2,1)
--ease-exitcubic-bezier(.4,0,1,1)
--ease-springcubic-bezier(.34,1.56,.64,1)

Поверхности и стекло

Стекло видно только там, где под ним есть что размывать. На светлом фоне backdrop-filter не ловит ничего, и карточка растворяется в секции. Поэтому стекло — только поверх изображения или тёмного фона (шапка над героем, подписи поверх кадра, панель над схемой регионов), а на светлых секциях — плотная поверхность --surface-1 с ледяной гранью --edge-highlight. Наглядно — в разделе «Материалы» витрины дизайн-системы.

Ритм секций и ледяной излом

Границы между секциями — не черта и не полоса, а полигональный излом: два слоя треугольных граней с разными углами, плоская заливка без градиентов внутри грани и обязательная пара «блик / глубина». Слой заезжает под контент соседних секций, поэтому граница блоков исчезает и страница читается единым массивом. Геометрия генерируется из seed (src/data/facets.ts), руками правятся только seed и палитра: полигоны, забитые в разметку, никто потом не осмелится трогать.

Тона секций и приёмы лежат в src/data/transitions.ts, а правила (излом только между светлым и тёмным, изломов не больше трёх плюс одно поле поперёк секции, не больше двух тёмных секций подряд, фактура только на светлой) проверяет scripts/test/transitions.test.mjs — нарушение роняет тест, а не всплывает на приёмке.

С 20.08 граней на главной нет ни одной: владелец забраковал приём как слишком грубый. Стык рисует мягкое растворение — градиент из фона верхней секции в фон нижней, тона берутся из того же реестра. Пять кандидатов на замену стоят рядом в лаборатории /lab/transitions/; колонка «приём» в реестре осталась описанием и ждёт выбора владельца.

СекцияТонФактураПриём в реестре
Геройdark
Новостиlightледяной излом · seed 17
Календарьlight-2glowрастворение
Специалистамlightрастворение
Сборнаяlight-2растворение
Дисциплиныdarkледяной излом · seed 43
Представительстваdark-2растворение
Медиаlight-2grainледяной излом · seed 91
Партнёрыlightрастворение

Событийные темы

Сайт реагирует на события, а не на человека: время суток, праздник, идущий старт. Профилирования и трекеров нет — контекст одинаков для всех, кто зашёл в эту минуту.

Активно не более одного настроения одновременно — с наибольшим приоритетом среди подходящих. Суточный слой (data-daypart) действует всегда и меняет только освещение. Траур — не «ещё одна тема», а стоп-кран: он гасит декор и анимации всех остальных.

Уважение к посетителю: переключатель «Спокойный вид» в подвале отключает декор и переживает перезагрузку; при prefers-reduced-motion декор статичен; в рабочих разделах и рядом с материалами с флагом sensitive декора нет вовсе.

idНазваниеКогдаПриоритетСлоиВключена
mourningТраурВключается вручную из админки, снимается вручную100lightда
live-eventИдёт соревнованиеПока есть старт со статусом «идёт»80priority, lightда
victoryПобедаВключается вручную после крупной победы, живёт 48 часов70light, copyда
figure-skating-day-ruДень фигурного катания в России8 января65light, decorда
new-yearНовогоднее20 декабря — 8 января60light, decorда
state-holidayГосударственный праздник23 февраля, 8 марта, 9 мая, 12 июня55light, copyда
world-ice-skating-dayВсемирный день конькобежного спортаДекабрь, дату ISU объявляет каждый год отдельно50light, copyда
season-startОткрытие сезона1–30 сентября40priority, copyда
frostМорозноКалендарная зима30light, decorда
pre-holidayКанун праздникаЗа один-два дня до праздника из реестра20copyда

Дата всемирного дня конькобежного спорта хранится по годам (dateByYear), а не считается формулой: ISU объявляет её каждый год отдельно — в 2025 это было 14 декабря, хотя на сайте события упоминается «первое воскресенье декабря». Год без даты — тема молчит, без ошибок и без угадывания.

Примерить любую тему можно на витрине дизайн-системы.

Сайты представительств

Права — флаг на пару «блок × регион». Включается в панели управления отдельно для каждого региона. Выключенный блок на сайте региона всё равно есть — его наполняет федерация. Сотрудники федерации могут отредактировать содержимое любого сайта.

БлокЧто показываетЧто даёт региону разрешениеЕсли регион не заполнил
ОбложкаФотография и название представительстваЗаменить фотографию и заголовокФедеральный кадр и название региона из справочника
О представительствеТекст о региональной организацииРедактировать текстОбщий текст федерации о работе представительств
НовостиЛента новостей регионаПубликовать свои новостиФедеральные новости с отметкой региона
СобытияКалендарь стартов регионаВести свой календарьВсероссийские старты, которые проходят в этом регионе
ФотогалереяСнимки соревнований и тренировокЗагружать фотографииБлок не показывается, пока нет ни одного снимка
Тренеры и специалистыСписок специалистов представительстваВести списокБлок не показывается, пока список пуст
КонтактыАдрес, телефон, почта представительстваМенять адрес, телефон, e-mailКонтакты из справочника регионов
ДокументыФайлы регионального уровняПубликовать файлыСсылка на федеральный раздел «Специалистам»
ПартнёрыЛоготипы партнёров регионаДобавлять логотипыПартнёры федерации

Карта разделов и переезд адресов

Ничего не выбрасываем. Единственное осознанное слияние — две новостные ленты. Контент не мигрируем, старый сайт остаётся на old.fsrussia.ru.

БылоСтало у насКомментарий
/news + /novosti-federatsii + /intervyu/news/Одна лента с рубриками: новости, анонсы, результаты, интервью, документы
/sbornaya/team/ + /athletes/<slug>/121 карточка — картотека с фильтрами
/sorevnovaniya/events/ + /events/<slug>/Календарь с прошедшими и предстоящими
Дисциплины (6)/disciplines/ + /disciplines/<slug>/Шесть, включая любительское и балеты
/obshchie-dokumenty, /kollegiya-sudej, /otchety/specialists/Единый документный раздел с категориями, ~70 файлов
/antidoping, /anti-doping-seminars/specialists/antidoping/49 файлов, структура сохраняется как есть
/testy/specialists/tests/Текстовый методический раздел, не архив файлов
/press-tsentr/press/Аккредитации и контакты для СМИ
/federatsiya/about/О федерации и Исполком; отсюда же ссылка на /docs/
/regions/Новое: карта и представительства
/search/Новое: сквозной поиск

301-редиректы

Без них поисковая выдача уходит в никуда. Глубокие ссылки на конкретные материалы уходят на old.fsrussia.ru тем же путём.

ОткудаКуда
/news/news/
/novosti-federatsii/news/
/sbornaya/team/
/sorevnovaniya/events/
/antidoping/specialists/antidoping/
/obshchie-dokumenty/specialists/
/kollegiya-sudej/specialists/
/otchety/specialists/
/testy/specialists/tests/
/press-tsentr/press/
/federatsiya/about/

Порядок блоков главной

Блок
1Полоса партнёров над шапкой
2Герой
3Лайв или ближайший старт — когда есть
4Новости — главный поток
5Календарь соревнований
6Специалистам: документы
7Сборная
8Дисциплины
9Карта представительств
10Медиа
11Партнёры-витрина

Данные и интеграции

Правило: страница не ходит в чужой API напрямую. Путь один — страница → src/api/ → фикстура или внешний сервис. Когда сервис коллег появится, меняется реализация функции, а вёрстка не трогается.

СущностьВладелецСейчасФункция apiФормаЗамечание
Новостисервисы коллегдемо-данныеgetNews, getNewsBySlugNewsItemЗаголовки и лиды сняты с действующего fsrussia.ru
Соревнованиясервисы коллегдемо-данныеgetEvents, getUpcomingEvents, getLiveEventCompetitionEventКалендарь сезона 2026/2027 из утверждённого Исполкомом PDF
Результаты и протоколысервисы коллегданных пока нетgetResultsByEventResultRowОпубликованных протоколов сезона нет; выдумывать баллы нельзя
Спортсменысервисы коллегдемо-данныеgetAthletes, getAthleteBySlugAthleteСостав и портреты — с опубликованной федерацией страницы сборной
Регионы и представительствамыдемо-данныеgetRegions, getRegionById, getRegionStatsRegionСправочник ведём сами; под сшивку с orgs коллег есть externalOrgId
Медиасервисы коллегдемо-данныеgetMediaMediaItemСвоих видеофайлов нет — у роликов только постер
Поискмыдемо-данныеsearch, getSearchSuggestionsSearchHitИндекс собирается из тех же фикстур один раз на модуль

Правила разработки

Стилизация — только токенамиСырые hex и «магические» пиксели невозможно перекрасить темой и нельзя переиспользовать на других направлениях федерации.
Анимируем transform и opacity, эффект — компонент в motion/width/height/top/left вызывают перерасчёт раскладки: на мобильном это каша. Копипаста эффекта в странице расходится с оригиналом через неделю.
Доступность: контраст AA, видимый фокус, цель 44px, prefers-reduced-motionПортал федерации читают с телефонов и с клавиатуры. Кольцо фокуса убирать нельзя даже «ради красоты».
Данные — только через src/api/Когда появится сервис коллег, меняется реализация функции, а не вёрстка страниц.
Бюджет и весКартинки — next/image с sizes, шрифты с нашего домена, декор тем — динамическим импортом. За то, чего 340 дней в году нет, платить весом нельзя.
SEO: метаданные, JSON-LD, canonical, редиректыБез 301 с разделов верхнего уровня поисковая выдача уходит в никуда.
Персональные данные: публичный профиль — фиксированный список полейСостав полей утверждает федерация, фильтрация на нашей стороне. Особенно для несовершеннолетних.

Как добавить

Новую событийную тему

  1. Запись в src/data/moods.ts: id, условие активации, приоритет, слои, строка микрокопии
  2. Файл src/styles/moods/<id>.css — только переопределения токенов
  3. Если нужен декор — компонент в components/mood/decor/ и ветка в MoodDecor
  4. Проверить приоритет против соседних тем: активной может быть только одна
  5. Примерить на /styleguide/#moods

Новый блок регионального сайта

  1. Компонент блока
  2. Запись в реестре блоков (src/data/blocks.ts)
  3. Фолбэк на случай, если регион блок не заполнил
  4. Тумблер «регион может редактировать» появится в панели автоматически

Новый источник данных

  1. Строка в docs/integrations/CONTRACT.md — кто владелец сущности
  2. Тип в src/types/
  3. Фикстура той же формы в src/data/fixtures/
  4. Функция в src/api/ — страница потребляет только её

Разделы и модули

РазделАдресСтатусНазначение
Главная/готовоВитрина портала: новости, календарь, документы, сборная, регионы
Представительства/regions/готовоКарта России и справочник 89 субъектов
Поиск/search/готовоСквозной поиск по спортсменам, новостям, соревнованиям и разделам
Как устроен проект/docs/готовоОписание проекта простым языком — для согласования с федерацией
Техническая документация/handbook/готовоДизайн-система, реестры и правила разработки
Дизайн-система/styleguide/готовоЖивая витрина токенов, атомов и движения
Панель управления/admin/в работеДемонстрация: сайты регионов, права на блоки, контент, интеграции
Новости/news/готовоЛента и карточка материала с рубриками
Соревнования/events/готовоКалендарь, страница турнира, вкладки; протоколы — за системой федерации
Сборная и картотека/team/готовоСоставы, картотека с фильтрами и карточки спортсменов
СпециалистампланируетсяДокументы, судьям, тренерам, антидопинг, тесты
Сайт представительствапланируетсяШаблон регионального сайта на поддомене

Версии

Что менялось в системе, а не в контенте. Полная история правок — в docs/CHANGELOG.md репозитория.

ДатаЧто изменилось
19.08.2026Каркас, дизайн-система и токены; статический экспорт
19.08.2026Слой данных на реальном контенте федерации, главная страница
19.08.2026Раздел «Как устроен проект» для согласования
19.08.2026Карта представительств, сквозной поиск, панель управления
19.08.2026Фотографии вместо заглушек, цветные логотипы партнёров, полоса спонсоров
19.08.2026Событийные темы: реестр, расчёт, декор, примерка
19.08.2026Техническая документация — эта страница