# Figma Pixel Perfect

> figma-pixel-perfect

- Skill: `mobiss11/figma-pixel-perfect` (Agent Skill, multi-file: 4 files)
- Install (CLI): `npx skillmds@latest add mobiss11/figma-pixel-perfect`
- Raw SKILL.md: https://api.skillmd.com/api/skills/mobiss11/figma-pixel-perfect/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Design & Media
- Author: Mobiss11 (https://skillmd.com/u/mobiss11)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/mobiss11/figma-pixel-perfect

---


# figma-pixel-perfect

Протокол вёрстки по макету Figma без отсебятины. Главная идея: **ты не дизайнер, ты фотокопир с линейкой**. Любое значение (размер, цвет, шрифт, отступ, радиус, иконка) существует в макете — твоя работа его достать и потом **измерить**, что оно легло в рендер. Если достать не получилось — это проблема, о которой надо сказать, а не место для творчества.

## Железные правила

1. **Источник истины — данные из Figma MCP.** Не память о «типичных дизайнах», не «обычно 16px», не глазомер по скриншоту. Каждое значение в коде прослеживаемо до ответа MCP.
2. **Иконки и картинки не рисуются — скачиваются.** Ни одной SVG «по памяти», ни эмодзи вместо иконки, ни иконки из lucide/heroicons/fontawesome, если её нет в макете. Не выгрузился ассет → стоп и репорт.
3. **Размеры не округляются и не «гармонизируются».** В макете 13px — значит 13px. Нет подходящего токена/класса — используй точное значение (`p-[18px]`), а не ближайший красивый (`p-4`).
4. **Проверка — измерением, не глазами.** «Вроде похоже» ≠ pixel perfect. Сверяй числа: rect и computed styles из рендера против спеки.
5. **Непонятно / не достаётся / противоречиво → репорт, не догадка.** Одним блоком в конце работы.

## Шаг 0. Ссылка и выбор MCP-сервера

Распарси URL:
- `figma.com/design/<FILE_KEY>/<name>?node-id=123-456` → fileKey = `<FILE_KEY>`, nodeId = `123:456` (дефис в URL = двоеточие в API).
- Ссылка **без `node-id`** — весь файл. Не гадай и не передавай пустой nodeId: возьми `get_metadata` по странице, покажи список фреймов, спроси какой верстать.
- `figma.com/proto/...` — прототип; попроси ссылку на design-фрейм (Copy link to selection).

Серверов может быть несколько (разные проекты — разные аккаунты). Найди все инструменты вида `get_design_context` (ToolSearch, если отложенные). Если серверов больше одного — дешёвый пробный вызов (`get_metadata` на fileKey) на каждом; 403/404 → следующий. Ни у кого нет доступа → стоп и репорт с именами проверенных серверов. Вёрстка вслепую по скриншоту запрещена.

Подробная карта инструментов и различий серверов: [references/mcp-tools.md](references/mcp-tools.md).

## Шаг 1. Данные (до первой строчки кода)

1. **`get_design_context` на целевой ноде — первый и главный вызов.** Возвращает референс-код (React+Tailwind), скриншот и хинты. `get_metadata`/`get_screenshot` — НЕ замена ему: metadata — для ориентации и точной геометрии, screenshot — для финальной сверки.
2. **`get_metadata`** — дерево слоёв с точными x/y/width/height. Отсюда: размер вьюпорта для проверки и таблица ожидаемых габаритов ключевых элементов.
3. **`get_screenshot`** — сохрани в файл (`_figma_ref.png`) как визуальный эталон.
4. **`get_variable_defs`** — имена токенов (цвета/размеры).

Большая нода (целый экран): у корневого ответа детали урезаются — вызывай `get_design_context` дополнительно на ключевых дочерних нодах из metadata.

**Ошибки MCP:** прочитай сообщение прежде чем ретраить; таймаут → запроси ноду поменьше; и никогда не «ладно, сверстаю по скриншоту» — это гарантированные выдумки.

Заверши шаг дистилляцией: заполни `_figma_spec.md` ([шаблон](templates/figma-spec.md)) — размеры, токены, таблица ожиданий, ассеты, тексты. Дальше работаешь из него, к MCP не возвращаешься (см. «Экономия лимитов»).

## Шаг 2. Референс-код ≠ финальный код

Ответ `get_design_context` — референс, не готовый код. Адаптируй его под стек и конвенции проекта, применяя хинты по приоритету (ранний источник бьёт поздний):

1. **Code Connect** → используй замапленный компонент из кодовой базы как есть.
2. **Ссылки на доки компонентов** → следуй им.
3. **Аннотации дизайнера** → это прямые указания, выполняй.
4. **Дизайн-токены (CSS-переменные)** → мапь на токен-систему проекта.
5. **Сырые hex / абсолютные координаты** → переноси дословно.

Правило про токены: **вычисленный результат обязан совпасть с макетом, но выражай его через то, что уже есть в проекте.** Есть в проекте токен `--color-primary: #6C5CE7` и в макете этот же цвет — используй токен. Нет ничего подходящего — точное литеральное значение. Запрещено «округлять к токену», который даёт другое число: это дрейф от макета.

Перед вёрсткой проверь проект: существующие компоненты (кнопки, инпуты), утилиты, шрифты. Повторное использование > генерация дубля.

## Шаг 3. Ассеты

1. Из metadata выпиши слои-иконки/иллюстрации/фото (`VECTOR`, `IMAGE`, компоненты `icon/...`).
2. Скачай их (`download_assets` / ссылки из design context). SVG для иконок, PNG/WebP для растра.
3. Посчитай: N ассетов скачано → в рендере должно быть ровно N соответствующих `<svg>`/`<img>`. Эта проверка входит в аудит (шаг 5) и ловит и выдуманные, и задублированные иконки.

## Шаг 4. Вёрстка

- Значения из design context — дословно: hex полностью, line-height/letter-spacing/font-weight числами.
- Шрифты — те же семейства, что в макете. Недоступен → системный с похожей метрикой + запись в репорт (молчаливая замена запрещена).
- Auto-layout → flex/grid с теми же gap/padding/alignment.
- Фиксированный фрейм (375×812 и т.п.) → верстай на этом вьюпорте. Про адаптив вне макета не фантазируй — спроси про брейкпоинты, если просят адаптив с одним макетом.
- Ничего сверх макета: ни ховеров, ни анимаций, ни состояний, которых там нет.

## Шаг 5. Самопроверка: сначала цифры, потом картинка

### 5а. Численный аудит (главная проверка)

«Похоже/не похоже» — не аргумент. Аргумент — дельта в пикселях.

1. Таблица ожиданий уже готова в `_figma_spec.md` (ключевые элементы → width/height/font-size/line-height/color/gap/padding).
2. Отрендери на вьюпорте ровно в размер фрейма и измерь DOM: `getBoundingClientRect()` + `getComputedStyle()` через browser-инструменты / Playwright. Готовый снипет: [scripts/measure_dom.js](scripts/measure_dom.js).
3. Сравни числа. Расхождение формулируется конкретно: «спека: font-size 24px, рендер: 28px» — и чинится по данным, не подгонкой.
4. Проверь количества: `document.querySelectorAll('svg, img').length` против числа ассетов из шага 3; тексты — дословно из макета (не перефразированы).

### 5б. Визуальная сверка (вторичная)

1. Скриншот рендера → `python3 scripts/pixel_diff.py _figma_ref.png _render.png --out _diff.png` — даст % расхождения и heatmap с локализацией по зонам.
2. Heatmap нужен, чтобы найти **структурные** промахи: пропавший элемент, съехавший блок, не тот фон. Нашёл зону → выясни правильное значение в данных Figma → почини → перемерь (5а).
3. **Антиалиасинг и рендер шрифтов дают фоновый шум 1–3% — это норма, не расхождение.** Железное правило: если значение совпадает со спекой по цифрам, его НЕ трогают ради снижения diff. Иначе цикл «поменял 14→15px, сломал line-height, чиню три итерации проблему, которой не было».

### Лимит итераций

Максимум 3 круга правок по визуальному diff. Не сходится — причина не в пикселях: либо компонент надо резать на части и сверять по отдельности, либо расхождение объективно (шрифт, рендер) — тогда оно объясняется в репорте, а не замазывается.

## Экономия лимитов (токенов и вызовов Figma MCP)

Design context экрана — тысячи токенов, каждый просмотр картинки — ещё сотни, у Figma MCP есть rate-лимиты. Правила экономии — они же правила аккуратности:

1. **Один заход за данными.** По metadata спланируй, какие ноды нужны, и вызови `get_design_context` по одному разу на каждую. Полученное не перезапрашивается.
2. **Сразу дистиллируй в спек-файл.** После шага 1 выпиши все нужные значения в `_figma_spec.md` (шаблон: [templates/figma-spec.md](templates/figma-spec.md)) и дальше работай только с ним. Сырые ответы MCP второй раз не читаются.
3. **Проверяй текстом, не картинками.** Числа из measure_dom.js и вывод pixel_diff.py — копейки. Эталонный скриншот смотри один раз при получении; heatmap открывай только когда diff выше порога. «Сравню глазами обе картинки ещё разок» на каждой итерации — запрещено.
4. **Правки пачкой.** Один аудит → полный список дельт → одна серия правок → одно повторное измерение. Не чини по одной дельте с перемером после каждой.
5. **Ассеты — одним batch-вызовом**, не по одному.

## Когда остановиться и сказать, а не придумать

Копи проблемы по ходу, выдай блоком «⚠️ Проблемы по макету» в конце:

- Ассет не выгружается / шрифт недоступен
- Ссылка без node-id (какой фрейм?)
- Ни один MCP-сервер не имеет доступа к файлу
- В макете одно состояние (нет hover/empty/error) — состояния не выдумываются
- Данные противоречат друг другу (context ≠ скриншот — макет правили?) → сними скриншот заново, скажи
- Текст-заглушка в макете (lorem, «Название») — что подставлять?

Формат финального ответа: что сверстано → результаты аудита (таблица дельт: ожидание/факт по ключевым элементам, % визуального diff) → «⚠️ Проблемы по макету». Пустой репорт при заметных расхождениях — красный флаг: скорее всего, что-то придумано вместо того, чтобы спросить.

## Типичные ошибки (не делай так)

| Анти-паттерн | Почему провал |
|---|---|
| Нарисовал SVG «по смыслу» / взял из icon-пака | Пользователь получает не свой дизайн. Только ассеты из макета. |
| Цвет пипеткой со скриншота | Скриншот сжат, цвет искажён. Цвет — из design context / variables. |
| Округлил 13px → 12px, `p-[18px]` → `p-4` | Pixel perfect умер. Точное значение важнее красивого класса. |
| Молча заменил шрифт | Метрика плывёт. Замена только с пометкой в репорте. |
| Сверстал по скриншоту, не вызвав design context | Все размеры — догадки. Скриншот — эталон проверки, не источник значений. |
| Гоняет pixel-diff, меняя верные значения | Шум антиалиасинга не чинится вёрсткой. Совпадает со спекой — не трогай. |
| Сдал без численного аудита | «Вроде похоже» — так и появляются 28px вместо 24px. |
| Добавил ховеры/анимации от себя | Отсебятина. Только по просьбе пользователя. |

