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

Суббота: Coolify, две локальные модели, два сайта к вечеру

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

Обкатал self-hosted деплой на Coolify и за день выкатил два проекта с локальных моделей: лендинг студии и крестики-нолики четыре в ряд. URLы живые.

Суббота: Coolify, две локальные модели, два сайта к вечеру

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

Получилось два живых URL.

Coolify

С Coolify я встречался на ранних версиях: поставил, поиграл, закрыл вкладку и вернулся к Nginx руками, скриптам и PM2. Обычный брутфорс.

Пару месяцев назад открыл снова и увидел другой продукт. Self-hosted PaaS: обычный VPS, свой Heroku без процента с деплоев и без чужого региона, который внезапно лёг. Деплой из git, Docker-образа и docker-compose. Автодеплой по пушу, 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. Тексты заготовки про «10 лет опыта» и «500 проектов». Структура рабочая, код чистый, деплоить можно.

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

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

Генерация без возни с промптом даёт шаблон. Для болванки клиентского проекта, где всё равно менять тексты и картинки, этого хватает. Каркас готов, дальше работает человек.

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

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

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

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

Каждый шаг объяснял как дебилу. Сначала файл с типами. Только типы. Потом функцию проверки победителя. Только её. Если бы писал сам, уложился бы раза в три быстрее. Это честно.

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

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

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

Визуал неоновый, частицы на ход, анимация победы, комбо с множителем. Минимакс от локальной 7B модели получился рабочий не потому что модель умная. Потому что задачу разрезали до сигнатур и не дали съехать.

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

От промпта до URL

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

Между «промпт готов» и «сайт онлайн» минут десять, если не торопиться. Раньше показать идею значило макет в Figma или пальцы в воздухе. Теперь можно отправить ссылку.

Где этим нельзя кормить клиента

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

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

Если нужен сайт из Telegram-канала, страницы услуг, статьи и FAQ под поиск, это отдельная услуга: /ru/telegram-site.

Оба субботних проекта живы: deploy.potapov.me и tictac.potapov.me. Можно потыкать.