Communitygithub.com

biolineX/figma-landing

Вёрстка лендинга из Figma в чистые HTML/CSS/JS через Figma MCP, блок за блоком с проверкой пользователем. Use when the user gives a Figma link (whole file, desktop or mobile frame) and asks to build / сверстать a landing page in plain HTML, CSS and JS.

What is figma-landing?

figma-landing is a Codex agent skill that вёрстка лендинга из Figma в чистые HTML/CSS/JS через Figma MCP, блок за блоком с проверкой пользователем. Use when the user gives a Figma link (whole file, desktop or mobile frame) and asks to build / сверстать a landing page in plain HTML, CSS and JS.

Works with~Claude Code✓Codex CLI~Cursor
npx skills add https://github.com/biolineX/figma-landing/tree/HEAD

Ask in your favorite AI

Open a new chat with this agent skill pre-loaded.

Documentation

Figma → лендинг на HTML/CSS/JS

Скилл переводит макет лендинга из Figma в статичную вёрстку на HTML, CSS и JS. Работа идёт по одному блоку: после каждого блока агент останавливается и ждёт подтверждения пользователя.

Правила самой вёрстки (структура, БЭМ, единицы, картинки, hover и т.д.) лежат в templates/AGENTS.md этого скилла. На шаге 3 этот файл копируется в корень проекта и дальше действует всегда.

Требования

  • Подключён Figma MCP (get_metadata, get_design_context, get_screenshot, при наличии — get_variable_defs). Если его нет — сказать пользователю и остановиться.
  • Пользователь дал ссылку вида https://www.figma.com/design/:fileKey/:fileName?node-id=1-2.
  • Для сервера, скриншотов и WebP нужен Node.js. Команды npx при первом запуске качают пакеты из сети — Codex может запросить разрешение, это нормально.

Порядок работы

Шаги выполнять по порядку, не пропуская.

Шаг 1. Разобрать ссылку

  • fileKey — часть после /design/. Если в ссылке есть /branch/:branchKey/, использовать branchKey.
  • nodeId — значение node-id, дефис заменить на двоеточие (1-2 → 1:2).
  • Ссылка может вести на весь документ, на страницу, на десктоп-фрейм или на мобильный фрейм. Тип определить на шаге 2.

Шаг 2. Карта макета

  1. Вызвать get_metadata для узла из ссылки (для всего документа — без node-id или с корневой страницей).
  2. Найти фреймы-версии лендинга: десктоп, мобилка, иногда планшет. Ширины определить из макета, не подставлять стандартные. Также найти отдельно лежащие фреймы модальных окон (попапов) и открытого мобильного меню, если они есть на странице.
  3. Внутри каждого фрейма выделить секции верхнего уровня (шапка, hero, преимущества, отзывы, футер и т.д.).
  4. Сопоставить секции между версиями: «десктоп-секция ↔ мобильная секция» (по названию слоя, порядку и содержимому).
  5. Показать пользователю карту и дождаться подтверждения:
Ширины: десктоп 1440, мобилка 375
1. header      — 12:30 ↔ 40:2
2. hero        — 12:45 ↔ 40:18
3. advantages  — 13:10 ↔ 41:5
...
Модальные окна / меню:
- mobile-menu  — 45:12
- popup-order  — 46:01

Если мобильной версии нет — сказать об этом и спросить, как действовать.

