8000 GitHub - CodingF0X/Chat-app: Web based chat application built on top of Nest.js and React.js using GraphQL and Apollo Client for Real time data update
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Web based chat application built on top of Nest.js and React.js using GraphQL and Apollo Client for Real time data update

Notifications You must be signed in to change notification settings

CodingF0X/Chat-app

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 

Repository files navigation

Chat Web Application

In this project, I demonstrate how to build a scalable, maintainable chat application using NestJS with a Clean-Architecture mindset. The goal is to show how Nest’s module system, built-in dependency injection, and clear separation of concerns let you compose robust real-time features with GraphQL and WebSockets.


Application Functionality

  • Real-time messaging
    Users can send and receive text messages in real time via GraphQL subscriptions over WebSockets (using the graphql-ws package).
  • GraphQL API
    I chose GraphQL over REST because:
    • Single endpoint: simplifies client-server communication.
    • Type safety: strong typing of queries/mutations which will make sure fewer runtime errors.
    • Subscriptions: first-class support for real-time data push.
  • Authentication & Authorization
    Users sign in via a local (email/password) strategy, receive a JWT in an HTTP-only cookie, and subsequent requests (including GraphQL and WebSocket connections) are guarded by JWT-based guards.

Architecture Design

I follow a four-layer Clean Architecture:

  1. Domain Layer
    • Entities (User, Chat, Message, JwtPayload)
  2. Application Layer (Use Cases)
    • Services (UsersService, ChatsService, MessagesService, AuthService) encapsulate business rules and logic (e.g. hashing passwords, publishing events, composing MongoDB aggregation pipelines are a few to mention).
  3. Interface Adapters
    • Resolvers (GraphQL) and Controllers (REST endpoints for file upload, auth functionality and count APIs).
    • Guards (JwtAuthGuard, GqlAuthGuard, LocalAuthGuard) and Passport Strategies (JwtStrategy, LocalStrategy) translate framework inputs into calls to the Application layer to authenticate and authorize the user to make the right API call.
  4. Infrastructure Layer
    • Nest Modules (UsersModule, ChatsModule, MessagesModule, AuthModule) wire everything together.
    • Repositories (UserRepository, ChatRepository) extend an abstract MongoDB repository; Mongoose Schemas (UserDocument, ChatDocument, MessageDocument) define persistence models.
    • Third-party services: AWS S3 for profile image storage (S3Service), in-memory PubSub for GraphQL subscriptions, and Nest’s JwtModule/ConfigService for secrets management.

This separation makes sure that the core logic remains framework-agnostic and testable, while NestJS simply wires the pieces using dependency injection.

UML Class Diagram

Chat Module

Chat-class-uml

User Module

mmea

Auth Module

auth-class-uml

---


Directed Acyclic Graph (DAG)


A directed acyclic graph (DAG) is a conceptual representation of a series of activities, as per https://hazelcast.com/foundations/distributed-computing/directed-acyclic-graph/

In Nest.js architecture, modules typically are designed in hierarchical structure. This is system works

in layers, ensuring that each module and its components get their dependencies from the closest

injector, be it module-specific or global (Feature or root module).


Nest’s module system ensures that each module is a single unit of responsibility. As modules become dependent on one another, they form a directed acyclic graph (DAG) that paints a clear picture of the application’s architecture.
It is a visualization aids in the following aspects:

  1. Problem diagnosis: Easily identifying which modules might be affected when a single module encounters an issue.

  2. Optimized refactoring: Recognizing which modules can be independently refactored without disturbing the application’s overall functionality.

3.Enhanced scalability: Strategically adding new modules or expanding existing ones based on the current module graph.

DAG in our Chat App: module-deps

Note: This diagram was created using madge with the help of GraphViz




Circular Dependencies

It is the situation where two classes, services or modules depend on each other. So they call each other at once.
In this particular app, i have came across the circular dependency between Chats and Messages modules where they depend on each other in object initialization.

image


In order to solve this issue, Nest.js provides the solution to this issue using Forward reference as per the Nest.js Docs


I utilized this solution in my code:

in Chats Module :

@Module({
  imports: [
    UsersModule,
    MongooseModule.forFeature([
      {
        name: ChatDocument.name,
        schema: ChatSchema,
      },
    ]),
    forwardRef(() => MessagesModule),
  ],
  providers: [ChatsResolver, ChatsService, ChatRepository],
  exports: [ChatRepository, ChatsService],
  controllers: [ChatsController],
})
export class ChatsModule {}

in Messages Module :

@Module({
  imports: [forwardRef(() => ChatsModule), PubSubModule, UsersModule],
  providers: [MessagesResolver, MessagesService],
  controllers: [MessagesController],
})
export class MessagesModule {}



Data Modeling

  • MongoDB / Mongoose

    • AbstractEntity: base schema with _id: ObjectId and createdAt / updatedAt from AbstractEntity.
    • UserDocument → persisted user data (email, hashed password) + User domain entity returned to clients.
    • ChatDocument → each chat has a userId owner, a name, and an array of embedded MessageDocument subdocuments.
    • MessageDocument → stores content, sender (ObjectId), and createdAt; transformed into a Message GraphQL object type on the way out.
  • GraphQL Types & Inputs

    • Object Types (User, Chat, Message) mirror the domain entities.
    • Input Types (CreateUserInput, UpdateUserInput, CreateChatInput, UpdateChatInput, CreateMessageInput) enforce validation via class-validator.
    • Args Types (PaginationArgs, GetMessagesArgs, MessageCreatedArgs) support cursor-style pagination and subscription filters.

    DB worklolad:

    Chat App - Workload

    Conceptual Data Model

Chat App - Conceptual Model


Implementation

Technical Overview

Chat App - Technical Overview

Technologies

Backend

  • Framework: NestJS v11 (modules, DI, pipes, guards, interceptors)
  • API:
    • Apollo GraphQL (@nestjs/graphql, @apollo/server)
    • WebSocket Subscriptions via graphql-ws & graphql-subscriptions
  • Database: MongoDB with Mongoose (@nestjs/mongoose)
  • Auth: Passport.js strategies (local, jwt), JWT in HTTP-only cookies
  • File Storage: AWS S3 (@aws-sdk/client-s3) for user profile images
  • Logging: Pino (nestjs-pino)
  • Validation: class-validator & joi for request payloads
  • Migrations: migrate-mongo
  • Testing: Jest, Supertest

Frontend

  • Framework: React v19, Vite

  • GraphQL Client: Apollo Client (@apollo/client)

  • Real-time: graphql-ws for subscriptions over WebSockets

  • Styling: MUI (Material UI), styled-components

  • Routing: React Router v7

  • State & Caching: Apollo’s in-memory cache, localForage for offline caching

  • Tooling: ESLint, Prettier, GraphQL Codegen

# key NPM scripts to run the server: 

npm run start:dev       # start in watch mode
npm run build            # compile to dist/
npm run test             # run unit tests
npm run test:e2e         # run end-to-end tests

# Key NPM scripts to run the React APP
npm run dev           # start Vite development server
npm run build         # production build
npm run codegen       # generate GraphQL types/hooks

About

Web based chat application built on top of Nest.js and React.js using GraphQL and Apollo Client for Real time data update

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

0