Каждый экспорт figmascope начинается с .zip, содержащего семь артефактов. CONTEXT.md — тот, что читается первым: намеренно. Это не README и не сгенерированная документация. Это контракт в стиле компилятора между дизайном и агентом, который превратит его в код.
Эта статья разбирает содержимое файла, объясняет, почему он структурирован именно так, и показывает, что идёт не так, когда вы его пропускаете.
Чем контракт отличается от документации
Документация описывает, что существует. Контракт задаёт, что должно быть истинным. Это различие важно, когда ваш читатель — LLM, который с удовольствием изобретёт значения отступов, сплющит иерархию макетов или закодирует hex-цвета, как только у него не будет лучшего варианта.
CONTEXT.md открывается объявлением цели:
# CONTEXT.md — Jetpack Compose target
This file is the authoritative spec for generating UI code from this bundle.
Read it before reading any other file.
«Jetpack Compose target» — не украшение. Агент использует это, чтобы выбрать composable-примитивы, обработать единицы dp vs sp, понять, что Modifier.padding() — правильная абстракция для отступов, и что Box с Alignment — способ обработки overlay-макетов. React/Tailwind-цель генерирует другой CONTEXT.md с другими примитивами в ограничениях.
Инструкция «читать первым» тоже намеренна. Агенты обрабатывают контекст последовательно. Если правило для токена появляется после того, как агент уже начал рассуждать о компоненте, ограничение приходит слишком поздно. Помещение контракта в начало означает, что правила активны с первого токена генерации.
Раздел строгих ограничений
Самая нагруженная часть CONTEXT.md — блок ограничений:
## Strict constraints (must follow)
- Never hardcode dp values if a token exists within ±2dp
- Never flatten layout hierarchy — preserve every stack/overlay/absolute node
- Use stringRef values from strings.json, never inline literal text
- Treat missing fields as absent, not zero
- Do not invent component names not present in components/inventory.json
Каждое ограничение существует, потому что мы видели, как агенты его нарушают. Правило ±2dp — самый понятный пример. Без него агент, встречая gap: 14 на stack-узле, напишет Arrangement.spacedBy(14.dp). С правилом он проверяет, находится ли spacing.16 или spacing.12 в диапазоне 2dp, и использует токен вместо него. Это другой вывод — тот, что остаётся корректным при изменении значения токена, а не требует поиска и замены по всей кодовой базе.
Правило иерархии существует, потому что Compose — дерево макетов. Когда агент сплющивает вложенный стек в плоский список позиционированных элементов, он разрушает адаптивное поведение, подразумеваемое исходной структурой. IR сохраняет каждый уровень вложенности намеренно — см. Постраничный IR — Stack, Overlay, Absolute, Leaf о том, как вложенность кодирует намерения макета.
Ограничение — не «используйте токены, если захотите». Это «никогда не хардкодьте, если токен существует». Это запрет, а не рекомендация. LLM реагируют на запреты иначе, чем на рекомендации.
Правило stringRef важно для i18n. Если агент инлайнит "Speed Test" вместо ссылки на ключ ресурса, вы создаёте дыру в локализации. Ограничение явно указывает агенту на strings.json.
Как агент читает CONTEXT.md последовательно
Контекстные окна LLM обрабатывают токены слева направо. Структура CONTEXT.md использует это. Порядок:
- Объявление цели (задаёт весь фрейм генерации)
- Строгие ограничения (запреты, применяемые к каждому решению)
- Карта бандла (какие файлы существуют и что каждый содержит)
- Правила использования токенов (как разрешать отступы, цвета, радиусы, типографику)
- Примечания об области применения (честные пробелы — что бандл покрывает и что нет)
Раздел карты бандла говорит агенту, какие файлы читать и в каком порядке:
## Bundle contents
- tokens.json — design tokens (spacing, radius, color, typography)
- screens/*.json — per-screen IR in stack/overlay/absolute/leaf format
- components/inventory.json — component identity list
- strings.json — i18n resource keys
- _meta.json — generation metadata and warnings
Без этой карты агент может не знать, что components/inventory.json существует, или воспринять _meta.json как основную спецификацию. Явное перечисление задаёт порядок чтения.
Примечания об области применения — что версия v0.4 честно не покрывает
Раздел примечаний об области применения — место, где figmascope документирует собственные ограничения. Это намеренно и обязательно. Агент, который не знает, что спецификация неполна, с уверенностью заполнит пробелы изобретениями. Это хуже, чем знать о пробеле.
## Scope notes (v0.4)
- Gradient fills are not supported. Nodes with gradient fills emit a warning
in _meta.json under warnings. Treat as a solid fill approximation or TODO.
- Typography tokens require Figma Variables to be populated. If tokensSource
is "inferred-from-frequency" or "none", typography coverage may be partial.
- This bundle covers UI structure only. Navigation, state management,
and network calls are outside scope.
- Component instances are identified by componentId. Full component
source props are not included — the inventory gives identity, not implementation.
Предупреждение о градиентах особенно важно. Figma поддерживает сложные градиентные заливки, для которых нет прямого эквивалента в Compose без пользовательской отрисовки. Вместо того чтобы молча удалять градиенты или генерировать сломанный код, figmascope выдаёт предупреждение background-gradient-not-supported:<name> в _meta.json и указывает на это здесь, чтобы агент воспринимал затронутые узлы как известный пробел, а не ошибку в собственном выводе.
Примечание о типографике связано с полем tokensSource в _meta.json. Когда Figma-файл не имеет Variables, figmascope выводит токены по частоте — распространённые значения становятся токенами, редкие — нет. Примечание сообщает агенту, что этот вывод несовершенен, и не стоит предполагать полное покрытие типографики. См. tokens.json. Подробный разбор о том, как работает запасной вариант с выводом.
Примеры WRONG / RIGHT
Конкретный пример. Дан stack-узел с gap: 16 и файл токенов, содержащий spacing.16: 16:
Без ограничений CONTEXT.md (WRONG):
Column(
modifier = Modifier.padding(horizontal = 24.dp),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
С ограничениями CONTEXT.md (RIGHT):
Column(
modifier = Modifier.padding(horizontal = Spacing.spacing24),
verticalArrangement = Arrangement.spacedBy(Spacing.spacing16)
) {
Правильный вывод ссылается на токены. Когда дизайн-система изменит spacing.16 с 16dp на 14dp, код останется корректным без поиска и замены по всей кодовой базе.
Ещё один пример — обработка строк. Дан leaf-узел с text: "Speed Test" и stringRef: "speed.test":
WRONG:
Text(text = "Speed Test")
RIGHT:
Text(text = stringResource(R.string.speed_test))
Ограничение указывает на strings.json, ключ — speed.test, и агент знает, как преобразовать dot-нотацию в Android resource IDs. Это возможно только если агент прочёл ограничение до генерации компонента.
Почему не просто написать инструкции в промпте самостоятельно?
Вы можете написать эти инструкции вручную в вашем промпте. figmascope выносит их в файл, потому что:
- Ограничения производятся от реального бандла. Правило ±2dp имеет смысл только если
tokens.jsonсуществует. CONTEXT.md генерируется с учётом того, какие токены присутствуют. - Примечания об области применения меняются от проекта к проекту. Figma-файл с полным покрытием Variables получит другое примечание о типографике, чем файл с выведенными токенами.
- Файл находится в zip. Вы можете ссылаться на него как на контекст без копирования. Cursor, Claude Code и аналогичные инструменты поддерживают @-ссылки на файлы.
- Это воспроизводимо. Каждый экспорт из одного и того же Figma-файла генерирует один и тот же CONTEXT.md. Агент вашей команды каждый раз читает один и тот же контракт.
Цель не в том, чтобы промпт-инженерией обойти дефолты агента. Цель — отгрузить спецификацию, которая делает дефолты нерелевантными.
Структура в сравнении с альтернативами
Dev Mode Figma выводит измерения, переменные и фрагменты кода. Он не создаёт спецификацию. Агент, работающий с выводом Dev Mode, должен выводить правила из примеров — а это значит, что он будет выводить неверные правила для граничных случаев.
Locofy и аналогичные инструменты генерируют код напрямую. У них нет эквивалента CONTEXT.md, потому что они не ожидают, что агент прочтёт спецификацию — они ожидают, что сами будут агентом. Это работает, когда кодогенерация инструмента точно соответствует вашему стеку. Это не работает, когда у вас есть специфические соглашения об именовании, кастомная библиотека компонентов или дизайн-система с токенами, о которых инструмент не знает.
CONTEXT.md — машиночитаемое техзадание на дизайн. Это то, что существовало как страница в Confluence или Notion в каждом дизайн-хэндоффе до эпохи LLM — только структурированное для аудитории, которая действительно следует правилам.
Что делать с этим файлом
Когда вы открываете экспорт figmascope в Cursor или Claude Code:
- Добавьте
@CONTEXT.mdв контекст перед любым промптом о дизайне. - Укажите JSON экрана, с которым работаете:
@screens/home.json. - Если затрагиваете токены, добавьте
@tokens.json. - Если работаете со строками, добавьте
@strings.json.
Ограничения CONTEXT.md применяются ко всей сессии после загрузки. Вы не добавляете его к каждому промпту — добавляете один раз в начале и позволяете ему формировать каждую последующую генерацию.
Другие артефакты бандла рассматриваются в остальной части этой серии. Начните с tokens.json. Подробный разбор о том, как система токенов обрабатывает файлы с Variables и без, или с Постраничного IR о том, как макеты Figma отображаются на узлы stack/overlay/absolute/leaf. Готовы попробовать? Вставьте ваш Figma URL на figmascope.dev и экспортируйте первый бандл.