П/ВИН

KP Generator: как мы строили генератор КП-презентаций

·9 мин чтения
KP Generator: как мы строили генератор КП-презентаций

Коммерческое предложение — это первое, что видит потенциальный клиент после переговоров. И в B2B-сегменте «просто хорошее» КП давно не работает. Нужно лучшее. Именно с этой амбициозной задачей я начал проект kp-generator: сделать генератор КП-презентаций, который был бы не просто функциональным, но и визуально безупречным. Расскажу, как мы шли от исследования структуры идеального КП до полноценной системы с 10 дизайн-пресетами и живым превью в интерфейсе.

С чего всё началось: исследование идеального B2B-КП

Прежде чем писать хоть строчку кода, я провёл ресёрч. Изучил данные Gong (67 тысяч записей звонков с разбором что работает в продажах), отчёты Prospeo 2026, методологии Brixon Group, McKinsey и Forrester. Параллельно смотрел на нарративные фреймворки — CDP, Raskin's Arc, Gong's Nexus Model.

Вывод оказался неожиданно чётким: лучшие КП в мире строятся по «10-12 slide spine» — позвоночнику из слайдов с железной логикой. Проблема → цена бездействия → решение → доказательства → ROI. Никаких отступлений, никаких «а ещё мы умеем вот это».

Для нашего продукта — системы операционного управления на базе Toyota/Lean — центральное обещание звучало так: «рост прибыли 20-30% за 3 месяца без найма». Это не маркетинговый слоган, это конкретный оффер, который нужно было упаковать в визуальную историю.

Архитектура проекта: что было до

Когда я подключился к работе над kp-generator, уже существовал базовый движок в рамках проекта v0-german. Там был 4-шаговый визард, который генерировал три PDF-документа — диагностику, КП и дорожную карту — через GPT-4o и библиотеку @react-pdf/renderer.

Дизайн был честно скажу — бордовый с золотым, базовая типографика, никаких изысков. Функционально работало, визуально — нет. PDF-рендеринг через react-pdf жёстко ограничивает возможности: нет анимаций, нет сложных раскладок, нет того визуального «вау», который нужен для продающей презентации.

Параллельно существовал slides-generator — эксперимент с Google Stitch для генерации HTML-слайдов с AI-изображениями и последующим экспортом в Google Slides. Но это был отдельный пайплайн без интеграции с основным продуктом.

Задача стала очевидной: объединить лучшее из двух миров — персонализированный контент из диагностики + красивые Google Slides как итоговый формат.

Выбор формата: почему Google Slides

Первый стратегический вопрос — в каком формате отдавать КП клиенту. Было три варианта:

PDF через Puppeteer — pixel-perfect, но статичный. Клиент не может редактировать, менеджер не может быстро подправить цифры перед встречей.

Google Slides через API — редактируемая презентация, клиент получает ссылку, можно показывать на экране во время встречи, менеджер правит в реальном времени.

Hybrid: сначала промты, потом автоматизация — создать набор промтов под каждый слайд, вручную проверить качество в Google Stitch, потом встроить в автоматику.

Мы выбрали третий путь как наиболее прагматичный: сначала валидируем визуальный язык вручную, потом автоматизируем. Это сохраняет гибкость и позволяет итерировать дизайн без переписывания кода.

Для автоматизации используется Google Slides API — мощный инструмент, который позволяет программно создавать слайды, управлять шейпами, цветами, шрифтами и позиционированием элементов.

Структура идеального КП: гибридный подход

Изучив несколько методологий, мы остановились на гибридной структуре из 11 слайдов:

  1. Титул + Обещание — имя клиента, конкретный результат, дата
  2. Точка А (Диагностика) — персонализированная картина «где вы сейчас» на основе данных из диагностики
  3. Цена бездействия — что происходит если ничего не менять (в деньгах)
  4. Точка Б — конкретная картина результата через 3 месяца
  5. Метод — как именно достигается результат (Toyota/Lean система)
  6. Доказательства — реальные кейсы с цифрами
  7. Процесс работы — 3-4 шага, что происходит на каждом
  8. Инвестиция и ROI — тарифы, окупаемость в месяцах
  9. Гарантии — снятие рисков
  10. Следующий шаг — конкретный CTA
  11. Контакты — менеджер, мессенджеры

Ключевой принцип: каждый слайд должен отвечать на один вопрос в голове клиента. Нет слайда ради слайда.

Персонализация — отдельная история. Данные из исследований показывают 3.2x конверсию при глубокой персонализации против универсальных шаблонов. Поэтому каждый промт для генерации слайда содержит плейсхолдеры: {{client_name}}, {{business}}, {{pain_points}}, {{revenue}} — всё берётся из диагностики, которую клиент заполняет на первом шаге.

Главная проблема: дизайн уровня 2010 года

