Что было до нас
Бизнес-клуб TERRA ведёт бесплатный курс «Команда образования» для действующих собственников и руководителей. 12 модулей за два месяца, наставники-практики, очно в Санкт-Петербурге и онлайн. Сайт должен объяснять программу и приводить людей в Telegram-канал.
К нам пришли с черновиком, который собрал неопытный вайб-кодер. Это был один HTML-файл примерно на 140 мегабайт. Все фотографии и видео зашили прямо в код в base64. Файл почти не открывался ни в редакторе, ни в браузере. Мобильное меню не работало. Плееры были нарисованные, часть видео отдавала 404.
Голова документа была пустой. Ни описания, ни Open Graph, ни микроразметки, ни фавиконки. Поисковик видел страницу без имени и без смысла. В палитре жили 36 разных цветов, включая розовый и серый, которых нет в гайдлайне клуба.
Отдельное ограничение шло от юридической формы. Курс некоммерческий, персональные данные организация не собирает. Значит формы заявки на сайте быть не может в принципе.
Разобрали 140 мегабайт скриптом
Вручную такой файл не разобрать. Мы написали скрипт. Он распарсил base64 и вытащил картинки в отдельные файлы. Отдельно достал JSON с данными, который лежал внутри кода: 21 профиль куратора с ролями и достижениями, 16 историй выпускников из точки А в точку Б, отзывы, реальные фотографии людей.
Все изображения перевели в WebP и подогнали под размер показа. Голос основателя вытащили из вертикального видео ВК через ffmpeg и yt-dlp: 81 секунда подкаста на первом экране.
Итог по весу: 224 КБ HTML вместо примерно 140 мегабайт. Сайт целиком, вместе с 68 фотографиями людей, аудио и блогом, весит 2,6 МБ. Приём с распаковкой исходника переиспользуется на любом тяжёлом наследии.
У некоммерческого проекта нет права собирать персональные данные. Форм на сайте нет по решению клиента. Единственное действие посетителя: переход в Telegram. Мы развесили около 30 именованных целей Яндекс.Метрики на каждую кнопку и каждую ссылку. Теперь видно, из какой именно точки человек ушёл в канал: с первого экрана, из шапки, из расписания, из кейсов, из блока наставников, с липкой кнопки или из футера. Это заменяет воронку заявок и показывает, какая секция реально работает.
Собрали страницу заново, интерактив написали руками
Лендинг пересобрали с нуля по брендбуку курса. 10 секций со сквозной нумерацией, чередование тёмных и светлых блоков, тёмно-бирюзовая палитра, Montserrat. Фирменный мотив «лента из точек» из гайдлайна усилили до полноценного интерактива.
Внешних JS-библиотек в проекте ноль. Весь интерактив написан на Canvas и штатных браузерных API.
Параллельно собрали контентный слой: 5 SEO-статей по 1000 до 1200 слов, статья про историю курса с фотоаватарками команды, хаб блога, страница «Миссия и принципы». Сверху лёг SEO и GEO пакет: canonical, Open Graph, JSON-LD (WebSite, EducationalOrganization, NGO, Course с датами потока, FAQPage на 11 вопросов), sitemap, llms.txt и robots.txt, где явно разрешены 14 ИИ-краулеров: GPTBot, ClaudeBot, PerplexityBot, Google-Extended, YandexBot и другие.
- Сфера из 250 точек на первом экране. Каждая точка это реальный ученик или куратор, наведение раскрывает карточку.
- Морф точек «хаос в систему» в блоке про боль руководителя.
- Волна из точек под финальной кнопкой записи.
- Орбита кураторов, клик-таймлайн на 12 модулей, слайдер отзывов, модалки кейсов и профилей.
- Две пасхалки для тех, кто до них доберётся.
Скорость при трёх работающих холстах
Анимация обычно съедает баллы производительности. Здесь её оставили и всё равно вытащили скорость в зелёную зону.
PageSpeed 99 на десктопе и 84 на мобильном. LCP 0,8 секунды. CLS 0,007 при постоянно вращающейся сфере.
Механика простая. Первый кадр сферы рисуется сразу как статичное созвездие, и именно он становится главным элементом отрисовки. Вращение включается флагом через 0,8 секунды после полной загрузки. За пределами экрана холсты останавливаются и не крутятся вхолостую. Размеры холста и слайдера отзывов считаются один раз и кешируются, пересчёт идёт только при изменении окна.
Грабли
Кейс без единой сложности читается как реклама. Вот что реально ломалось по дороге.
- Мобильный PageSpeed отдавал ошибку NO_LCP. Lighthouse не мог поймать момент отрисовки: сфера крутилась непрерывно, страница никогда не затихала. Помог отложенный старт вращения. Балл поднялся с ошибки до 84.
- CLS был 0,174. Montserrat грузится асинхронно, и при подмене шрифта вся страница дёргалась. Сделали свой @font-face-фолбэк на базе локального Arial с подогнанными метриками: size-adjust 112,71%, ascent-override 85,79%, descent-override 22,25%. Сдвиг упал до 0,007.
- Глобальное правило overflow-x:clip убрало тёмную полосу справа на мобильном и заодно сломало прилипающую колонку расписания на десктопе. Ограничили медиазапросом до 880 px.
- Четыре аватарки при обрезке в квадрат кадрировались по центру картинки и отрезали лица. Перекропили по лицу скриптом.
- Переменную в JavaScript нельзя называть top. Это window.top, страница молча ломается. Записали в правила проекта.
- Пуш в репозиторий не равен выкатке. Боевой домен отдаёт сервер на стороне клиента. После пуша сайт 40 минут не менялся, и сначала казалось, что мы что-то сломали. Автозабора на репозитории просто не было. Позже на стороне клиента подняли автовыкатку, теперь правка доходит до сайта примерно за полминуты.
- Лендинг лежал в нашей общей рабочей папке, и параллельно его правил другой процесс. Массовая автозамена по всем HTML-файлам переписала биографию спикера курса. Откатили через git. После этого файлы в коммит добавляем поимённо и проверяем индекс глазами.
- Мелочи, которые видит только заказчик. Надпись «С 0 ₽» читалась как «СОР». Точка-разделитель повисала одна на новой строке при переносе. Такие вещи автотесты не ловят никогда.
Что осталось у клиента после сдачи
Код запушен в репозиторий заказчика. Сайт переехал на боевой домен ko.business, noindex снят, страница открыта для индексации и верифицирована в Яндекс.Вебмастере. Сервером распоряжается клиент, доступа туда у нас нет и мы туда не лезем.
Сайт после сдачи ведёт сотрудница клуба, она не программист. Вместо инструкции в Word мы положили в корень репозитория файл CLAUDE.md, который её Claude Code читает автоматически. Внутри 5 разрешённых задач с точными рецептами: добавить кейс, куратора, звезду на сферу, отзыв, статью. Там же команда самопроверки кода перед пушем и жёсткий раздел про то, что трогать нельзя. Всё за пределами этого списка идёт к разработчику.
Хронология без прикрас. Старт 24 июня, приёмка 3 июля: 9 дней. Дальше переезд на домен, пачка примерно из 38 правок по мобильной и десктопной версиям, перф-фикс мобильного балла и передача поддержки. Всего 243 коммита за 12 рабочих дней с правками.
Частые вопросы
Сколько времени занимает разработка лендинга для курса?
Лендинг курса «Команда образования» сделали за 9 дней: старт 24 июня, приёмка 3 июля. В эти дни вошли разбор исходника, сборка страницы с нуля, 5 SEO-статей и блог. После приёмки был переезд на домен ko.business и примерно 38 правок по мобильной и десктопной версиям. Всего 243 коммита за 12 рабочих дней.
Сайт весит слишком много и долго открывается: что делать?
Такой файл руками не разобрать, нужен скрипт. У TERRA исходник был одним HTML на 140 МБ: фотографии и видео зашили прямо в код в base64. Мы распарсили base64, вытащили изображения в отдельные файлы, перевели в WebP и подогнали под размер показа. Страница стала весить 224 КБ, весь сайт с 68 фотографиями, аудио и блогом занимает 2,6 МБ.
Можно ли обновлять сайт самому, без программиста?
Да, если заложить это в проект заранее. Сайт после сдачи ведёт сотрудница клуба, она не программист. В корень репозитория мы положили файл CLAUDE.md, который её Claude Code читает автоматически: 5 разрешённых задач с точными рецептами, команда самопроверки кода перед пушем и раздел про то, что трогать нельзя. Всё за пределами этого списка идёт к разработчику.
Как считать конверсию сайта, если на нём нет формы заявки?
Курс некоммерческий, персональные данные организация не собирает, поэтому форм на сайте нет по решению клиента. Единственное действие посетителя: переход в Telegram. Мы развесили около 30 именованных целей Яндекс.Метрики на каждую кнопку и каждую ссылку. Теперь видно, из какой точки человек ушёл в канал: с первого экрана, из шапки, из расписания, из кейсов, из блока наставников, с липкой кнопки или из футера.
Можно ли сделать сайт с анимацией и не потерять скорость загрузки?
Можно. На лендинге TERRA работают три холста Canvas, включая сферу из 250 точек на первом экране, внешних JS-библиотек в проекте ноль. PageSpeed при этом 99 на десктопе и 84 на мобильном, LCP 0,8 секунды, CLS 0,007. Помогли три приёма: первый кадр сферы рисуется сразу статичным созвездием, вращение включается через 0,8 секунды после полной загрузки, за пределами экрана холсты останавливаются.
