Перейти к содержимому

Субботние эксперименты: своя платформа деплоя и два ИИ-проекта за день

Константин Потапов
9 мин

Как я собрал собственную платформу быстрого деплоя на Coolify, за одну субботу задеплоил два проекта сгенерированных локальными нейросетями — и зачем вообще это нужно.

Субботние эксперименты: своя платформа деплоя и два ИИ-проекта за день

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

Спойлер: получилось интереснее, чем я рассчитывал.

Coolify: от любопытства до продакшена

С Coolify я познакомился ещё на ранних версиях, когда это был симпатичный but rough инструмент для энтузиастов. Тогда я поставил, поиграл, закрыл вкладку и вернулся к привычному набору: Nginx вручную, скрипты деплоя, PM2. Стандартный DevOps-брутфорс.

Но пару месяцев назад обновился снова — и увидел другой продукт. Зрелый, стабильный, с нормальным UI и без сюрпризов в продакшене. Coolify сейчас — это self-hosted PaaS: вы берёте обычный VPS, ставите Coolify, и получаете собственный Heroku/Vercel, который живёт на вашем железе, не берёт процент с деплоев и не падает от чужих проблем с регионом.

Coolify умеет деплоить из git-репозитория, Docker-образов и docker-compose. Поддерживает автодеплой по пушу в ветку, SSL из коробки через Let's Encrypt, переменные окружения, логи в реальном времени и базы данных одной кнопкой.

Моя платформа — это Coolify как движок плюс моя конфигурация поверх. Coolify живёт в домашнем облаке, снаружи торчит Nginx Proxy Manager — он раздаёт SSL и маршрутизирует домены. Coolify об этом не знает, просто строит и запускает контейнеры. Главное — отработанный процесс от «сгенерировал код» до «проект доступен по URL» за несколько минут.

Именно это я и хотел проверить в субботу.

Эксперимент первый: лендинг без заморочек

Первый проект — deploy.potapov.me. Лендинг веб-студии. Генерировал без лишних раздумий: попросил локальную нейросеть сделать Next.js сайт с нормальной структурой страниц, секциями hero/features/services/cases и плавными анимациями.

Результат получился... нормальным. Именно нормальным, не идеальным. Модель выдала Next.js 16 с React 19, анимации на CSS transitions, компонент FadeIn для каждого блока, адекватный mobile-layout. Тексты — обобщённые заготовки про «10 лет опыта» и «500 проектов». Но структура — рабочая, код — чистый, деплоить — можно.

app/
  about/
  cases/
  components/
  contact/
  services/
  globals.css
  layout.tsx
  page.tsx

На деплой от git push до доступного URL ушло меньше трёх минут. Coolify подхватил репозиторий, собрал контейнер, поднял сервис, прописал SSL. Я открыл браузер — сайт работает.

Главный вывод этого эксперимента: генерация без промт-инжиниринга даёт шаблонный, но рабочий результат. Подходит как болванка для клиентского проекта, где потом всё равно менять тексты, цвета и изображения. Каркас готов — дальше работает человек.

Эксперимент второй: учимся промтить со слабыми моделями

Второй проект интереснее — tictac.potapov.me. Крестики-нолики, но не классические: победная линия — четыре в ряд, а не три. Звучит как мелочь, но это другая алгоритмическая сложность: больше комбинаций, другой минимакс, другие эвристики для бота. Задача была не написать игру, а научиться вытаскивать хороший результат из слабой нейросетки.

Слабые локальные модели — это реальность. Профессиональные Tesla с сотнями гигабайт памяти есть у дата-центров, не у нас с вами. Большинство работает на моделях 7–14B, которые хорошо справляются с простыми задачами, но начинают ломаться на сложных. Вопрос в том, как правильно формулировать задачи, чтобы получить то, что нужно.

Инструментарий: LM Studio для запуска модели локально, Opencode как AI-кодинг агент поверх неё. Ещё попробовал Goose — не зашло, слишком много автономии без контроля, не моё.

