Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
343 changes: 254 additions & 89 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,118 +1,283 @@
`TODO: Add a nice screenshot of the app!`
# StudyBridge

# Cohort XX final project
## Overview

This is the final project for the HackYourFuture curriculum we did as a cohort using the [MERN stack](https://www.mongodb.com/resources/languages/mern-stack) by following the agile methodology with our team and a group of mentors. A quick guide to what we built:
StudyBridge is a full-stack educational platform that connects students and teachers in one ecosystem.
The application is designed to simplify the process of finding a tutor, booking lessons, managing communication, and organizing the learning workflow in real time.

> TODO: Add short description of the app
The platform supports two main user journeys:

`[Click here for the Demo version](TODO: add link)`
- **Student flow** - search for teachers, view profiles, create lesson appointments, communicate with tutors, receive notifications, and join online lessons
- **Teacher flow** - create and manage a professional profile, receive and process appointment requests, communicate with students, manage regular learners, and conduct online lessons

## 1. Setup
In addition, the platform includes moderation flows that help keep content structured and the teacher approval process controlled.

First, to setup all the directories run the following in the main directory:
StudyBridge is built as a modern full-stack application with strong attention to architecture, scalability, and real user interaction. The project combines a React-based client application with a Node.js backend,
real-time features via WebSockets, structured backend layering with CQRS, dependency injection, and TypeScript across the stack.

`npm install`
---

`npm run setup`
## Tech Stack

The first command will install `cypress` and some small libraries needed for running the rest of the commands. The second will go into the `client` and `server` directories and set those up to be ran.
### Core stack
- **MERN**
- **TypeScript**
- **CQRS**
- **Dependency Injection**

In the `client` and `server` directory there are two `.env.example` files. Create a copy and rename that to `.env`. Then follow the instructions in those files to fill in the right values.
### Frontend
- **React**
- **React Router**
- **TanStack Query (React Query)**
- **Zustand**
- **Socket.IO Client**
- **Tailwind CSS**
- **Framer Motion**
- **Axios**

To run the app in dev mode you can run the following command in the main directory:
### Backend
- **Node.js**
- **Express**
- **Socket.IO**
- **MongoDB**
- **Mongoose**
- **InversifyJS**

`npm run dev`
### Tooling
- **ESLint**
- **Prettier**
- **Husky**
- **npm**

## 2. Code structure
---

```
client
├── public
└── src
| └── __tests__
| └── __testUtils__
| └── components
| └── hooks
| └── pages
| └── __tests__
| └── components
| └── util
| index.jsx
cypress
| └── fixtures
| └── integration
| └── plugins
| └── support
server
└── src
└── __tests__
└── __testUtils__
└── controllers
└── db
└── models
└── routes
└── util
index.ts
```
## Full Stack Description

### MERN
StudyBridge follows the **MERN** stack architecture:

- **MongoDB** for storing users, appointments, conversations, messages, notifications, and related entities
- **Express** for building the backend API and request handling
- **React** for the client-side user interface
- **Node.js** as the server runtime

### TypeScript
TypeScript is used across both frontend and backend to ensure strong typing, safer refactoring, and better maintainability. This helps reduce runtime errors and improves developer experience.

### CQRS
The backend uses **CQRS (Command Query Responsibility Segregation)**:

- **Command repositories** are responsible for create, update, and delete operations
- **Query repositories** are responsible for read operations

This separation makes the backend more scalable and keeps business logic organized.

### Dependency Injection
The backend uses **InversifyJS** for dependency injection.
This allows services, repositories, and controllers to stay decoupled and easier to test.

### Real-time communication
**Socket.IO** powers the real-time features of the platform:

- live chat messaging
- typing indicators
- unread message counters
- online presence tracking
- incoming call events
- live notifications

### State management
The frontend clearly separates responsibilities between:

- **React Query** for server state
- **Zustand** for client-side and UI state

This keeps the application predictable and easier to manage as it grows.

---

## Features

### Authentication and authorization
- Student and teacher registration
- Secure login flow
- Access token and refresh token handling
- Protected routes
- Role-based access control
- Session restore and logout flow

### Teacher discovery
- Browse teacher profiles
- View lesson details, pricing, and profile information
- Search and filtering
- Teacher profile editing

### Appointment management
- Create lesson appointments
- Approve or reject lesson requests
- Track appointment statuses
- Manage regular students
- Support recurring weekly schedules

### Real-time chat
- One chat per teacher-student pair
- Real-time messaging
- Typing indicators
- Online presence
- Unread message counters
- Read/unread synchronization

### Notifications
- Real-time notifications for new messages
- Notifications for appointment approval or rejection
- Persistent notifications stored in database
- Mark one as read
- Clear read notifications

### Video calls
- Online lesson calls
- Incoming call popup
- Join links for specific calls
- Teacher-student live communication flow

### Moderation
- Teacher moderation workflow
- Status management
- Restricted moderator routes

### 2.1 Client structure
---

- `public` || public facing client code
- `__tests__` || any `jest` tests for specific components will be in a `__tests__` folder on the same level
- `__testUtils__` || any code that is only being used in the tests is put in the `__testUtils__` folder to separate that away from the rest of the code
- `components` || all of our shared components that are used over multiple pages
- `hooks` || all of our custom hooks
- `pages` || the page components of our app, any routing will go between these components
- `pages/components` || components used specifically on those pages
- `util` || any utility functions that can be used anywhere on the client side
- `main.tsx` || the start point of the client
- `vite.config.ts` || to configure vite
## Screenshots

### 2.2 Cypress structure
### Home page
![Home page](docs/homePage.png)

- `fixtures` || any data/files that `cypress` needs can be placed here
- `integration` || all of our tests are in here, separated in folders based on the pages in our app
- `plugins` || any plugins for our `cypress` configuration can be placed here
- `support` || custom commands and other support files for `cypress` can be placed here
### Teachers list
![Teacher profile](docs/teacherList.png)

### 2.3 Server structure
### Teacher profile
![Teacher profile](docs/teacherPage.png)

- `__tests__` || any `jest` tests for the api endpoints as that is our testing strategy for the backend
- `__testUtils__` || any code that is only being used in the tests is put in the `__testUtils__` folder to separate that away from the rest of the code
- `controllers` || all of our controller functions that interact with the database
- `db` || all of our configuration for the database
- `models` || all of our `mongoose` models will be placed here
- `routes` || code to match up the API with our controllers
- `util` || any utility functions that can be used anywhere on the server side
- `index.ts` || the start point of the server
### Appointments
![Chat page](docs/appointments.png)

## 3. Stack / external libraries
---

The base stack of the app is a MERN stack (Mongoose, Express, React, Node). Next to that we make use of the following extras:
## Architecture

### 3.1 Configuration libraries
StudyBridge is structured as a layered full-stack application.

- `dotenv` || To load the .env variables into the process environment. See [docs](https://www.npmjs.com/package/dotenv)
- `vite` || To bundle our React app and create a static app to host. See [docs](https://vite.dev/)
- `husky` || To run our tests and linter before committing. See [docs](https://typicode.github.io/husky/#/)
- `eslint` || To check our code. We have different configurations for frontend and backend. You can check out the configuration in the `.eslintrc.(c)js` files in the respective `client` and `server` folders. See [docs](https://eslint.org/)
- `prettier` || To automatically format our code. See [docs](https://prettier.io/)
- `concurrently` || To run commands in parallel. See [docs](https://github.com/open-cli-tools/concurrently#readme)
### Frontend architecture
The frontend is built as a React SPA with a modular structure.

For more information on how these work together including the automatic deployment to heroku, have a look at our detailed [DEV](./DEV.md) file.
Main responsibilities are split into:
- **Pages** for route-level UI
- **Components** for reusable UI blocks
- **Features** for domain-specific logic
- **Hooks** for reusable behavior
- **Stores** for client-side state
- **API layer** for backend communication

### 3.2 Client-side libraries
### Backend architecture
The backend is divided into clear layers:

- `@testing-library/*` || We use React Testing Library to write all of our tests. See [docs](https://testing-library.com/docs/react-testing-library/intro/)
- `jest` || To run our tests and coverage. See [docs](https://jestjs.io/)
- `jest-fetch-mock` || To mock out the backend for our testing purposes. See [docs](https://github.com/jefflau/jest-fetch-mock#readme)
- **Controllers** — handle HTTP requests and responses
- **Services** — contain business logic
- **Command repositories** — handle write operations
- **Query repositories** — handle read operations
- **Schemas/models** — define persistence layer
- **Socket handlers** — manage real-time events

This structure helps keep the codebase maintainable and scalable.

---

## Why this project is technically interesting

StudyBridge is more than a simple CRUD application.
It combines several real-world product requirements in one system:

- authentication with refresh flow
- role-based access control
- real-time messaging
- persistent notifications
- appointment approval workflow
- online presence tracking
- video call integration
- CQRS-based backend architecture
- dependency injection

The project demonstrates how to build a production-style platform with real-time communication and maintainable architecture.

---

## Project Goal

The goal of StudyBridge is to provide a convenient and structured environment where:

- students can quickly find suitable teachers
- teachers can present their expertise and manage their work
- both sides can communicate smoothly in one application

The platform is designed to reduce friction in online learning by combining search, booking, messaging, and lesson management in a single place.

---

## Folder Structure

### Client
```bash
client/
src/
api/
components/
features/
hooks/
layouts/
pages/
router/
store/
types/
util/

server/
src/
composition/
controllers/
db/
repositories/
commandRepositories/
queryRepositories/
routes/
services/
socket/
types/
utils/
validation/
```
## How to run locally

## Clone repository
```bash
git clone <your-repository-url>
cd StudyBridge
```

## Install dependencies
```bash
npm install
cd client && npm install
cd ../server && npm install
```
## Start the development servers

```bash
cd client
npm run dev
```
## Open the application
```bash
http://localhost:5173
```

### 3.3 Server-side libraries

- `nodemon` || To automatically restart the server when in development mode. See [docs](https://nodemon.io/)
- `jest` || To run our tests and coverage. See [docs](https://jestjs.io/)
- `supertest` || To more easily test our endpoints. See [docs](https://github.com/visionmedia/supertest#readme)
- `mongodb-memory-server` || To mock out our database in our backend tests. See [docs](https://github.com/nodkz/mongodb-memory-server)
- `cors` || To open up our API. See [docs](https://github.com/expressjs/cors#readme)
- `mongoose` || To add schemas to our database. See [docs](https://mongoosejs.com/)
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ export const DropdownNotificationsMenu = ({
<div className="flex flex-col items-start gap-1">
<div className="flex items-center gap-1 text-sm font-medium text-light-100">
<span>{option.actor.name}</span>
<Badge title="Messages" />
<Badge title="Appointments" />
</div>
<span className="text-sm text-light-400">
{option.status === "approved"
Expand Down
Loading
Loading