
Почему мы перешли на монорепозиторий
Мы только что завершили крупное обновление инфраструктуры: переход от отдельных репозиториев к единой структуре монорепозитория.
Зачем нужны изменения?
Brandmine состоит из двух основных приложений:
- Статический сайт Hugo (brandmine.ai) - Наша публичная контентная платформа
- Внутреннее приложение Hub (hub.brandmine.ai) - CRM, pipeline сделок, управление историями
Раньше они находились в отдельных репозиториях. Каждое общее обновление означало двойную работу - копирование TypeScript типов, конфигурационных файлов, синхронизация структур данных.
Проблема: Простое изменение схемы требовало редактирования 6+ файлов в 2 репозиториях, отслеживания 2 отдельных развёртываний и надежды, что ничего не рассинхронизируется.
Что мы построили
Наш монорепозиторий использует современные инструменты, созданные именно для такого сценария:
1. Единое рабочее пространство (pnpm)
Одна команда pnpm install устанавливает все зависимости для обоих приложений. Больше не нужно переключаться между репозиториями для запуска скриптов настройки.
2. Общие пакеты
Мы создали 4 внутренних пакета, которые используют оба приложения:
@brandmine/shared-types- Единый источник истины для TypeScript интерфейсов@brandmine/typescript-config- Единообразная конфигурация tsconfig для всех проектов@brandmine/prettier-config- Унифицированное форматирование кода@brandmine/eslint-config- Общие правила линтинга
Результат: Измените определение типа один раз, оба приложения получают его мгновенно.
3. Интеллектуальная система сборки (Turborepo)
Turborepo добавляет кэширование и выполнение задач с учётом зависимостей:
- Первая сборка: 11,4 секунды
- Кэшированная сборка: 204 мс (на 98% быстрее, ускорение в 55 раз)
- Параллельные dev-серверы: Запуск Hugo и Hub одновременно
Сообщение «FULL TURBO» при попадании в кэш вызывает необоснованное удовлетворение.
Реальное влияние
До монорепозитория
# Терминал 1
cd brandmine-hugo
npm install
hugo server
# Терминал 2
cd brandmine-hub
npm install
npm run dev
# Изменение схемы
# → Редактирование hugo/data/schema.json
# → Копирование в hub/src/types/schema.ts
# → Ручная синхронизация
# → Надежда, что ничего не пропустили
После монорепозитория
# Один терминал
pnpm dev # Оба приложения запущены
pnpm build # Оба приложения собраны (с кэшированием)
# Изменение схемы
# → Редактирование packages/shared-types/index.ts
# → Оба приложения обновляются автоматически
# → Типобезопасность гарантирована
Технические детали
Миграция в 5 фаз:
- ✅ Создан пакет общих типов
- ✅ Переход на pnpm workspaces
- ✅ Реструктуризация в макет
apps/иpackages/ - ✅ Созданы пакеты общих конфигураций
- ✅ Интегрировано кэширование Turborepo
Дисковое пространство: Сэкономлено ~500 МБ (сокращение на 40-50%) за счёт устранения дублирующихся зависимостей.
Нулевой простой: Все миграции происходили без влияния на production развёртывания. Сборки Cloudflare Pages адаптировались без проблем.
Что это даёт
Упрощённая синхронизация данных Hugo ↔ Hub
Наши скрипты синхронизации (sync-to-supabase.js, sync-from-supabase.js) теперь импортируют общие типы напрямую. Больше никакой хрупкой валидации на основе строк.
Уверенный рефакторинг
TypeScript знает обо всех использованиях в обоих приложениях. Переименовываете поле? Компилятор показывает каждое место, требующее обновления.
Быстрая адаптация
Новые разработчики клонируют один репозиторий, запускают pnpm install и готовы к работе. Никакой путаницы «какой репозиторий мне нужен?».
Извлечённые уроки
Важность имён фильтров
Turborepo требует точных имён пакетов (@brandmine/hugo, а не hugo). Мы узнали это на своём опыте, когда сборка Cloudflare завершилась неудачей. Теперь мы сначала тестируем имена фильтров локально.
Паттерны Gitignore для монорепозиториев
Паттерны корневого уровня (/public/) не применяются к подкаталогам (apps/hugo/public/). Мы исправили это немедленно и удалили 1000+ случайно отслеживаемых артефактов сборки.
Изменения синтаксиса версий
Turborepo v2.x использует tasks вместо устаревшего ключа pipeline. Всегда проверяйте последнюю документацию при реализации по старым спецификациям.
Почему это важно
Большинство миграций монорепозиториев связаны с масштабом (Google, Meta управляют тысячами сервисов). Наша миграция - о ясности.
Когда ваш CTO - это Claude, а CEO переключается между бизнес-стратегией и технической реализацией, снижение когнитивной нагрузки имеет значение. Один репозиторий, одна истина, одна команда для запуска всего.
Цель: Меньше времени на координацию инфраструктуры, больше времени на освещение исключительных брендов.
Что дальше
Сейчас: Дать монорепозиторию стабилизироваться 2-3 недели. Мы не гонимся за теоретическими оптимизациями.
В будущем (при необходимости):
- Удалённое кэширование (Turborepo Cloud)
- Оптимизация CI/CD (обнаружение затронутых задач)
- Общие утилитарные пакеты
А пока? Мы создаём функции, а не инфраструктуру.