Проблема 😩
Спринт-планирование. Команде нужно оценить таски. Кто-то кидает ссылку на Planning Poker. Ты кликаешь. Ждёшь. Половина команды не может подключиться. Вторая половина уже ушла за кофе.
Знакомо?
У нас в AGG TEAM мы перепробовали всё:
- Planning Poker Online (лагает, реклама, древний интерфейс)
- Scrum Poker for Jira (дорого, требует Jira)
- PlanITpoker (работает, но нет НАШИХ фич)
После третьего краша посреди оценки я подумал: "Да пошло оно, сделаю сам."
Настоящая задача: 6 команд, 1 комната 🤯
Вот в чём загвоздка: у нас не ОДНА скрам-команда. У нас ШЕСТЬ отделов:
- Frontend, Backend, DevOps, QA, Аналитика, Менеджмент
Все хотят делать планинг покер. Одновременно. В одной комнате.
Это хаос. Как играть в шесть разных карточных игр за одним столом.
Существующие инструменты: "Вот комната, сами разбирайтесь!" Не идеально.
Что я сделал
🎰 Поддержка нескольких столов (до 6!)
Основная идея: одна сессия, несколько независимых столов.
interface Table {
id: string;
name: string; // "Frontend отдел", "Backend ниндзя"
revealed: boolean; // Карты раскрыты для этого стола?
}
interface Player {
id: string;
name: string;
tableId: string; // За каким столом сидит
vote: string | null; // "5", "13", "?", "☕"
}
Хост создаёт столы с кастомными названиями. Все выбирают свой стол. Каждый стол голосует независимо. Видишь все столы + общую среднюю оценку.
Возможности хоста: Добавлять, удалять, переименовывать столы на лету. Перемещать людей между столами при необходимости.
⚡ Real-time синхронизация
Использовал Supabase как бэкенд. Простой подход с polling:
useEffect(() => {
if (view === 'room' && roomId) {
fetchRoomState();
const interval = setInterval(fetchRoomState, 2000);
return () => clearInterval(interval);
}
}, [view, roomId]);
Да, WebSocket'ы были бы круче. Но для прототипа и ~50 пользователей? Polling отлично работает. Если масштаб вырастет, переделаю.
Обновления в реальном времени:
- Кто-то присоединился → мгновенно
- Кто-то проголосовал → сразу
- Карты раскрыты → все видят результаты
- Эмодзи брошено → летит через экран
💓 Умное определение отключения
Проблема других инструментов: люди закрывают вкладки, но их аватары остаются навсегда. Пользователи-призраки.
Моё решение использует heartbeat + явное отключение:
// Отправляем heartbeat каждые 10 секунд
const sendHeartbeat = async () => {
await fetch(`${API_URL}/rooms/${roomId}/heartbeat`, {
method: 'POST',
body: JSON.stringify({ playerId }),
});
};
// Также явное отключение при закрытии страницы
window.addEventListener('beforeunload', () => {
navigator.sendBeacon(
`${API_URL}/rooms/${roomId}/disconnect`,
JSON.stringify({ playerId })
);
});
Результат:
- Страница открыта, но бездействуешь? Сиди сколько хочешь (без киков)
- Закрыл страницу/вкладку? Мгновенное отключение (2 секунды)
Никаких призраков. Чистые комнаты.
🎉 Атаки эмодзи!
Моя любимая фича. Кликаешь на любого участника, кидаешь эмодзи. Оно буквально летит от твоего аватара к его с плавной анимацией (💩)(🤮).
12 эмодзи: 👍 👏 🎉 ❤️ 🚀 🔥 😂 🤔 💯 ✨ 👌 🙌
Реальные сценарии:
- 👍 согласен с оценкой
- 🔥 кто-то делает отличное замечание
- 😂 джун оценивает простую таску в 89 поинтов
- ☕ определённо пора за кофе
Это сделало наши планирования весёлыми. Люди реально теперь ждут оценочные встречи!
🃏 Фибоначчи + специальные карты
Классика: 0, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89
Плюс:
- "?" → "Понятия не имею"
- "☕" → "Нужен кофе перед размышлениями"
Можно менять голос даже после раскрытия. Почему? Потому что во время обсуждения можешь понять, что 13 на самом деле 8. Большинство инструментов блокируют голоса. Мой - нет.
🧮 Автоматический расчёт среднего
Каждый стол показывает свою среднюю. Плюс общий итог внизу по ВСЕМ столам.
const calculateAverage = (players, revealed) => {
if (!revealed) return null;
const numericVotes = players
.map(p => p.vote)
.filter(v => v && !isNaN(Number(v)))
.map(Number);
if (numericVotes.length === 0) return null;
return (numericVotes.reduce((a, b) => a + b) / numericVotes.length).toFixed(1);
};
Идеально для: "Какая общая оценка по всем командам?"
🌙 Тёмная тема + 🌍 Мультиязычность
Переключатель в углу меняет тему (светлая/тёмная) и язык (RU/EN). Сохраняется в localStorage, автоматически применяется в следующий раз.
Потому что если в твоём приложении в 2026-м нет тёмной темы... что ты вообще делаешь?
Технический стек 🛠
Frontend:
- React + TypeScript
- Tailwind CSS v4
- Lucide иконки
Backend:
- Supabase Edge Functions (Hono + Deno)
- Supabase KV Store (key-value таблица)
Почему Supabase?
- Быстрая настройка (без деплоя сервера)
- Edge Functions (TypeScript бэкенд)
- Простой KV store для состояния комнат
- Бесплатный tier для прототипов
Вызовы и решения 💡
1. Пользователи-призраки
Проблема: Пользователи закрывают вкладки, аватары остаются навсегда
Решение: Механизм heartbeat + явное отключение через navigator.sendBeacon
2. Управление состоянием
Проблема: Синхронизация 6 столов + игроков
Решение: Единый источник правды в бэкенде, polling для обновлений
Как изменились планирования
До:
- "Стойте, все загрузились?"
- "Обнови, я не вижу твой голос"
- "Кто ещё тут?"
- неловкое ожидание
После:
- Создать комнату (5 секунд)
- Все заходят (мгновенно)
- Голосуем, раскрываем, обсуждаем
- Кидаемся эмодзи для веселья
- Реально заканчиваем вовремя
Реальные отзывы:
"Стойте, планинг покер может быть плавным?"
"Обожаю кидать огненные эмодзи в людей!"
"Наконец инструмент, который не бесит"
Что дальше? 🚀
- История сессий (кто как голосовал)
- Таймер голосования (опциональный обратный отсчёт)
- Кастомные колоды (размеры футболок?)
- Звуковые эффекты (опционально)
- Интеграция с Jira
Ключевые выводы 🧠
1. Делай то, что нужно тебе
Хватит ждать "идеальный" инструмент. 80% за выходные лучше чем 100% "когда-нибудь".
2. Polling - не зло
WebSocket'ы круты, но polling отлично работает для малых команд. Не усложняй.
3. Маленькие радости важны
Фича с эмодзи заняла 2 часа. Это любимая фича всех. Мелочи делают разницу.
4. Тёмная тема - обязательна
Серьёзно. На дворе 2026-й.
Попробуй! 🎮
Используй, это бесплатно
Итог
Иногда несколько вечеров кодирования экономят месяцы фрустрации. Плюс учишь что-то новое. Win-win.
Если у твоей команды та же боль с планинг покером - делай свой! Сейчас есть крутые фреймворки, бесплатный хостинг и AI-ассистенты. Отговорок нет.
Вопросы? Идеи? Хочешь помочь? Пиши в комментах!
P.S. Да, существуют enterprise-решения. Моё стоило $0, отлично работает для нас и было весело делать. 😄
Top comments (4)
Халявный скрам-покер))
Что-то новенькое😅
Да-да, он бесплатный, жду предложений по улучшению!)
Огонь, сколько по времени заняло? Какой вайбкод инструмент используешь?
2 дня, Figma-make + Trae😇