Архитектура системы

Четыре слоя, каждый из которых можно понять, отладить и заменить независимо от остальных.

⚙️

Backend

Node.js + Express 5. REST API для CRUD-операций, WebSocket для real-time событий. Один процесс, один порт.

🎨

Frontend

Vanilla JS SPA. 32 модуля, ноль фреймворков. CSS-переменные для тем. Работает без сборки.

Real-time

WebSocket для сообщений и событий. Yjs для CRDT-синхронизации документов. Конфликтов при совместном редактировании нет.

🗄️

Database

SQLite в WAL mode. Один файл, встроен в процесс, нулевая латентность на чтение. Бэкап -- копия файла.

Каждый слой отдельно

Backend: Node.js + Express 5

Серверная часть b8q -- это один Node.js процесс на Express 5. Выбор Express 5 (а не 4) обусловлен нативной поддержкой async/await в обработчиках маршрутов. Ошибки в async-хендлерах автоматически ловятся middleware, не нужны обёртки вроде express-async-errors. Это упрощает код и убирает целый класс багов с unhandled promise rejection.

API построен по REST-принципам: каждый ресурс (пользователи, чаты, сообщения, документы, файлы, доски) имеет стандартные CRUD-эндпоинты. Для real-time событий параллельно работает WebSocket-сервер на том же порту. Клиент получает данные через REST при загрузке страницы и подписывается на WebSocket для получения обновлений в реальном времени.

Весь сервер запускается одной командой: node server.js. Нет Docker-зависимостей, нет внешних сервисов (кроме опционального TURN-сервера для звонков). Это упрощает self-hosted деплой до минимума: скопировал файлы, установил зависимости через npm, запустил. Для production рекомендуется PM2 или systemd, но и без них сервер работает стабильно.

Middleware-цепочка минимальна: CORS, JSON body parser, JWT-проверка, rate limiter. Каждый middleware делает одну вещь и не трогает остальное. Логирование -- через console с timestamp, без тяжёлых logging-фреймворков. В production логи перенаправляются в файл или syslog через стандартный pipe.

  • Express 5 с нативным async/await
  • REST API + WebSocket на одном порту
  • Запуск одной командой, без Docker
  • Минимальная middleware-цепочка
⚙️

Frontend: Vanilla JS SPA

Фронтенд b8q -- это SPA на чистом JavaScript. Без React, без Vue, без Angular. 32 модуля, каждый из которых отвечает за конкретный кусок интерфейса: ChatModule, CallModule, DocumentEditor, KanbanBoard, FileManager и так далее. Модули загружаются через ES-модули и регистрируются в центральном роутере.

Такой подход выбран осознанно. Без фреймворка размер бандла на порядок меньше: весь JavaScript-код приложения -- это десятки килобайт, а не мегабайты. Страница загружается мгновенно. Нет виртуального DOM, нет реактивной системы, нет diffing-алгоритма -- работа с DOM прямая, через querySelector и createElement. Для 90% задач этого достаточно.

Стилизация построена на CSS-переменных. Шесть предустановленных тем переключаются сменой набора переменных на :root. Пользователь может настроить акцентный цвет, и вся цветовая схема пересчитается автоматически. Никакого CSS-in-JS, никакого Tailwind -- обычные CSS-файлы с понятной структурой.

Сборка не нужна. Код работает напрямую в браузере через <script type="module">. На production файлы можно минифицировать через terser, но это опционально. Отладка -- через DevTools браузера, без source maps, без webpack. Каждый файл -- это модуль, и его можно открыть, прочитать и понять.

  • Vanilla JS, 32 модуля, ноль фреймворков
  • ES-модули, нет этапа сборки
  • CSS-переменные для 6 тем + кастомные цвета
  • Размер бандла на порядок меньше фреймворков
🎨

Real-time: WebSocket + Yjs

В b8q два канала real-time коммуникации. Первый -- WebSocket для системных событий: новые сообщения, typing indicators, статусы прочтения, обновления канбан-досок, уведомления о файлах. Клиент открывает одно WebSocket-соединение при авторизации и держит его открытым на протяжении всей сессии. При разрыве -- автоматический реконнект с экспоненциальным backoff.

Второй канал -- Yjs для совместного редактирования документов. Yjs -- это CRDT-библиотека (Conflict-free Replicated Data Type). Она гарантирует, что при одновременном редактировании одного документа несколькими пользователями все правки корректно сольются без конфликтов. Нет "победил последний, кто сохранил" -- каждая операция коммутативна и идемпотентна.

