Architecture Overview
Complete technical architecture documentation for Bellamy Book.
New to the codebase? Start with Understanding the Architecture for a full walkthrough of how the system fits together.
System Architecture
Bellamy Book uses a modular architecture (one API, many workers, polyglot persistence)—not a fine-grained microservices mesh:
- Frontend: React + Vite single-page application (social feed, posts, stories, chat, blogs, etc.)
- Admin Panel: React + CoreUI dashboard (users, content, backup, license, AI agent, tickets, etc.)
- Backend API: Single ASP.NET Core (.NET 8) REST API + SignalR for real-time (notifications, presence)
- Workers: Separate processes—Kafka consumers, RabbitMQ consumers, and one polling worker (media)
- Data stores: PostgreSQL, MongoDB, Redis, Neo4j, Elasticsearch/OpenSearch
- Message brokers: Kafka (events), RabbitMQ (AI blog generation + push notifications)
- Storage: MinIO (or S3-compatible) for media files
Key Distinctions
| Concern | Technology | Used by |
|---|---|---|
| Event streaming | Kafka | GraphWorker, ScoringWorker, TrendingWorker, HashtagWorker, ElasticsearchSyncWorker, InteractionWorker, WebSocketWorker |
| AI blog + push | RabbitMQ | BlogAutoGenerationWorker, WebPushNotificationWorker, ExpoPushNotificationWorker |
| Media processing | Polling (PostgreSQL) | MediaProcessingWorker (polls pending MediaFile records) |
| Real-time chat | SignalR (separate host) | ChatWorker (hub at /hubs/chat; frontend connects to ChatWorker URL) |
| Real-time notifications | SignalR (separate host) | WebSocketWorker (hubs at /hubs/notification, /hubs/onlineusers) |
Architecture Sections
System Architecture
- Understanding the Architecture — Start here for a full walkthrough
- System Overview — Component diagram, request/event flow, databases
- System Architecture Deep Dive — Media, recommendations, push, search, chat/calls, scaling
- Microservices — API surface and worker list
- Data Flow — Request and event sequences
Components
Infrastructure
High-Level Architecture
┌──────────────────┐ ┌──────────────────┐
│ Social Frontend │ │ Admin Panel │
│ (React + Vite) │ │ (React + CoreUI) │
└────────┬─────────┘ └────────┬─────────┘
│ HTTP/REST + SignalR │ HTTP/REST
└───────────┬───────────┘
▼
┌───────────────────────┐
│ Backend API (ASP.NET │
│ Core, .NET 8) │
└───┬──────────────────┘
│
┌────────┼────────┬──────────┬──────────────┐
▼ ▼ ▼ ▼ ▼
┌───────┐ ┌───────┐ ┌─────┐ ┌───────┐ ┌─────────────┐
│Postgre│ │MongoDB│ │Redis│ │ Neo4j │ │Elasticsearch│
└───────┘ └───────┘ └─────┘ └───────┘ └─────────────┘
▲ ▲ ▲ ▲ ▲
│ │ │ │ │
└────────┴────────┴──────────┴──────────────┘
│
┌────────────────┼────────────────┐
▼ ▼ ▼
┌───────┐ ┌─── ───────┐ ┌─────────┐
│ Kafka │ │ RabbitMQ │ │ MinIO │
│(events)│ │(blog+push)│ │(media) │
└───┬───┘ └────┬─────┘ └────┬────┘
│ │ │
▼ ▼ ▼
Workers Blog + Push MediaProcessing
(Kafka) workers Worker (polls DB)
Component Diagram
Layout is top-to-bottom so all labels stay visible. Long names are wrapped with line breaks.
graph TB
subgraph Clients[" "]
FE["Frontend<br/>React + Vite"]
ADMIN["Admin Panel<br/>React + CoreUI"]
end
subgraph API_Layer[" "]
API["Backend API<br/>ASP.NET Core .NET 8"]
end
subgraph Realtime["Real-time (separate processes)"]
WS["WebSocketWorker<br/>SignalR Notification + Presence"]
CHAT["ChatWorker<br/>SignalR Chat hub"]
end
subgraph Data["Data & storage"]
PG[("PostgreSQL")]
MONGO[("MongoDB")]
REDIS[("Redis")]
NEO4J[("Neo4j")]
ES[("Elasticsearch")]
MINIO[("MinIO / S3")]
end
subgraph Kafka_Workers["Kafka workers"]
KAFKA["Kafka"]
INT["InteractionWorker"]
SCORE["ScoringWorker"]
TREND["TrendingWorker"]
GRAPH["GraphWorker"]
HASHTAG["HashtagWorker"]
ELASTIC["ElasticsearchSyncWorker"]
WSNOTIF["WebSocketWorker"]
end
subgraph Rabbit_Workers["RabbitMQ workers"]
RABBIT["RabbitMQ"]
BLOG["BlogAutoGenerationWorker"]
WEBPUSH["WebPushNotificationWorker"]
EXPOPUSH["ExpoPushNotificationWorker"]
end
MEDIA["MediaProcessingWorker<br/>polls PostgreSQL"]
FE --> API
ADMIN --> API
FE --> WS
FE --> CHAT
API --> PG
API --> MONGO
API --> REDIS
API --> ES
API --> KAFKA
API --> RABBIT
KAFKA --> INT
KAFKA --> SCORE
KAFKA --> TREND
KAFKA --> GRAPH
KAFKA --> HASHTAG
KAFKA --> ELASTIC
KAFKA --> WSNOTIF
RABBIT --> BLOG
RABBIT --> WEBPUSH
RABBIT --> EXPOPUSH
MEDIA --> PG
MEDIA --> MINIO
INT --> PG
INT --> REDIS
SCORE --> PG
SCORE --> NEO4J
TREND --> PG
GRAPH --> NEO4J
HASHTAG --> PG
ELASTIC --> ES
BLOG --> PG
WS --> REDIS
CHAT --> MONGO
Note: ChatWorker and WebSocketWorker are separate deployables; the frontend connects to their base URLs for SignalR hubs. MediaProcessingWorker polls the database for pending media (no Kafka). Blog and push workers consume RabbitMQ.
Technology Stack
Frontend
- React 18
- Vite
- Redux Toolkit (or similar state)
- React Router
- Axios
- SignalR client
Backend
- .NET 8
- ASP.NET Core
- Entity Framework Core
- SignalR
- MediatR
- Quartz (scheduled jobs)
Data & search
- PostgreSQL (core data)
- MongoDB (stories, chat, notifications)
- Redis (cache, sessions, rate limiting)
- Neo4j (social graph)
- Elasticsearch/OpenSearch (full-text search)
Infrastructure & messaging
- Kafka (event streaming)
- RabbitMQ (blog generation, push notifications)
- MinIO or S3-compatible storage (media)
- Docker & Docker Compose
Design Principles
- Modular monolith: Single API with clear modules; workers are separate processes.
- Event-driven: Async processing via Kafka (and RabbitMQ for blog/push).
- Polyglot persistence: Right store per use case (relational, document, graph, search, cache).
- Scalability: Stateless API, horizontal worker scaling, database replication where needed.
- Security: JWT, RBAC, license gating, rate limiting, HTTPS.
Learn More
- Understanding the Architecture — Full architecture walkthrough
- System Overview — Diagrams and data flow
- System Architecture Deep Dive — Media, recommendations, push, search, chat, scaling
- Frontend · Backend