Когда базовая генерация заработала, встал следующий вопрос — и именно он стал основной темой второй большой итерации. Дизайн был, мягко говоря, устаревшим. Generic dropdown с шестью темами: auto, dark, light, blue, green, gradient. Пользователь выбирает «blue» и не знает что получит. Claude интерпретирует hint как хочет. Результат непредсказуем.

Для B2B-презентации, которая должна производить впечатление на собственников бизнеса — это катастрофа.

Мы приняли решение: переделать систему тем с нуля. 10 полноценных дизайн-пресетов с живым CSS-превью в интерфейсе.

10 дизайн-пресетов: от Brutalism до Mono

После ресёрча современных визуальных трендов собрали следующий набор:

| # | Стиль | Характер | Для кого | |---|-------|----------|----------| | 1 | Brutalism | Толстые рамки, асимметрия, кремовый/чёрный | Агрессивные рынки, стартапы | | 2 | Neon Cyber | Тёмный фон, неоновые акценты, глоу-эффекты | Tech, IT-продукты | | 3 | Glassmorphism | Полупрозрачные карточки, blur, gradient mesh | SaaS, финтех | | 4 | Gradient Flow | Плавные градиенты, органические формы | Маркетинг, креативные агентства | | 5 | Dark Luxury | Угольный фон, золотые акценты | Премиум-сегмент, консалтинг | | 6 | Corporate Pro | Строгий синий, чистая типографика | B2B классика, банки | | 7 | Retro Wave | Пурпур + оранжевый, ретро-эстетика | Нестандартные бренды | | 8 | Editorial | Минимализм, типографика в центре | Консалтинг, стратегия | | 9 | Nature Organic | Зелёный, натуральные текстуры | ESG, экологичные бренды | | 10 | Mono Sharp | Чёрно-белый, высокий контраст | Архитектура, дизайн-студии |

Каждый пресет — это не просто набор цветов. Это структурированный TypeScript-объект с полной спецификацией:

interface ThemePreset {
  id: string;
  name: string;
  description: string;
  colors: {
    background: string;
    surface: string;
    primary: string;
    accent: string;
    text: string;
    textSecondary: string;
  };
  fonts: {
    heading: string;
    body: string;
    mono?: string;
  };
  style: {
    borderRadius: 'none' | 'small' | 'medium' | 'large';
    shadows: 'none' | 'subtle' | 'strong';
    decorativeElements: string[];
  };
  claudeHint: string; // подсказка для AI как оформлять контент
}

Пример пресета Brutalism:

{
  id: 'brutalism',
  name: 'Brutalism',
  description: 'Сырая энергия, грубые формы, максимальный контраст',
  colors: {
    background: '#fef5e7',
    surface: '#000000',
    primary: '#ff3333',
    accent: '#ffcc00',
    text: '#000000',
    textSecondary: '#333333',
  },
  fonts: {
    heading: 'Space Grotesk',
    body: 'Roboto Mono',
  },
  style: {
    borderRadius: 'none',
    shadows: 'none',
    decorativeElements: ['thick-borders', 'offset-boxes', 'raw-shapes'],
  },
  claudeHint: 'Используй резкие заголовки, короткие ударные фразы, избегай мягких формулировок. Контент должен быть прямолинейным и агрессивным.',
}

Архитектура CSS-превью

Одна из самых важных UX-задач: пользователь должен видеть реальный вид слайда ДО генерации. Мы реализовали компонент ThemePreview — миниатюрный CSS-рендер слайда, который точно отражает финальный результат в Google Slides.

Подход: пресет задаёт палитру и стилевые гайдлайны, Claude творит в рамках этого стиля, CSS-превью показывает общий вайб. Это осознанный компромисс — не pixel-perfect копия, но достаточно точное отражение настроения и цветовой схемы.

function ThemePreview({ preset }: { preset: ThemePreset }) {
  return (
    <div
      className="theme-preview"
      style={{
        backgroundColor: preset.colors.background,
        border: preset.style.borderRadius === 'none'
          ? `3px solid ${preset.colors.primary}`
          : 'none',
        borderRadius: preset.style.borderRadius === 'none' ? 0 : 8,
      }}
    >
      <div
        className="preview-title"
        style={{
          fontFamily: preset.fonts.heading,
          color: preset.colors.text,
        }}
      >
        {preset.name}
      </div>
      <div
        className="preview-accent"
        style={{ backgroundColor: preset.colors.accent }}
      />
      <div
        className="preview-body"
        style={{
          fontFamily: preset.fonts.body,
          color: preset.colors.textSecondary,
        }}
      >
        {preset.description}
      </div>
    </div>
  );
}

Интеграция с Google Slides API

Самая технически сложная часть — перевести дизайн-пресет в реальные элементы Google Slides. Библиотека googleapis для Node.js предоставляет полный доступ к Slides API, но требует точного понимания модели данных.

Мы написали layout renderer — функцию, которая принимает слайд (контент + пресет) и возвращает набор requests для Google Slides API:

