Программа Матемаркетинг 2026 — статическая копия preview
Ситуация
Страница программы конференции — это Vue SPA: данные живут в API, вёрстка в бандле, и «сделать так же» обычно означает «сделать похоже»
Задача
Разобрать чужой интерфейс до измеримых величин и собрать работающую копию без сборки и бэкенда
Действия
Вытащил программу из публичного API, снял метрики сетки с отрендеренного DOM, собрал HTML/CSS/JS и прогнал четыре независимых проверки: ревью, security, браузерные тесты, визуальный аудит
Результат
Сетка совпадает с оригиналом до пикселя: колонка времени 99 px, зал 420 px, карточка 391 px, строка 550 px, верх сетки y = 414; тесты ловят расхождение данных и вёрстки
Стек
HTMLCSSJavaScriptPython
Исходники Смотреть на GitHub → Обновлено: 3 нояб. 2026 г.
Содержание
  1. Ситуация
  2. Задача
  3. Действия
  4. Результат
  5. Ограничения
  6. Документация

Программа Матемаркетинг 2026 — статическая копия

▶ Живая копия — открывается на любом хостинге, без сборки и установки. Код: NikitaBoyarkin/mm-program-page.

Ситуация

Страница программы конференции — типичный SPA: в HTML приходит пустой <div id="app">, программа подтягивается из API и рисуется в браузере. Скопировать такую страницу «сохранением вёрстки» нельзя: в сохранённом файле не будет ни докладов, ни сетки. Обычный ответ на такую задачу — «сделал похоже», и проверить это утверждение нечем.

Задача

Разобрать интерфейс до измеримых величин — размеров колонок, отступов, высоты строки, кеглей — и собрать копию, которая работает без сборки, без бэкенда и без npm. И, главное, получить проверяемое утверждение вместо «похоже»: замеры, тесты и зафиксированный список отклонений.

Действия

  1. Разведка. Определил, что страница — Vue-приложение, а программа приходит из GET /api/event-program/event/6/: 335 КБ JSON, 3 дня, 91 доклад, 11 треков, 9 залов. Дизайн-токены (границы #E5E7EB, фон сетки #F9FAFB, бренд #5C34F6) вытащил из конфигурации визуала и боевого CSS, а не подбирал на глаз.
  2. Данные. tools/fetch_program.py качает payload, чистит HTML из описаний, склоняет пустой short_description к первому абзацу и собирает window.MM_PROGRAM. Режимы --fetch, --check (ловит дрейф между слепком и API) и --dry-run.
  3. Вёрстка. Скелет index.html + курированный CSS (выгрузка боевого CSS со снятыми data-v-* и выброшенными Vuetify-внутренностями) + app.js без зависимостей: сетка «время × залы», multi-slot карточки, табы дней, 11 чипов треков, избранное в localStorage, модалка с фокус-трапом, экспорт дня в .ics.
  4. Проверка. Четыре независимых прохода: ревью кода (15 находок, 2 высоких), security-аудит (0 блокирующих), браузерные тесты на headless Chrome и визуальный аудит с замерами в пикселях. По находкам добавил валидацию URL картинок, фолбэки битых баннеров и аватаров, фолдинг строк в .ics, aria для табов и CSP.

Результат

Сетка воспроизведена по замерам, а не по ощущению:

Метрика (1440 px) Оригинал Копия
Колонка времени 99 px 99–100 px
Колонка зала 420 px 420 px
Карточка и радиус 391 px, 16 391 px, 16
Баннер 4:3, 291 px 4:3, 291 px
Строка сетки 550 px 550 px
Верх сетки y = 414 y = 414
Заголовок (ink-бокс) 638×22 650×22
Высота документа 6605 px 6589 px

Проверки: tests/test_data.py — 9 тестов, 2370 проверок инвариантов данных; tests/test_page.py — 7 тестов на реальный рендер (счётчики по дням, целостность grid-area, скриншоты на 1440 и 390 px, деградация без данных). Оба набора проверены мутациями: сломанный счётчик, сдвинутая сетка и пустой заголовок валят соответствующий тест.

Ограничения

  • Нет бэкенда: авторизации, личного кабинета, серверного избранного, чата и плеера в копии не будет.
  • Картинки и коммерческий заголовочный шрифт не перепубликуются — грузятся с CDN первоисточника. Из-за CORS оригинальный Loos Wide не загружается, поэтому заголовок рисует свободный Unbounded, подогнанный по ink-боксу (650×22 против 638×22).
  • Счётчик в шапке показывает число докладов дня, а не «людей онлайн»: присутствие в статике выдумывать нельзя.
  • Данные — слепок на дату сборки. python3 tools/fetch_program.py --check покажет, если программа на первоисточнике изменилась.

Документация

  • Код и тесты — index.html, assets/app.js, tests/, tools/fetch_program.py
  • CONTRACT.md — схема данных, DOM-контракт и список поведения
  • docs/DECISIONS.md — все отклонения от оригинала с причинами
  • Живая копия — открывается без установки

Нужен такой же разбор на ваших данных?

Расскажите задачу — вернусь с планом: какие данные нужны, что проверяем и за какой срок. Отвечаю в течение дня.

Обсудить задачу →