Весь старый сайт был выдержан в CRT-стиле Pip-Boy — зелёное свечение, моноширинный шрифт, эффект строчной развёртки старого монитора. Эстетика Fallout, которая мне действительно нравится и которую я не хотел терять. Проблема вскрылась не в дизайне, а в контенте: короткие технические заметки в этом оформлении читались тяжело и неохотно — оказалось, что радиация идёт не только от пустоши, но и от попытки читать абзац на пять строк зелёным моноширинным текстом. Сам формат больше подходил для атмосферного "досье", чем для статьи на 1500-2000 слов, которую должен захотеть дочитать человек, а не только поисковый краулер.
Я хотел изменить не только внешний вид, но и саму подачу материала — сделать блог понятнее для тех, кто интересуется AI-инструментами и вайб-кодингом, а не писать сухие технические заметки, которые удобны роботам и неинтересны живым читателям. Дизайн под эту задачу я спроектировал сам, в Claude Design — расширении Claude для создания дизайн-макетов и прототипов, сохранил из него хендофф-пакет и отдал Claude Code на разработку — с одним жёстким условием: Pip-Boy стиль не выбрасывать, а оставить как отдельную личную страницу.
Ниже — рецепт, по которому Claude Code распаковал хендофф-пакет, вытащил design-токены прямо из HTML-прототипов и пересобрал два визуальных стиля (тёплый минимализм для блога и CRT-терминал в стиле Pip-Boy для личной страницы) поверх существующей кодовой базы на Next.js, без переноса одного макета один в один и без потери старого дизайна.
Что лежит внутри такого хендофф-пакета
Хендофф-пакет из Claude Design, в отличие от классического Figma Dev Mode, не требует отдельного плагина-экспортёра — инструмент сам формирует архив с прототипами и токенами по запросу. Это не то же самое, что нативный Figma MCP или Figma Agent, которые держат живое соединение с файлом дизайна прямо во время генерации кода — здесь макет спроектирован заранее в Claude Design и передаётся Claude Code одним архивом, без постоянной связи между двумя инструментами. Более простой, но менее автоматизированный путь: подходит, когда дизайн уже готов и не будет меняться параллельно с кодом.
Пакет — ZIP с .dc.html файлами (design-code превью, отдельный самодостаточный HTML на каждый экран или компонент) и README.md с описанием системы. Внутри README — весь дизайн-контракт: шрифты, цвета в oklch, радиусы, состояния hover, breakpoints.
Ключевая строка из README пакета, которая определила весь подход к реализации:
The
.dc.htmlfiles are design references, not production code — self-contained HTML prototypes. Do not copy this HTML into the Next.js app. Recreate the same look and interactions inside the existing codebase, reusing its data loading and component structure.
Это не техническая деталь — это инструкция, которая экономит часы. Скопировать HTML в JSX и получить нерабочий блог с задублированной логикой — простой путь. Прочитать токены и перенести их в существующие компоненты — единственный путь, который не ломает SEO, MDX-рендер и уже написанную бизнес-логику.
Стек AI-инструментов
- Claude Design — где спроектирован сам макет: обе дизайн-системы, токены,
.dc.html-прототипы и README собраны здесь, до передачи в разработку. - Claude Code — основной агент разработки: распаковка ZIP, чтение
.dc.html/README.md, написание спеки и плана, правка компонентов. - Claude Browser (MCP) — headless-превью запущенного
pnpm dev, для визуальной сверки готовой вёрстки со скриншотами дизайна прямо в диалоге, без выхода в отдельный браузер. - Superpowers skills (
brainstorming,writing-plans) — задали формат: сначала спека и план, потом код, а не наоборот.
Промпт и процесс: от ZIP до спеки
Задача была сформулирована одной репликой, с приложенным файлом:
@"~/Downloads/design-handoff.zip"
Создай ветку develop, обновись с origin/main. Потом в этой ветке
собери мне новый сайт с новым дизайном, приложил handoff-пакет
в котором мы сделали новый дизайн. Когда все будет готово запусти
локально и покажи мне результат.Дальше агент действовал по шаблону, который стоит повторять на любом хендофф-пакете:
1. Распаковать в /tmp, не в репозиторий. ZIP уходит во временную директорию, а не в рабочее дерево проекта — так дизайн-файлы не попадают в git по случайности и не путаются с реальными исходниками.
2. Прочитать README до просмотра HTML. README пакета описывал две независимые дизайн-системы на одном сайте: тёплый минимализм для блога (Inter + JetBrains Mono, светлая палитра в oklch) и CRT-терминал для отдельной страницы (шрифт VT323, зелёное свечение, scanline-эффект). Без этого шага легко смешать токены двух систем в одном компоненте.
3. Прочитать каждый .dc.html как спецификацию, а не как код для копипаста. В файлах вроде Blog.dc.html, Post.dc.html, SiteHeader.dc.html — уже готовые значения: oklch(0.98 0.004 90) для фона страницы, oklch(0.47 0.12 45) для акцентного оранжевого, радиусы 16-20px для карточек, 999px для пилюль. Это и есть design tokens, которые надо перенести в Tailwind-классы, а не HTML-разметку, которую надо перенести в JSX.
4. Зафиксировать прочитанное в спеке, прежде чем трогать код. Именно на этом шаге агент задокументировал карту маршрутов, список удаляемых компонентов и список того, что менять нельзя.
Спека вместо "сразу кодить"
Первый артефакт, который родился из хендофф-пакета, — не код, а markdown-документ. На вход агенту дали ZIP, на выходе перед первой строчкой TSX появилась спека с картой маршрутов:
| URL | Что | Система |
|---|---|---|
/ | Главная = список блога | A (блог) |
/posts/slug | Страница статьи | A (блог) |
/dossier | Отдельная CRT-страница с несколькими вкладками | B (CRT) |
Здесь же — явный список того, что редизайн не трогает: загрузку MDX-постов, JSON-LD, generateMetadata, sitemap-логику. Дизайн — визуальный и структурный пасс, данные и SEO-инфраструктура остаются как есть.
Смена URL-схемы постов обсуждалась в той же волне работы — если интересна именно эта тема отдельно, у неё своя механика в статье про URL-роутинг в Next.js, где разбирается переход от клиентского состояния к SEO-friendly маршрутам.
Отдельно спека фиксировала риск, который легко пропустить: один из валидаторов проекта хардкодил путь до старого файла страницы поста. Смена структуры роутов без правки валидатора — гарантированный красный pnpm build на следующем шаге, а не сюрприз в проде.
План на тысячу с лишним строк — и почему это не оверинжиниринг
После спеки — подробный план реализации, разбитый на этапы: общий каркас (шапка/подвал/фон), блог-система, CRT-система, роутинг и редиректы, финальная сверка.
Это выглядит избыточно для "просто перекрасить сайт" — примерно как доставать полное досье S.P.E.C.I.A.L., чтобы решить, в какой цвет покрасить забор. Но план — не бюрократия, а список конкретных файлов и порядка их правки, синхронизированный с зависимостями между ними (например: сначала токены в глобальных стилях, потом компоненты, которые на них ссылаются). План писался один раз и закрыл вопрос "что делать дальше" на десяток последующих коммитов.
Результат: две дизайн-системы на общем каркасе
Итоговая архитектура — общий каркас страницы (шапка, фон, подвал) и две независимые визуальные системы поверх него. Это прямое следствие исходного требования: не заменять один стиль другим, а developer-читаемый блог и личный CRT-раздел держать раздельно, но на одной кодовой базе.
Компонент шапки сайта, воссозданный из SiteHeader.dc.html, использует ровно то, что было в токенах хендофф-пакета — oklch-цвета вместо hex, плавный переход на наведении, без единой строки, скопированной из прототипа:
export function SiteHeader() {
return (
<header className="sticky top-0 z-20 glass border-b border-[oklch(0.88_0.005_260)]">
<div className="max-w-[1024px] mx-auto px-6 h-14 flex items-center justify-between gap-4">
<Link href="/" className="flex items-center gap-2.5 transition-opacity hover:opacity-70">
{/* лого-марка + вордмарк из design tokens пакета */}
</Link>
<nav aria-label="Основная навигация">
<a
href="https://t.me/zaplakhov"
className="rounded-full border border-[oklch(0.88_0.005_260)] transition
hover:border-[oklch(0.47_0.12_45_/_0.4)] hover:text-[oklch(0.47_0.12_45)]"
>
Подкинуть работёнку
</a>
</nav>
</div>
</header>
)
}Токены CRT-системы (зелёное свечение, тёмный фон терминала, приглушённый зелёный для второстепенного текста) легли в те же CSS custom properties, что уже существовали в проекте — их не пришлось изобретать заново, README пакета просто подтвердил актуальные значения свечения.
После переноса компонентов — обязательная визуальная сверка. Через MCP-инструмент браузерного превью агент поднял локальный pnpm dev, открыл главную страницу, страницу поста и CRT-раздел, прогнал все вкладки последнего и сверил итоговую вёрстку со скриншотами из дизайна — без ручного открытия Chrome DevTools в отдельном окне.
Редизайн вёрстки был проще, чем редизайн текста: почему AI-агент пишет слишком технично
Пересобрать компоненты по токенам оказалось предсказуемой механической работой — спека, план, код, визуальная сверка, готово. Куда сложнее и до сих пор не закрыто — научить того же агента писать сам контент в новом, более читаемом формате.
Разногласие повторяется почти в каждой сессии написания поста: агент по умолчанию тяготеет к суховатому, избыточно техническому изложению — оптимальному для того, чтобы его проиндексировал поисковик, но не для того, чтобы обычный человек дочитал статью до конца. Формально правильный текст, который живой читатель не откроет во второй раз — тот самый "нейрослоп", узнаваемый по гладким, но пустым формулировкам. Иронично: мы только что переехали из терминала, который читать было физически тяжело, в блог, который читать было эмоционально тяжело — просто по другой причине. Каждый раз приходится явно возвращать в промпт требование писать проще, разворачивать контекст "зачем это было нужно", добавлять конкретику вместо общих формулировок — и этот процесс настройки ещё не закончен, он идёт параллельно с самим редизайном.
Собственно, эта статья — часть того же эксперимента: она написана после нескольких раундов уточняющих вопросов о реальной мотивации, а не как пересказ commit-истории.
Pro Tips: работа с хендофф-пакетом через AI-агента
- Проси Claude Design сгенерировать README с текстовыми токенами, а не только картинки. Числовые значения (oklch, px, font-weight) агент читает точно; цвета "на глаз" по скриншоту — с погрешностью.
- Явно указывай агенту: "не копировать HTML/CSS дословно". Иначе получаешь вторую параллельную реализацию верстки рядом с существующей — двойную поддержку вместо редизайна.
- Спека и план — до первой правки компонента. Даже при "быстром" редизайне документ на 80-100 строк экономит больше времени, чем тратит: следующий коммит через день не начинается с "а что мы вообще решили".
- Гоняй существующие валидаторы сразу после смены структуры роутов, а не в конце. Правка захардкоженного пути в скрипте дешевле одной строкой сейчас, чем красным CI потом.
- Закрывай цикл визуальной сверкой в браузере, а не чтением диффа глазами. CSS-токены, которые выглядят правильно в коде, легко ошибаются в реальном рендере (line-height, backdrop-filter, стек шрифтов).
- Для контента, а не только для кода: явно проси AI писать проще и разворачивать мотивацию. Модель по умолчанию тяготеет к формально правильному, но сухому тексту — если цель "чтобы дочитал человек", а не просто "чтобы проиндексировал поисковик", это нужно требовать в промпте отдельно и переспрашивать себя же о реальных причинах решений, а не только о технических шагах.
Common Pitfalls
- Копирование
.dc.htmlкак есть. Design-code превью держит собственные inline-стили и разметку без учёта Server Components, MDX-рендера и уже существующих пропсов — перенос "один в один" плодит мёртвый код и рассинхрон с данными. - Пропуск README ради быстрого взгляда на HTML. Без текстового описания системы легко смешать токены двух дизайн-систем в одном компоненте — агент не знает, что акцент одной системы не должен попасть в палитру другой, если это не сказано явно.
- Забытые захардкоженные пути в валидаторах и конфигах. Смена схемы роутов — это не только компоненты, но и скрипты, sitemap, редиректы. Не проверил — сборка падает не на том шаге, где ждёшь.
- Доверие AI на слово в вопросе "что можно удалить". Спека предлагает список компонентов на снос — это нужно перепроверить самому перед мержем, а не полагаться на догадку модели о живом коде.
- Пропуск визуальной проверки в браузере. Дифф в коде может выглядеть корректным, а реальный рендер — разъехаться по отступам или шрифтам; без превью в браузере это всплывает только в проде.