Синхронизация Yjs работает поверх WebSocket. Когда пользователь открывает документ, клиент запрашивает текущее состояние и подписывается на обновления. Каждое нажатие клавиши транслируется как операция -- вставка символа в позицию N. Другие клиенты применяют эту операцию к своей копии документа. Результат идентичен на всех устройствах, даже если оба пользователя печатали в одно и то же место.

Производительность Yjs масштабируется линейно с количеством операций. Документ с тысячами правок открывается за десятки миллисекунд. Для крупных документов Yjs использует компактное бинарное представление -- история изменений сжимается и занимает минимум памяти.

  • WebSocket для всех real-time событий
  • Автоматический реконнект с backoff
  • Yjs CRDT -- бесконфликтное совместное редактирование
  • Линейная масштабируемость по количеству операций

WebRTC: P2P-звонки

Звонки в b8q реализованы через WebRTC -- стандарт W3C для peer-to-peer аудио/видео в браузере. Медиапотоки идут напрямую между участниками, серверу передаётся только сигнализация (offer/answer/ICE candidates) через WebSocket. Это минимальная задержка и отсутствие нагрузки на сервер при передаче медиа.

Для установки соединения используется ICE framework. Сначала клиенты пытаются установить прямое соединение через STUN-серверы (определение публичного IP и порта). Если прямое соединение невозможно (симметричный NAT, корпоративный файрвол), трафик идёт через TURN-relay. b8q поддерживает настройку кастомных STUN/TURN серверов в конфигурации.

Видео передаётся с адаптивным качеством. Клиент мониторит пропускную способность соединения через RTCPeerConnection.getStats() и динамически переключает разрешение: 720p при нормальном канале, 480p при слабом, 1080p при хорошем. Переключение происходит без разрыва звонка -- просто меняется constraint на видеодорожке.

Групповые звонки на 2-5 участников работают через mesh-топологию: каждый участник устанавливает P2P-соединение с каждым. Для 5 участников это 10 соединений. Mesh-архитектура не требует медиасервера (SFU/MCU), что упрощает деплой, но ограничивает масштаб. Для большинства рабочих созвонов 5 человек -- достаточный потолок.

  • WebRTC peer-to-peer, без медиасервера
  • ICE: STUN для NAT traversal, TURN как fallback
  • Адаптивный битрейт 480p / 720p / 1080p
  • Mesh-топология для групповых звонков
📹

База данных: SQLite + WAL

Почему SQLite, а не PostgreSQL или MySQL? Потому что для self-hosted мессенджера на одном сервере SQLite -- оптимальный выбор. Нет отдельного процесса БД, нет сетевых вызовов, нет конфигурации пулов соединений. SQLite встроен в процесс Node.js через better-sqlite3 и работает как библиотека. Запрос к базе -- это вызов функции, а не сетевой roundtrip.

WAL mode (Write-Ahead Logging) -- ключевая настройка. В этом режиме читатели и писатели не блокируют друг друга. Пока один запрос записывает данные, другие продолжают читать без ожидания. Для мессенджера это критично: сотни SELECT-запросов на чтение истории чатов выполняются параллельно, не мешая записи новых сообщений.

Производительность SQLite в WAL mode на типичных нагрузках мессенджера -- десятки тысяч операций в секунду. Для команды до нескольких сотен человек это с большим запасом. Вся база данных -- один файл на диске. Бэкап -- cp database.db database.db.backup. Миграции -- SQL-файлы, которые выполняются при запуске сервера.

Схема базы нормализована: users, chats, messages, documents, files, boards, cards. Индексы на часто запрашиваемых полях (chat_id, created_at, user_id). FTS5-расширение используется для полнотекстового поиска по сообщениям. Всё это работает из коробки, без установки расширений -- FTS5 встроен в стандартную сборку SQLite.

  • SQLite встроен в процесс, нет сетевых вызовов
  • WAL mode: читатели не блокируют писателей
  • Один файл БД, бэкап -- копия файла
  • FTS5 для полнотекстового поиска
  • Десятки тысяч операций в секунду
🗄️

AI: Gemini + Rule-based fallback

AI-ассистент в b8q подключается к Google Gemini через REST API. Клиент отправляет сообщение в чат, сервер формирует prompt с контекстом (история диалога, системная инструкция) и отправляет запрос к Gemini. Ответ модели возвращается пользователю как обычное сообщение в чате.

