WebSocket Notifications System (SocialVibes)
This document describes the WebSocket + toast notification system added to SocialVibes, how to use it, how to extend it, and where to modify the code when scaling.
Overview
The system consists of:
- FastAPI WebSocket server (backend) for real‑time push.
- REST publish endpoint for sending toasts.
- Optional shared secret auth for partner tools/CLI.
- React Native client for WebSocket receive + toast UI.
- Local per‑user notification history (AsyncStorage).
- Optional Redis pub/sub mode for future horizontal scaling.
Backend Architecture
Key Files
fastapi/app/domains/websocket/
├── manager.py # Connection manager + optional Redis pub/sub
├── routes.py # /ws (socket) + /ws/toast (publish) + /ws/history
└── schemas.py # Pydantic payload models
WebSocket Endpoint
- URL:
ws://<host>/api/v1/ws?token=<FIREBASE_ID_TOKEN> - Requires Firebase token (auth is enforced for clients).
Publish Endpoint
- URL:
POST http://<host>/api/v1/ws/toast - Accepts JSON payload (see schema below)
- Auth options:
- JWT (Authorization: Bearer
) - Shared secret header (X‑SV‑KEY:
)
Payload Schema
{
"title": "Minecraft Turnering",
"teaser": "Starter om 10 minutter i Hal C",
"description": "Tryk her for detaljer!",
"image_url": "https://...",
"action_url": "sv://event/123",
"action_label": "Se aktivitet"
}
Config Settings (fastapi/.env)
WS_REDIS_ENABLED=false
WS_CONNECTION_THRESHOLD=100
WS_REDIS_CHANNEL=sv:ws:broadcast
WS_HISTORY_SIZE=0
WS_PUBLISH_SECRET=your-shared-secret
WS_PUBLISH_HEADER=X-SV-KEY
Notification History
Currently per‑user history is stored locally on the device using AsyncStorage. This means:
Each user sees their own notifications Persistent across app restarts No backend load Not shared across devices (yet)
If you want server‑side persistent history later, see “Scaling & Growth” below.
Frontend Architecture
WebSocket Client
frontend/src/core/ws/
├── types.ts # Shared types (ToastPayload etc.)
├── useWebSocket.ts # Native WS connection logic
└── WebSocketProvider.tsx # Context provider + useWSEvent
Toast UI
frontend/src/core/components/toast/
├── EventToast.tsx # Small banner toast
└── EventDetailModal.tsx # Large modal view
Notification History UI
Header + Bell
Partner / CLI Publishing
To allow external partners or internal tools to publish without JWT, a shared secret is supported.
Header (default)
Set in fastapi/.env:
CLI Tool
Location:
Example:
dotnet run --project sv-cli -- toast \
--url http://192.168.1.108:8080/api/v1 \
--title "Minecraft Turnering" \
--teaser "Starter om 10 minutter i Hal C" \
--description "Tryk her for detaljer!" \
--image-url "https://..." \
--action-url "sv://event/123" \
--action-label "Se aktivitet" \
--secret your-shared-secret
Supported env vars:
Scaling & Growth
1) Horizontal Scaling (multiple instances)
Enable Redis broadcast mode:
All instances publish to Redis, and each instance forwards to its local connections.
2) Per‑user server history (future)
Add a DB table:
Modify:
fastapi/app/domains/websocket/routes.py- write to DB on publish
- new
/ws/historythat filters byuser_id - Frontend: fetch history from API rather than AsyncStorage
3) More event types
Steps:
- Add to backend
EventTypeenum inschemas.py - Add new payload schema
- Add matching interface in
frontend/src/core/ws/types.ts - Add UI handler in
WebSocketProvideror a new component
Summary of Where to Modify
| Goal | File(s) |
|---|---|
| Change toast payload | fastapi/app/domains/websocket/schemas.py + frontend/src/core/ws/types.ts |
| Adjust toast UI | frontend/src/core/components/toast/EventToast.tsx |
| Adjust modal UI | frontend/src/core/components/toast/EventDetailModal.tsx |
| Add new event types | schemas.py, types.ts, new UI handler |
| Change auth strategy | fastapi/app/domains/websocket/routes.py |
| Add persistent history | new DB layer + /ws/history endpoint |
| CLI behavior | /sv-cli/Program.cs |
Minimal + Scalable Summary
- Minimal now: small set of files, no heavy dependencies, fast local WS.
- Scalable later: Redis pub/sub + optional DB history + new event types.