function buildSlideRequests(
  slideContent: SlideContent,
  preset: ThemePreset,
  slideId: string
): slides_v1.Schema$Request[] {
  const requests: slides_v1.Schema$Request[] = [];
 
  // Фон слайда
  requests.push({
    updatePageProperties: {
      objectId: slideId,
      pageProperties: {
        pageBackgroundFill: {
          solidFill: {
            color: hexToRgb(preset.colors.background),
          },
        },
      },
      fields: 'pageBackgroundFill',
    },
  });
 
  // Заголовок с правильным шрифтом
  requests.push({
    insertText: {
      objectId: `${slideId}_title`,
      text: slideContent.title,
    },
  });
 
  requests.push({
    updateTextStyle: {
      objectId: `${slideId}_title`,
      style: {
        fontFamily: preset.fonts.heading,
        foregroundColor: {
          opaqueColor: { rgbColor: hexToRgb(preset.colors.text) },
        },
        bold: true,
      },
      fields: 'fontFamily,foregroundColor,bold',
    },
  });
 
  return requests;
}

Важный момент из code review: цвета между CSS-превью и Google Slides должны точно совпадать. На первой итерации была ошибка — hex-значения корректно парсились в CSS, но функция hexToRgb для Slides API возвращала нормализованные float-значения (0-1), и где-то закралась ошибка округления. Поправили, покрыли тестами.

Пайплайн разработки: subagent-driven development

Для реализации мы использовали подход Subagent-Driven Development — каждая задача выполняется свежим субагентом с двухэтапным ревью: сначала проверка соответствия спеке, потом качество кода.

12 задач в плане:

  1. TypeScript типы (ThemePreset interface)
  2. 10 пресетов в lib/theme-presets.ts
  3. CSS-превью компонент (ThemePreview)
  4. Селектор тем (ThemeSelector — список + превью)
  5. Обновление Create page
  6. Обновление Edit page
  7. Layout renderer
  8. Обновление Google Slides renderer
  9. Обновление Claude промптов
  10. Обновление API routes
  11. Подключение Google Fonts
  12. Финальная сборка и верификация

Всё закончилось 6 коммитами и успешным деплоем. Bilд прошёл с первого раза после финальных фиксов из code review.

Результат

Что получили в итоге:

Было: generic dropdown с 6 текстовыми опциями, непредсказуемый дизайн, один PDF-формат

Стало: 10 визуальных пресетов с живым превью, персонализированные Google Slides КП, структура из 11 слайдов по лучшим B2B-практикам, полная интеграция данных из диагностики

Селектор тем теперь показывает миниатюрный слайд для каждого пресета — пользователь сразу видит цвета, шрифты, общее настроение. Выбор осознанный, а не вслепую.

Каждое КП персонализировано: имя компании, отрасль, выявленные проблемы, цифры из диагностики — всё подставляется автоматически.

Выводы и уроки

Первый и главный урок: дизайн — это не украшение, это часть продукта. Когда мы занимались только функциональностью генерации, казалось что всё работает. Но «работает» и «производит впечатление» — разные вещи. В B2B-продажах визуал КП напрямую влияет на конверсию. Мы это знали теоретически, но сделали правильно только когда взялись за это как за отдельную инженерную задачу.

Второй урок: начинать с исследования — не трата времени. Полдня на изучение методологий Gong, McKinsey и Forrester дали нам чёткую структуру из 11 слайдов, которую мы не придумывали с нуля. Эта структура основана на данных о реальных продажах, а не на интуиции. Код пишется быстрее когда знаешь точно что строить.

Третий урок: гибридный подход к автоматизации работает. Мы не пытались автоматизировать всё сразу. Сначала валидировали концепцию вручную через Google Stitch, потом встроили в автоматику. Это сэкономило нам минимум неделю разработки — мы не переписывали систему после того как обнаружили что визуал не тот.

Четвёртый урок: TypeScript-типы для дизайн-системы — это инвестиция, которая окупается немедленно. Строгий ThemePreset interface поймал несколько ошибок ещё на этапе компиляции. Без типов мы бы ловили их в рантайме, когда Google Slides API возвращал ошибки форматирования цвета.

Пятый урок: code review после реализации нашёл реальные баги. Несовпадение цветов между CSS-превью и финальным слайдом, отсутствующий фолбэк на edit page — это не мелочи, это UX-критичные проблемы. Двухэтапное ревью (спека + качество кода) — не бюрократия, а страховка.

Проект продолжается. Следующие шаги — A/B тестирование пресетов на реальных клиентах, метрики конверсии по каждому стилю и, возможно, генерация AI-изображений как дополнительный слой поверх базовых пресетов. Но даже в текущем виде это уже совсем другой продукт по сравнению с тем, с чего начинали.

Паша Вин
Паша Вин

AI-инженер, предприниматель, маркетолог. Основатель feberra.com и x10seo.ru. 13 лет в перфоманс-маркетинге, 3 года в системной интеграции AI в бизнес.

Связанный проект

Slides Generator