Добей фразу — браузерная party-game для компании друзей. Игроки придумывают начала фраз, добивают чужие фразы смешными концовками, голосуют за лучшие шутки и проходят несколько быстрых раундов.
Проект сделан как лёгкая онлайн-игра без регистрации: создал лобби, отправил друзьям код или ссылку, дождался игроков и запустил раунд.
- главное меню игры;
- создание лобби с настройками;
- вход по коду;
- вход по invite-ссылке;
- список открытых лобби;
- realtime-игра через Socket.IO;
- короткие коды комнат;
- восстановление игрока после обновления страницы через
sessionId; - ожидание игроков в лобби;
- 5-секундный отсчёт перед стартом игры;
- раунды с таймерами;
- ручные и автоматические начала фраз;
- режимы:
- каждый добивает чужую фразу;
- все добивают одну и ту же фразу;
- голосование за шутки;
- запрет голосовать за свою концовку;
- итоги раунда;
- история лучших шуток;
- раскрывающийся список лучших шуток;
- финальный экран с очками и титулами;
- копирование кода, ссылки и шуток;
- UI-звуки из папки
public/sounds; - обработка несуществующих лобби и неправильных ссылок.
- Игрок открывает сайт.
- Создаёт игру или входит в существующую.
- Хост создаёт лобби и отправляет друзьям код или ссылку.
- Игроки заходят в лобби.
- Хост запускает игру.
- Перед стартом появляется обратный отсчёт 5 секунд.
- Игроки пишут начала фраз.
- Затем каждый добивает чужую фразу.
- Все голосуют за самую смешную концовку.
- После раунда показываются итоги и лучшие шутки.
- Хост запускает следующий раунд или завершает игру.
- Node.js
- Express
- Socket.IO
- HTML
- CSS
- Vanilla JavaScript
Данные комнат хранятся в памяти сервера. База данных пока не используется.
.
├── public/
│ ├── index.html
│ ├── style.css
│ ├── client.js
│ └── sounds/
│ ├── ui-click.mp3
│ ├── copy.mp3
│ ├── join.mp3
│ ├── leave.mp3
│ ├── reveal.mp3
│ ├── vote.mp3
│ ├── win.mp3
│ └── error.mp3
├── server.js
├── package.json
├── README.md
└── _redirects
Клиент ожидает звуки в папке:
public/sounds/
Нужные файлы:
ui-click.mp3
copy.mp3
join.mp3
leave.mp3
reveal.mp3
vote.mp3
win.mp3
error.mp3
Если какого-то файла нет, браузер просто не сможет его проиграть. Поэтому перед деплоем лучше проверить, что все файлы лежат в public/sounds.
Проверка локально:
http://localhost:3000/sounds/ui-click.mp3
http://localhost:3000/sounds/copy.mp3
Установить зависимости:
npm installЗапустить сервер:
npm startОткрыть игру:
http://localhost:3000
Для теста открой несколько вкладок браузера:
- В первой вкладке создай игру.
- Во второй вкладке зайди по коду или ссылке.
- Запусти игру.
- Пройди полный раунд: начало → концовка → раскрытие → голосование → итоги.
Перед пушем можно быстро проверить JS-файлы:
node --check public/client.js
node --check server.js/ главное меню
/create создание игры / настройки лобби
/join-game меню входа в игру
/join-code вход по коду
/lobbies открытые лобби
/lobby/:code ожидание игроков в лобби
/join/:code invite-ссылка для входа в лобби
/game/:code активная игра
/game-started экран, если игра уже началась
/lobby-not-found экран, если лобби не найдено
Пока лобби находится в состоянии waiting, игроки могут присоединяться по коду или invite-ссылке.
После старта игры новые игроки уже не добавляются в комнату. Если новый пользователь откроет ссылку на уже начавшуюся игру, он увидит экран:
Игра уже началась
Новые игроки больше не могут присоединиться к этому лобби.
Игроки, которые уже были в сессии, остаются в игре и могут восстановиться после обновления страницы.
Хост может настроить:
- количество раундов;
- таймер на начало фразы;
- таймер на концовку;
- таймер голосования;
- режим начал:
- игроки сами кидают начала;
- игра предлагает начала автоматически;
- режим раздачи:
- каждый добивает чужую фразу;
- все добивают одну и ту же фразу;
- максимум игроков;
- скрытие авторов до итогов раунда;
- звуки;
- показ комнаты в списке открытых лобби.
Основные состояния комнаты:
waiting лобби создано, игроки ожидаются
starting обратный отсчёт перед стартом
prompting игроки пишут начала фраз
answering игроки добивают фразы
revealing готовые шутки показаны
voting голосование
scoreboard итоги раунда
finished финал игры
В public/client.js указан backend:
const BACKEND_URL =
location.hostname === "localhost" || location.hostname === "127.0.0.1"
? "http://localhost:3000"
: "https://textic-chat.onrender.com";Для локального запуска используется:
http://localhost:3000
Для продакшена используется Render URL:
https://textic-chat.onrender.com
Если backend переедет на другой домен, нужно заменить продакшен-URL в public/client.js.
В server.js нужно разрешить домены, с которых будет открываться frontend.
Пример:
const ALLOWED_ORIGINS = [
"http://localhost:3000",
"http://localhost:5173",
"https://exitserial.pages.dev"
];Если деплоишь frontend на другой домен, добавь его в ALLOWED_ORIGINS.
Самый простой вариант для MVP:
- Залить проект на GitHub.
- Создать Web Service на Render.
- Подключить GitHub-репозиторий.
- Build command:
npm install- Start command:
npm start- Открыть Render URL.
Так как Express раздаёт папку public, frontend и backend могут работать с одного сервера.
Можно вынести frontend на Cloudflare Pages, а backend оставить на Render.
В этом случае нужно:
- Задеплоить backend на Render.
- Задеплоить папку
publicна Cloudflare Pages. - В
public/client.jsуказать правильный Render URL. - В
server.jsдобавить домен Cloudflare Pages вALLOWED_ORIGINS.
- Комнаты хранятся только в памяти сервера.
- После перезапуска сервера активные комнаты пропадут.
- Нет базы данных.
- Нет авторизации.
- Нет постоянной истории игр.
- Одна копия сервера должна обслуживать одну игровую сессию realtime-комнат.
- Для продакшена с большим количеством игроков позже лучше добавить Redis/Postgres и нормальное хранение сессий.
node --check public/client.js
node --check server.jsПотом вручную:
- создать лобби;
- войти вторым игроком;
- скопировать код;
- скопировать ссылку;
- открыть invite-ссылку;
- запустить игру;
- проверить 5-секундный countdown;
- написать начало;
- написать концовку;
- проверить, что текст в поле не исчезает при обновлении прогресса;
- пройти голосование;
- проверить итоги раунда;
- проверить раскрывающийся список лучших шуток;
- проверить финал игры;
- проверить выход из комнаты;
- проверить удаление лобби;
- открыть несуществующее лобби и убедиться, что показывается экран ошибки.
Игра должна звучать дружелюбно, понятно и немного смешно.
Главное — не мешать игроку быстро понять, что делать.
Подходящие слова:
лобби
код
ссылка
игроки
раунд
начало
концовка
шутка
голосование
итоги
Не стоит перегружать интерфейс длинными шутками, токсичным юмором или непонятными формулировками. Кнопки и ошибки должны быть максимально ясными.
- постоянная история игр;
- база данных;
- авторизация;
- кастомные наборы тем;
- больше готовых начал фраз;
- роли игроков;
- режим зрителя;
- QR-код для входа в лобби;
- мобильная оптимизация под party-mode;
- админка для модерации авто-фраз;
- share-картинки с лучшими шутками.