Шаг 3. Каркас проекта и базовый UI

  1. Если в корне проекта нет AGENTS.md — скопировать templates/AGENTS.md из папки скилла. Заполнить в нём раздел «Этот лендинг» (ширины, контейнер, шрифты) по данным шага 2. Брейкпоинты оставить по умолчанию; менять, только если вёрстка этого макета ломается на других ширинах, — и тогда записать новые.
  2. Создать структуру: index.html, style.css, script.js, assets/icons/.
  3. index.html: <!doctype html>, lang="ru", charset, viewport, <title> и <meta name="description"> по смыслу лендинга. Фавикон не добавлять. script.js подключать с defer.
  4. Шрифты: взять из get_design_context/get_variable_defs, подключить через Google Fonts только нужные начертания, display=swap. Если шрифта нет в Google Fonts — попросить у пользователя файлы, подключить через @font-face из assets/fonts/.
  5. style.css: сброс стилей (см. AGENTS.md), затем :root с переменными цветов, шрифтов, отступов, ширины контейнера. Значения брать из get_variable_defs, если в макете есть переменные; иначе — собрать из макета и округлить.
  6. Базовые компоненты: выделить сквозные элементы макета (кнопки, заголовки секций, поля ввода) в переиспользуемые классы (.btn, .section-title, .input, .container). Если в макете нет UI-кита с состояниями (hover, focus, active), один раз спросить у пользователя правила наведения для типовых кнопок и ссылок на весь проект. Ответ записать в строку «UI-состояния» раздела «Этот лендинг» в AGENTS.md.
  7. Инструменты (один раз):
    • запустить в фоне локальный сервер из корня проекта: npx -y serve -l 3000 (запасной вариант — python3 -m http.server 3000). Все скриншоты снимать с http://localhost:3000, не с file://;
    • проверить, чем снимать скриншоты: Playwright MCP, если подключён; иначе — скрипт scripts/shot.cjs (см. «Самопроверка»);
    • проверить конвертер картинок (см. «Картинки») и запомнить результат.
  8. Сообщить пользователю, что каркас готов, и перейти к первому блоку.

Шаг 4. Блоки по одному

Для каждой секции из карты, строго по порядку сверху вниз (включая секции с формами):

  1. Данные. get_design_context и get_screenshot для десктоп-секции и для её мобильной пары.
    • Если ответ обрезан или слишком большой — get_metadata по секции и забирать дочерние узлы по отдельности.
    • Код из ответа (обычно React + Tailwind) — только справка о размерах, цветах и структуре. Не копировать его стиль.
  2. Картинки. Скачать и обработать ассеты блока (см. «Картинки»).
  3. Вёрстка. HTML блока в index.html, стили в style.css отдельным разделом с комментарием /* ===== hero ===== */, JS (если нужен) в script.js. Использовать базовые классы из шага 3.6, не дублируя код кнопок и заголовков. Сначала десктоп, затем адаптив до мобилки через clamp() и медиазапросы.
    • Для header на мобильной ширине сразу сверстать бургер-меню (по фрейму из карты или уточнив вид у пользователя).
    • Если в блоке есть форма — сверстать её с базовыми браузерными атрибутами валидации (required, type="email", type="tel", pattern), но без JS-логики отправки.
  4. Самопроверка. Снять только текущую секцию на ширине десктопа, мобилки и промежуточных (1024, 768). Сравнить со скриншотами Figma: отступы, размеры, шрифты, цвета, переносы. Исправить найденное и переснять.
    • Через Playwright MCP — скриншот элемента секции на каждой ширине.
    • Без MCP — скрипт из папки скилла:
      # один раз
      mkdir -p .screens && cp <папка-скилла>/scripts/shot.cjs .screens/
      npm i playwright --prefix .screens && npx -y playwright install chromium
      # после каждого блока
      node .screens/shot.cjs http://localhost:3000 .hero 1440,1024,768,375
      
      Скрипт сохраняет .screens/<секция>-<ширина>.png и пишет ⚠ горизонтальный скролл, если страница вылезает за ширину экрана. Любое такое предупреждение — исправить причину (не прятать через overflow: hidden на body).
    • Снимки секций удалять после подтверждения блока; сам скрипт и node_modules в .screens/ — на шаге 6.
  5. Отчёт и стоп. Коротко написать пользователю: что сделано, где были отклонения от макета и почему, что нужно уточнить по уникальным интерактивным элементам блока (нестандартный hover карточек, параметры слайдера). Ждать подтверждения. Правки пользователя внести в этот же блок, затем снова ждать.
  6. Только после «ок» — следующий блок.

Шаг 5. Модальные окна и логика форм