Архитектура AI-модуля предусматривает отказоустойчивость. Если API Gemini недоступен (таймаут, ошибка квоты, сетевые проблемы), срабатывает rule-based fallback. Это набор предопределённых паттернов и ответов для типовых запросов: помощь по интерфейсу, базовые команды, FAQ. Не полноценная замена LLM, но достаточно, чтобы ассистент не "молчал" при проблемах с внешним API.

Промпт-инжиниринг реализован на сервере. Клиент отправляет только текст пользователя, сервер добавляет системную инструкцию и историю последних сообщений. Это позволяет контролировать поведение модели централизованно -- администратор может изменить системный prompt без обновления клиентского кода.

Для организаций с жёсткими требованиями к данным AI-модуль можно полностью отключить в конфигурации сервера. Ни один запрос не уйдёт во внешний сервис. Это критично для компаний, которые работают с персональными данными, финансовой информацией или коммерческой тайной.

  • Google Gemini через REST API
  • Rule-based fallback при недоступности LLM
  • Серверный prompt engineering
  • Полное отключение AI для чувствительных данных
🤖

Безопасность: JWT + bcrypt + Rate Limiting

Авторизация в b8q построена на JWT (JSON Web Tokens). При логине сервер проверяет пароль, генерирует JWT с payload (user_id, role) и подписывает его секретным ключом. Токен передаётся клиенту и используется во всех последующих запросах в заголовке Authorization. Срок жизни токена настраивается в конфигурации.

Пароли хранятся в базе как bcrypt-хеши. bcrypt специально разработан для хеширования паролей: он медленный (cost factor настраивается), устойчив к rainbow tables (salt встроен в хеш) и давно проверен индустрией. Даже при утечке базы данных восстановить пароли из bcrypt-хешей практически невозможно при адекватном cost factor.

Rate limiting защищает от brute-force атак на авторизацию и от DoS на API. Ограничения настраиваются per-endpoint: для логина -- жёстче, для чтения сообщений -- мягче. При превышении лимита сервер возвращает 429 Too Many Requests. Для self-hosted установок администратор может настроить пороги под свою нагрузку.

WebSocket-соединения проверяются при установке: клиент передаёт JWT при handshake, сервер верифицирует подпись и извлекает user_id. Неавторизованные соединения отклоняются до передачи данных. Вся коммуникация идёт через HTTPS/WSS в production -- TLS обеспечивается reverse proxy (nginx, Caddy).

  • JWT для stateless-авторизации
  • bcrypt для хеширования паролей
  • Rate limiting per-endpoint
  • WebSocket-авторизация при handshake
  • HTTPS/WSS через reverse proxy
🔐

Развитие проекта

Ключевые этапы разработки b8q -- от первого прототипа до полноценной платформы.

Q3 2024

Прототип мессенджера

Первая версия: чат на WebSocket, авторизация по JWT, SQLite в качестве хранилища. Базовый UI на Vanilla JS. Проверка гипотезы: можно ли собрать рабочий мессенджер без фреймворков.

Q4 2024

Звонки и документы

Интеграция WebRTC для P2P-звонков. Три типа редакторов документов: Markdown, Rich Text (Quill), таблицы (jspreadsheet). Добавлен Yjs для совместного редактирования в реальном времени.

Q1 2025

Канбан, облако, AI

Канбан-доски с drag & drop. Облачное хранилище с превью файлов. AI-ассистент на базе Gemini. Групповые звонки до 5 участников. PWA-поддержка для мобильных устройств.

Q2 2025

Темы и кастомизация

Шесть цветовых тем. Настройка акцентных цветов. White-label режим для корпоративного брендинга. Импорт файлов .docx, .xlsx, .csv. Голосовые сообщения.

Q3 2025

Self-hosted и стабилизация

Документация для self-hosted деплоя. Picture-in-Picture для звонков. Скриншеринг. Оптимизация производительности SQLite и WebSocket. Закрытая бета-версия.

2026

Публичный запуск

Открытая регистрация. Облачная версия наряду с self-hosted. Расширение API для интеграций. Планы по E2E-шифрованию и федерации между серверами.

32
JS-модуля
0
UI-фреймворков
1
файл БД
P2P
архитектура звонков

Хотите пощупать вживую?

Лучший способ оценить архитектуру — развернуть и посмотреть. 5 минут от git clone до первого сообщения.

Запросить демо Безопасность