Modern real‑time web chat | Современный веб‑чат в реальном времени
Active development / Активная разработка
English · Русский
LocalWebChat is a full‑stack real‑time chat featuring public & private conversations, media (image / video / audio) with detection & audio duration, edit, soft delete placeholder, pinning, read receipts, presence (online + last activity), profile customization (avatar, banner, bio), dark/light theme, scroll + anchor restoration and a virtualized dynamic list (react-window). Frontend follows Feature‑Sliced Design (app / processes / pages / widgets / features / entities / shared). State is split into small isolated Zustand stores; React Query handles server cache.
- Real‑time messaging (Socket.IO)
- Public (general) & private chats
- Optimistic send (pending → finalized / failed)
- Media: image / video / audio (duration extraction for audio)
- Edit, soft delete (placeholder retained), pin message
- Read receipts & unread counters
- Presence: online / offline + last activity timestamp
- Virtualized list (react-window) with dynamic height cache
- Scroll & anchor restoration per chat key
- Profile: avatar crop, banner, description
- Dark / light mode (prefers-color-scheme)
- Validation & rate limiting
- Security hardening (CSP, sanitization, JWT, upload processing)
Frontend: React, Vite, Tailwind, Zustand, TanStack Query, react-window, framer-motion, date-fns.
Backend: Node.js, Express, MongoDB/Mongoose, Socket.IO, Multer, Sharp, JWT, bcrypt, express-validator.
Security: helmet, express-rate-limit, xss-clean, express-mongo-sanitize, compression.
app
· processes
· pages
· widgets
· features
· entities
· shared
chatStore
: selected user/chat meta, unread countersmessagesStore
: message lists, pending map, per-chat view (scroll anchor)
- Optimistic temp message appended (client id)
- Server response replaces with persisted message (real id)
- On error mark failed (UI hint / retry path)
Key: general
or private:<userId>
→ persist { scrollTop, anchorId, atBottom, ts }
to restore context & keep anchor stable while new messages stream.
Message fields:
_id, sender, receiver, isPrivate, content,
mediaUrl?, mediaType?, audioDuration?,
isPinned?, readBy[], isDeleted?,
createdAt, updatedAt
9. REST API (base: http://localhost:5000/api)
Auth: POST /auth/register
, /auth/login
, POST /auth/logout
, GET/PUT /auth/profile
, GET /auth/users/:id
, GET /auth/me
Messages: GET /messages
, POST /messages
, PUT /messages/:id
, DELETE /messages/:id
(soft), POST /messages/:id/read
, POST /messages/:id/pin
Status: GET /status/:userId
, PUT /status
, POST /status/activity
Chats: GET /chats
user_connected, users_online, user_status_changed,
join_room, message_send, message_new,
message_read, message_updated, message_delete (reserved), message_pinned
Frontend .env
:
VITE_API_URL=http://localhost:5000
Backend server/.env
:
PORT=5000
CLIENT_URL=http://localhost:5173
MONGODB_URI=mongodb://localhost:27017/webchat
JWT_SECRET=your_jwt_secret_key
git clone https://github.com/yourusername/local-webchat.git
cd local-webchat
npm install
cd server && npm install && cd ..
Two terminals (or background start):
cd server && npm start &
npm run dev
Open: http://localhost:5173
npm run build
Serve dist/
with any static server (Nginx, serve, etc.) while backend keeps running on PORT
.
frontend: dev | build | preview | lint
backend: start | dev (nodemon)
- helmet (CSP, headers)
- express-rate-limit (auth / message endpoints)
- xss-clean & express-mongo-sanitize
- JWT (Bearer + Socket handshake)
- Multer + Sharp (sanitized uploads & image processing)
- Compression for payload size
- react-window virtualization keeps DOM small
- Dynamic row height cache + targeted
resetAfterIndex
- Scroll anchor restoration prevents jump on new messages
- Fine-grained Zustand slices minimize re-renders
- Fork & create feature branch (
feature/xyz
) - Conventional commits
- PR with context (screens / before-after)
MIT (see LICENSE)
LocalWebChat — полнофункциональный чат в реальном времени: общий и приватные диалоги, медиа (изображения / видео / аудио) с определением типа и длительностью аудио, редактирование, мягкое удаление (placeholder), закрепление, отметки прочтения, статусы (онлайн + последняя активность), профиль (аватар, баннер, описание), тёмная/светлая тема, восстановление скролла и якоря, виртуализированный динамический список. Фронтенд организован по Feature‑Sliced (app / processes / pages / widgets / features / entities / shared). Состояние раздроблено на небольшие Zustand‑сторы + React Query для серверного кэша.
- Мгновенные сообщения (Socket.IO)
- Общий и приватные чаты
- Оптимистическая отправка (pending → finalized / failed)
- Медиа: изображение / видео / аудио (извлечение длительности аудио)
- Редактирование, мягкое удаление (плейсхолдер), закрепление
- Отметки прочтения и счётчики непрочитанного
- Онлайн / офлайн + последняя активность
- Виртуализация списка (react-window) с динамическими высотами
- Восстановление скролла и якоря на чат
- Профиль: обрезка аватара, баннер, описание
- Тёмная / светлая тема (prefers-color-scheme)
- Валидация и rate limit
- Усиленная безопасность (CSP, санация, JWT, обработка загрузок)
Frontend: React, Vite, Tailwind, Zustand, TanStack Query, react-window, framer-motion, date-fns.
Backend: Node.js, Express, MongoDB/Mongoose, Socket.IO, Multer, Sharp, JWT, bcrypt, express-validator.
Security: helmet, express-rate-limit, xss-clean, express-mongo-sanitize, compression.
app
· processes
· pages
· widgets
· features
· entities
· shared
chatStore
: выбранный пользователь / мета, непрочитанныеmessagesStore
: списки сообщений, pending, представление чата (якорь скролла)
- Оптимистическое временное (client id)
- Ответ сервера замещает (persisted id)
- При ошибке пометка failed (UI / retry)
Ключ: general
или private:<userId>
→ сохраняем { scrollTop, anchorId, atBottom, ts }
для восстановления позиции и стабильного якоря при поступлении новых сообщений.
_id, sender, receiver, isPrivate, content,
mediaUrl?, mediaType?, audioDuration?,
isPinned?, readBy[], isDeleted?,
createdAt, updatedAt
9. REST API (база: http://localhost:5000/api)
Auth: POST /auth/register
, /auth/login
, POST /auth/logout
, GET/PUT /auth/profile
, GET /auth/users/:id
, GET /auth/me
Messages: GET /messages
, POST /messages
, PUT /messages/:id
, DELETE /messages/:id
(soft), POST /messages/:id/read
, POST /messages/:id/pin
Status: GET /status/:userId
, PUT /status
, POST /status/activity
Chats: GET /chats
user_connected, users_online, user_status_changed,
join_room, message_send, message_new,
message_read, message_updated, message_delete (reserved), message_pinned
Frontend .env
:
VITE_API_URL=http://localhost:5000
Backend server/.env
:
PORT=5000
CLIENT_URL=http://localhost:5173
MONGODB_URI=mongodb://localhost:27017/webchat
JWT_SECRET=your_jwt_secret_key
git clone https://github.com/yourusername/local-webchat.git
cd local-webchat
npm install
cd server && npm install && cd ..
Два терминала (или запуск бэкенда в фоне):
cd server && npm start &
npm run dev
Открыть: http://localhost:5173
npm run build
Раздавать dist/
любым статичным сервером; backend продолжает работать на PORT
.
frontend: dev | build | preview | lint
backend: start | dev (nodemon)
- helmet (заголовки, CSP)
- express-rate-limit (auth / messages)
- xss-clean & express-mongo-sanitize
- JWT (Bearer + Socket handshake)
- Multer + Sharp (обработка изображений, санация)
- Compression (уменьшение трафика)
- Виртуализация (react-window)
- Кэш динамических высот + точечный reset
- Восстановление якоря без дёргания
- Мелкие Zustand‑сторы → меньше перерисовок
- Fork & ветка (
feature/xyz
) - Conventional commits
- PR с описанием и скриншотами
MIT (см. LICENSE)
Author: @kotru21
MIT © 2025