После вёрстки всех основных секций:

  1. Сверстать скрытые модальные окна (попапы), если они были найдены на шаге 2, и подключить триггеры открытия/закрытия (кнопки, Esc, клик по оверлею). Поведение — по разделу «JavaScript» в AGENTS.md.
  2. Каждое окно — как отдельный блок: самопроверка скриншотами в открытом состоянии, отчёт и ожидание подтверждения.
  3. Проверить работу всех форм на странице. Отправку данных (fetch/AJAX) никуда не делать, пока пользователь сам не попросит и не даст адрес (endpoint) или ТЗ.

Шаг 6. Финал

После подтверждения последнего этапа: проверить всю страницу целиком на всех ширинах, удалить временные файлы и папки (assets/_raw/, .screens/ целиком), остановить фоновый локальный сервер, удалить неиспользуемые стили и картинки. Написать короткий итог.

Картинки

  1. Ассеты блока брать из ответа Figma MCP (ссылки на изображения в get_design_context). Если отдан localhost-адрес — скачивать по нему как есть. Не использовать заглушки и сторонние наборы иконок.
  2. Скачивать во временную assets/_raw/<блок>/, растровые картинки — в 2 раза крупнее (2x), чем они стоят в макете.
  3. Адаптивная графика: если в мобильной версии блока используется кадрированная (другие пропорции) или другая по смыслу картинка — скачивать обе версии (hero-bg-desktop.webp и hero-bg-mobile.webp) и подключать через <picture>.
  4. Сортировка:
    • мелкие иконки внутри интерактивных элементов (кнопки, ссылки), которые должны менять цвет (fill/stroke) при наведении → инлайн <svg> в HTML с fill="currentColor" (или через CSS mask-image);
    • статичные иконки, логотипы, простая графика → SVG в assets/icons/ через <img> (или в папку блока, если это крупная графика). Если иконка пришла растром — сказать пользователю;
    • фото и сложные изображения → WebP в assets/<блок>/.
  5. Конвертация в WebP, качество 80. Порядок попыток:
    1. npx -y sharp-cli -i in.png -o out.webp -f webp -q 80 (нужен Node.js);
    2. cwebp -q 80 in.png -o out.webp;
    3. ничего нет — оставить исходный формат и один раз сказать пользователю, что поставить (Node.js или cwebp), не останавливая работу.
  6. Если WebP получился тяжелее оригинала — оставить оригинал.
  7. Имена файлов: латиница, нижний регистр, через дефис, по смыслу (hero-photo.webp, arrow-right.svg).
  8. После подтверждения блока удалить assets/_raw/<блок>/.

Hover, анимации, слайдеры

  • Hover: для базовых кнопок и ссылок — правила из строки «UI-состояния» в AGENTS.md. Если в блоке есть уникальные интерактивные карточки/элементы без состояний в макете — не придумывать, а спросить у пользователя в отчёте по блоку.
  • Анимации при прокрутке и кастомные анимации — только если пользователь сам попросил. Сначала уточнить, что именно должно происходить. Простое (появление при прокрутке) — IntersectionObserver; тяжёлое (привязка к колесу, «залипающие» секции, параллакс) — GSAP через CDN, только после согласия пользователя. Всегда учитывать prefers-reduced-motion.
  • Слайдер: простой (стрелки, точки, свайп) — свой на CSS scroll-snap + немного JS. Сложный (бесконечный, автоплей, эффекты, связанные слайдеры) — Swiper через CDN.

Частые проблемы

  • Ответ Figma обрезан → get_metadata по секции, затем get_design_context по дочерним узлам.
  • Не видна мобильная пара секции или фрейм мобильного меню → спросить пользователя, а не придумывать.
  • Шрифт не совпадает по ширине с макетом → проверить начертание и letter-spacing, не подгонять размер шрифта.
  • Картинки не скачиваются → проверить, что Figma MCP запущен; ссылки использовать без изменений.
  • На скриншоте слетели шрифты или иконки → проверить, что сервер на localhost:3000 запущен и снимок идёт с него, а не с file://.
  • Скрипт пишет «горизонтальный скролл» → найти элемент шире экрана (фиксированная ширина, большой gap, декор за краем) и исправить; для декоративных элементов за краем — overflow-x: clip на их секции.
  • Отклонение от макета ради доступности или технических ограничений → допустимо, но упомянуть в отчёте по блоку.

Related Skills