Собрал локальный MVP сервиса для поиска тиммейтов
Я регулярно встречаю объявления вроде «ищу дуо», «нужен саппорт», «собираю стак» в TikTok, Telegram, Discord и игровых пабликах.
Обычно в таком сообщении есть название игры, иногда ранг и время. Остальное выясняется в личке: кто как играет, нужен ли войс, насколько человек настроен на рейтинг, хочет ли он одну катку или постоянную команду. Сообщения быстро уезжают вверх, старые заявки продолжают висеть, а нормальные контакты теряются среди десятков чатов.
На хакатоне Kodik я решил проверить идею отдельного сервиса для такой задачи. Рабочее название — AbyssHub.
Я делал проект один. Сейчас у меня есть локальная версия, интерфейсы и кодовая база. Публично сервис ещё не запущен: я хочу сначала понять, есть ли у этой идеи спрос, какие сценарии важнее всего и где пользователи увидят проблемы раньше, чем я вложу в разработку ещё несколько месяцев.
Что хочу сделать
В первой версии пользователь заполняет анкету: выбирает игры, ранг, роль, регион, часовой пояс, язык, формат общения и цель поиска. Затем смотрит ленту анкет, ставит лайк или пропускает карточку. Взаимный лайк должен открывать чат. Отдельно предусмотрен поиск команды под конкретную задачу: турнир, стрим, регулярная игра или разовый сбор.
На бумаге это похоже на механику дейтинг-приложений. В игровом контексте важнее другое: перед первым сообщением быстро понять, совпадаете ли вы по условиям игры.
Например, я бы скорее написал человеку с такой анкетой:
CS2, Premier, будни после 20:00 по Москве. Ищу постоянный стак. Играю на результат, нужен войс, без оскорблений и ливов после первой неудачной карты.
Чем отвечал бы на короткое «ищу тиммейтов в CS2».
Что есть в коде
Репозиторий я собрал как монорепо: в нём лежат backend, frontend и инфраструктура. Бэкенд написан на Go, интерфейс — на TypeScript с Next.js, а SQL-миграции вынесены отдельно.
Внутри бэкенда я сразу разложил домены по сервисам:
- auth-service — регистрация, вход и токены;
- profile-service — анкета, игровые данные и аватары;
- matching-service — выдача карточек, лайки и мэтчи;
- chat-service — переписка после мэтча;
- team-search-service — поиск команды под конкретную задачу;
- moderation-service — жалобы и блокировки;
- notification-service — уведомления;
- payment-service — будущие платные возможности.
Это спорное решение для соло-разработки и ранней стадии. Несколько автономных сервисов добавляют точки отказа, усложняют локальную отладку и требуют больше дисциплины в API-контрактах. Я выбрал такую структуру, потому что у доменов довольно разные границы: авторизация, подбор, чат и модерация будут развиваться по-разному, а чат потенциально создаёт самую заметную нагрузку и самые неприятные риски.
Если по итогам обсуждения окажется, что такая структура слишком тяжёлая для текущей стадии, я без сожалений сведу часть логики в модульный монолит. Мне важнее скорость проверки продуктовой гипотезы, чем архитектурная красота.
Как устроен локальный стенд
Локальное окружение поднимается через Docker Compose. В нём есть PostgreSQL 16, Redis 7, Centrifugo для real-time-соединений, Asynqmon для наблюдения за фоновыми задачами, Nginx и контейнеры сервисов.
PostgreSQL хранит основные сущности продукта. В репозитории уже есть миграции для исходной схемы, ролей пользователей, soft delete, расширения pgcrypto, тестовых данных, дневных лимитов свайпов, аналитических данных, поиска команды и аватаров чатов.
Redis нужен для вещей, которые не хочется каждый раз считать или хранить в основной базе: сессий, лимитов, rate limiting и фоновых задач. Для реального времени я заложил Centrifugo: он снимает с прикладного кода часть работы с постоянными WebSocket-подключениями и pub/sub.
Почему подбор пока простой
Сейчас подбор устроен намеренно грубо: пользователи могут попасть в выдачу, если у них есть хотя бы одна общая игра. Вокруг этого уже можно строить фильтры по рангу, региону и роли.
Я сознательно не стал делать «умную» алгоритмическую ленту во время хакатона. Для неё нужны данные, которых у меня пока нет: какие карточки люди реально открывают, кому пишут, после каких мэтчей доходят до игры, какие фильтры используют и почему возвращаются или не возвращаются.
Есть слишком много предположений, которые хочется проверить:
- Для Доты и CS2 ранг \ ммр может быть важнее прайм-тайма.
- Для кооп-игр вроде Genshin Impact важнее цель и стиль общения.
- Для постоянной команды критичны часовой пояс и регулярность.
Сложный скоринг появится позже, если подтвердится, что люди вообще готовы заполнять профиль и искать через карточки. Сначала нужна простая, объяснимая логика выдачи.
Самая трудная часть — безопасность
Карточки, фильтры и лайки — понятная продуктовая механика. Больше всего времени у меня ушло на вопросы, связанные с безопасностью.
Сервис собирает чувствительный для игрока контекст: когда он бывает онлайн, где играет, как предпочитает общаться, что ищет и с кем готов вступать в контакт. После мэтча появляется переписка между незнакомыми людьми. В такой системе быстро возникают спам, оскорбления, преследование, мошеннические ссылки и попытки вытащить личные данные.
Поэтому в проект заложены отдельный сервис модерации, репорты, блокировки, soft delete и ограничения на действия пользователей. В конфигурации локального окружения секреты вынесены в переменные окружения, Redis запускается с паролем, а сервисы зависят от healthcheck’ов PostgreSQL и Redis.
Для входа планируется обычная схема email/логин и пароль с хэшированием через bcrypt, а для чата — TLS на уровне канала. Подтверждение email и привязку Steam/Riot-аккаунтов я отложил на следующий этап: эти механики нужны для доверия к профилям, но не должны тормозить проверку базового сценария.
Что хочу проверить до запуска
Сейчас для меня важнее всего ответы на несколько вопросов:
- Захотят ли игроки заполнить анкету из 10–15 полей ради более точного поиска.
- Какие параметры действительно нужны в карточке до первого сообщения.
- Достаточно ли совпадения по игре для первой выдачи.
- Где пользователи проведут границу между полезным профилем и лишним сбором данных.
В репозитории уже заложены продуктовые воронки: заполнение анкеты, первый свайп, первый мэтч, первое сообщение, а также retention D1, D7 и D30. Именно эти показатели я хочу смотреть в закрытом тесте, а не общее число регистраций.
Нужна критика
Буду рад фидбеку от игроков, разработчиков и администраторов игровых сообществ.
Если ты ищешь тиммейтов, расскажи:
- В какие игры ты играешь и где сейчас ищешь людей.
- Какие три поля чужого профиля для тебя самые важные.
- Готов ли ты пользоваться внутренним чатом или предпочёл бы сразу перейти в Discord/Telegram.
- Что вызовет недоверие к такому сервису.
- В каком сценарии ты бы попробовал AbyssHub первым: одна катка, дуо в рейтинг, постоянный стак, кооп или турнир.
Если ты работаешь с Go, real-time-системами или продуктами с пользовательским контентом, особенно интересны замечания к текущему делению на сервисы, модели безопасности и очередности разработки.