Процесс выглядел примерно так: объяснял каждый шаг как дебилу. Буквально. «Сначала создай файл с типами. Только типы, больше ничего. Вот структура...». Потом: «Теперь функцию проверки победителя. Только эту функцию». Потом следующую. Если бы писал сам — уложился бы раза в три быстрее. Это честно.

Отдельная боль — асинхронные колбэки. Модель стабильно в них путалась: генерировала код, где состояние читается до того как успевает обновиться, бот ходил по устаревшему борду, анимации вставали в гонку. Это не баг промта — это архитектурная проблема. Пришлось явно задавать структуру: весь игровой цикл через чистые функции без побочных эффектов, состояние только через useReducer, колбэки не трогают стейт напрямую. После того как дал модели эти ограничения рамками — перестала изобретать велосипед и начала писать предсказуемо.

Что получилось:

Архитектура: модель разложила код на три слоя — модели, логику и компоненты. Не монолит, а структура с разделением ответственности.

src/
  models/Game.ts         # типы GameState, Player
  logic/BoardLogic.ts    # чистые функции: победитель, ходы бота
  components/TicTacToe.tsx  # React UI

Бот с четырьмя режимами:

  • Лёгкий — случайные ходы
  • Средний — побеждает если может, но блокирует угрозы только в половине случаев
  • Сложный — идеальная игра: побеждает, строит вилки, блокирует, занимает центр
  • Непобедимый — минимакс с альфа-бета отсечением, математически совершенный

Визуал: неоновый дизайн, частицы при каждом ходе, анимация победы, комбо-система с множителем.

Минимакс с альфа-бета отсечением от локальной модели — это уже серьёзно. Алгоритм рабочий, логика корректная. Справилась не потому что умная, а потому что я разжевал задачу до элементарных шагов и не дал ей съехать в сторону.

Ключевой инсайт: слабые модели не нужно тянуть вверх — их нужно вести. Дать структуру заранее. Разбить сложное на простое. Показать интерфейс функции до того, как просить реализацию. Не говорить «напиши игру» — говорить «напиши вот эту функцию, вот её сигнатура, вот что она должна вернуть». Тогда 7B модель делает то, что обычно ожидаешь от 70B.

Но медленно. Это надо принять.

Процесс: от идеи до деплоя

Вот как выглядит весь поток, который я отработал за эту субботу:

  1. Генерация кода локальной нейросетью (LM Studio + Opencode)
  2. Ревью и минимальная доводка — исправить очевидные косяки, добавить .gitignore
  3. git push в репозиторий, подключённый к Coolify
  4. Coolify автоматически: сборка → контейнер → запуск
  5. Nginx Proxy Manager раздаёт домен и SSL
  6. Проверить в браузере

Всё. Между «промт готов» и «сайт онлайн» — минут десять, если не торопиться.

Это меняет экономику прототипирования. Раньше показать идею клиенту означало: набросать в Figma или объяснять на пальцах. Теперь это означает: сгенерировать, задеплоить, отправить ссылку.

Важная оговорка про клиентскую работу

Прежде чем дойти до «что дальше» — нужно сказать прямо, чтобы не было иллюзий.

В клиентских проектах я доверяю нейросетям только бойлерплейт: структура папок, конфиги, типы, базовые компоненты, стандартные CRUD-операции. То, что одинаково в каждом проекте и не несёт бизнес-ценности само по себе. Это ускоряет старт, не больше.

Бизнес-логику, архитектурные решения, интеграции, всё что будет болеть при поддержке — пишу сам. Потому что нейросеть не знает контекст вашего продукта, не несёт ответственности за результат и не будет чинить это в три часа ночи. Я — буду.

Вайб-кодинг — это когда генерируешь и не читаешь. Я читаю каждую строку перед коммитом.

Что дальше

Эта суббота была тестовым прогоном. Платформа работает, процесс отработан, инструменты понятны.

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

Если вам интересно, как это работает в формате услуги — я делаю сайты с помощью ИИ: от прототипа до готового продукта быстро и с предсказуемым результатом. Подробнее — на странице услуги.


Оба проекта из этой субботы живут на моей платформе деплоя: deploy.potapov.me и tictac.potapov.me. Можно зайти и потыкать.