Skip to main content

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

ConcernTechnologyUsed by
Event streamingKafkaGraphWorker, ScoringWorker, TrendingWorker, HashtagWorker, ElasticsearchSyncWorker, InteractionWorker, WebSocketWorker
AI blog + pushRabbitMQBlogAutoGenerationWorker, WebPushNotificationWorker, ExpoPushNotificationWorker
Media processingPolling (PostgreSQL)MediaProcessingWorker (polls pending MediaFile records)
Real-time chatSignalR (separate host)ChatWorker (hub at /hubs/chat; frontend connects to ChatWorker URL)
Real-time notificationsSignalR (separate host)WebSocketWorker (hubs at /hubs/notification, /hubs/onlineusers)

Architecture Sections

System Architecture

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)
  • 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

  1. Modular monolith: Single API with clear modules; workers are separate processes.
  2. Event-driven: Async processing via Kafka (and RabbitMQ for blog/push).
  3. Polyglot persistence: Right store per use case (relational, document, graph, search, cache).
  4. Scalability: Stateless API, horizontal worker scaling, database replication where needed.
  5. Security: JWT, RBAC, license gating, rate limiting, HTTPS.

Learn More