Кейс · Бэкенд · TypeScript

poll-board: опросы в реальном времени

Сервис опросов и голосований на TypeScript без runtime-зависимостей. Опрос на 2–10 вариантов со сроком жизни, ссылка, результаты растут у всех в реальном времени по SSE или WebSocket (кадры WebSocket разобраны вручную). Повторные голоса и накрутка режутся подписанным токеном и хэшем IP; экспорт CSV защищён от формульных ячеек.

  • TypeScript
  • Node.js 24
  • SSE
  • WebSocket
  • fast-check
  • vitest
  • axe
  • Docker
  • GitHub Actions

01 · Как выглядит

Скриншоты

Скриншот проекта «poll-board: опросы в реальном времени» на экране 1280 пикселей
Десктоп, 1280 px
Скриншот проекта «poll-board: опросы в реальном времени» на экране телефона, 390 пикселей
Телефон, 390 px

02 · О проекте

Что это и зачем

Сервис опросов и голосований на TypeScript без runtime-зависимостей. Опрос на 2–10 вариантов со сроком жизни, ссылка, результаты растут у всех в реальном времени по SSE или WebSocket (кадры WebSocket разобраны вручную). Повторные голоса и накрутка режутся подписанным токеном и хэшем IP; экспорт CSV защищён от формульных ячеек.

Ограничения

Лимиты частоты и счётчики потоков живут в памяти одного процесса.

Автор опроса не аутентифицируется, только ключ закрытия.

Токен в cookie не защищает от человека, который чистит cookie и меняет IP.

Образ 244 МБ на node:24-alpine; проект работает на небольшом VPS с демо-данными.

Что внутри

  • SSE и WebSocket на одном потоке событий; порядок монотонен: seq растёт на 1, closed последним
  • 43 теста; fast-check: сумма голосов равна числу принятых бюллетеней, кадры WebSocket при любой нарезке потока
  • 200 запросов (20 параллельно): p50 6,4 мс, p95 21,7 мс; около 25 МиБ RAM
  • Запуск read-only, cap-drop ALL, uid 10001; axe 0 в Firefox на 390 и 1280

03 · Как запустить

Запуск одной командой

git clone <репозиторий по запросу> poll-board
cd poll-board
npm ci && npm run build && npm start

04 · Код

Репозиторий приватный

Исходники лежат в приватном репозитории. Напишите в Telegram, открою доступ.

Запросить код