Quran_Tech_Server / docs /full_project_architecture.md
aboalaa147's picture
Initial deployment
eb6a2f9
|
Raw
History Blame Contribute Delete
21.1 kB
# Furqan — Full System & Component Architecture Blueprint
This document provides a comprehensive blueprint of the system and component-level architecture for **Furqan**, an interactive Quran learning and reciting platform. It details the multi-tier topology, component definitions, communication channels, state management, database schema, and core design patterns.
---
## 1. System Topology & Multi-Tier Architecture
Furqan is built on a modern multi-tier architecture designed for scalability, low-latency real-time video streaming, and automated AI processing.
```mermaid
graph TB
subgraph ClientTier["Client Tier (Browser SPA)"]
ReactSPA["React 19 SPA (Vite + TS)"]
WebRTCClient["Browser WebRTC (RTCPeerConnection)"]
SockJSClient["SockJS + STOMP Client"]
StripeJS["Stripe.js Element SDK"]
end
subgraph ApplicationTier["Application Server Tier"]
subgraph SpringBoot["Spring Boot 4.0 Backend (Java 21)"]
SecurityFilterChain["Spring Security & JWT Filter"]
RestController["REST Controllers (Auth, Booking, Profile, Admin)"]
WSController["WebSocket Signaling Controller"]
DomainService["Domain Services (Session, Availability, AI mapping)"]
PaymentService["Stripe Connect Integration Service"]
JAVE2["JAVE2 Audio Transcoder (FFmpeg wrapper)"]
end
end
subgraph DatabaseTier["Database Tier"]
PostgresDB[("PostgreSQL Database (Neon Cloud / Local)")]
end
subgraph ExternalTier["External Services Tier"]
AIService["Quran AI Service (FastAPI / ngrok)"]
StripeAPI["Stripe Connect & Payments API"]
GoogleOAuth["Google Identity Provider"]
GmailSMTP["Gmail SMTP (OTP delivery)"]
end
%% Client Connections
ReactSPA -->|HTTPS REST| SecurityFilterChain
SockJSClient -->|WS / SockJS| WSController
WebRTCClient <-->|Peer-to-Peer Media Streams| PeerWebRTCClient["Peer Browser WebRTC - RTCPeerConnection"]
StripeJS -->|Secure Card Tokenization| StripeAPI
%% Backend Routing
SecurityFilterChain --> RestController
WSController --> DomainService
RestController --> DomainService
DomainService --> PaymentService
DomainService --> JAVE2
DomainService -->|Spring Data JPA| PostgresDB
%% External API Integrations
PaymentService -->|Stripe SDK| StripeAPI
DomainService -->|RestTemplate Multipart| AIService
RestController -->|Google OAuth2 Client| GoogleOAuth
DomainService -->|JavaMailSender| GmailSMTP
```
### 1.1 Communication & Protocol Specifications
* **REST HTTP API (State Mutators & Querying):** The React SPA interacts with the Spring Boot backend via JSON-based REST APIs. All protected endpoints require a JWT token in the `Authorization: Bearer <JWT>` header.
* **WebRTC Peer-to-Peer (Audio/Video Media):** Media streams (audio and video) for live recitation classes run directly peer-to-peer between client browsers. No media passes through the application server, saving bandwidth and lowering latency.
* **WebSocket / STOMP (Signaling Channel):** Handshaking (SDP offers, answers, and ICE candidates) is facilitated by the backend via a SockJS endpoint (`/ws`) utilizing the STOMP messaging protocol. Messages published to `/app/signal` are multiplexed to the appropriate sub-channel under `/topic/session/{sessionId}`.
* **External AI Payload (Multipart HTTP):** Transcoded audio files (WAV) are pushed from the backend to the external Python AI Service via `multipart/form-data` requests.
---
## 2. Technology Stack & Environment
| Layer | Concern | Technology / Dependency | Specifications |
| :--- | :--- | :--- | :--- |
| **Frontend** | Framework & Language | React 19 + TypeScript | Strict typing, functional components |
| | Build System | Vite 7 | Hot Module Replacement (HMR) |
| | Styling | Vanilla CSS + Radix UI (shadcn) | Curated CSS Custom Properties |
| | Router | React Router v7 | Nested routing, role guards |
| | Localization | i18next & react-i18next | Multi-language (AR/EN), RTL support |
| | Real-Time | `@stomp/stompjs` + `sockjs-client` | STOMP signaling over WebSockets |
| | Payment Gateway | `@stripe/react-stripe-js` | Secure hosted payment elements |
| **Backend** | Framework & Language | Spring Boot 4.0 (Java 21) | MVC, Security, WebSocket, Mail |
| | Security | Spring Security 6 + JJWT | Stateless JWT auth, OAuth2 client |
| | Persistence | Spring Data JPA + Hibernate 6 | PostgreSQL dialect, connection pool |
| | Database | PostgreSQL | Hosted (Neon Cloud) or local instances |
| | Transcoding | JAVE2 (Java Audio Video Encoder) | FFmpeg wrapping for audio conversion |
| | External APIs | Stripe Java SDK (v25.3), Google Client API | Connection to Stripe Connect & Google OAuth |
---
## 3. Component Architecture
### 3.1 Frontend Component Tree (React SPA)
```
src/
├── main.tsx # Client boots with GoogleOAuthProvider
├── App.tsx # Base Router configurations & context nesting
├── lib/
│ ├── authContext.tsx # Holds current user state, triggers token restore
│ ├── StudentContext.tsx # Manages and caches student session lists/history
│ ├── languageContext.tsx # Toggles directionality (LTR/RTL), triggers i18n
│ └── api/ # Domain-specific fetch clients
│ ├── aiApi.ts # Talks to the ngrok-tunneled Python Quran Model
│ ├── bookingApi.ts # Availability slots, reservations, reviews
│ ├── paymentApi.ts # Stripe payment initiation
│ └── studentApi.ts / sheikhApi.ts / adminApi.ts
├── hooks/
│ └── useWebRTC.ts # Manages RTCPeerConnection, STOMP signaling,
│ # and RTT quality metric reporting
└── components/
├── Navbar.tsx # Top navigation with responsive menus and language switcher
├── LandingPage.tsx # Introduction & guest landing page
├── auth/ # SignIn, Register, OTP verification, Profile wizard
├── dashboards/
│ ├── StudentDashboard.tsx # Student home page showing streak, history, and goals
│ ├── SheikhDashboard.tsx # Teacher dashboard displaying class requests and stats
│ └── AdminDashboard.tsx # Platform dashboard (user activation, sheikh approval queue)
├── sheikh/
│ ├── FindSheikh.tsx # Search engine to filter sheikhs by country, rate, rating
│ ├── SheikhProfile.tsx # Teacher profile with availability picker and booking flow
│ └── MyStudents.tsx # Student management & history view
├── sessions/
│ ├── WaitingRoom.tsx # 5-minute pre-session countdown & connection check
│ ├── LiveSession.tsx # Real-time dashboard containing WebRTC video & notes
│ ├── SessionReport.tsx # Student feedback form after classes
│ └── SessionEndWaiting.tsx # Polling component waiting for sheikh to finalize report
├── practice/
│ ├── RecordingPractice.tsx # Recording interface for solo Quran reciting
│ └── EvaluationReports.tsx # AI report display (word error markup, tashkeel issues)
├── admin/ # Approve Sheikhs, Manage Users, Conduct Interviews
└── ui/ # Reusable shadcn primitive elements (Dialog, Accordion)
```
#### Key React Contexts:
1. **AuthContext:** Stores `authToken` and `currentUser` object in memory and local storage. On boot, it verifies profile status against `GET /api/auth/verify-profile`.
2. **LanguageContext:** Evaluates language configuration (AR/EN). Modifies the root document's body direction element (`dir="rtl"` or `dir="ltr"`) dynamically.
3. **StudentContext:** Holds listing and filter state for searching teachers, reducing component re-renders during queries.
### 3.2 Backend Packages & Layers (Spring Boot)
The Spring Boot backend is structured as a vertical domain slice pattern. Components are grouped by functional slice (Common/Auth, Student, Sheikh, Admin, WebSocket, Payment) rather than simple controller/service/repository folders.
```
com.yourcompany.quranapp.quran_app_backend/
├── config/
│ ├── SecurityConfig.java # JWT filter chains, CORS configurations, RBAC
│ └── GlobalExceptionHandler.java # Catches all exceptions, rendering standardized JSON responses
├── security/
│ ├── JwtAuthenticationFilter.java # OncePerRequestFilter extracting and verifying tokens
│ ├── CustomUserDetails.java # UserDetails implementation mapping roles and statuses
│ └── UserDetailsServiceImpl.java # Resolves queries checking user status
├── entity/ # Contains JPA entities (User, Session, Recitation, etc.)
├── dashboard/
│ ├── common/ # Auth Controllers, Services, JwtService, EmailService
│ ├── student/ # Student Profile, Recitation, and Booking controllers
│ ├── sheikh/ # Session, Availability, and Review endpoints
│ └── admin/ # User management, approval systems, and Interview scheduling
├── payment/ # Stripe API controllers and processing services
├── websocket/ # WS STOMP configuration and WebRTC signaling controllers
├── google/ # Google ID Token verification utility
└── setup/ # DataLoader for system bootstrapping
```
---
## 4. Database Schema & Data Architecture
The PostgreSQL database relies on Flyway migrations to evolve schemas. Soft delete mechanisms, checks, and cascade triggers ensure database integrity.
```mermaid
erDiagram
users ||--|| student_profile : "1:1 profile"
users ||--|| sheikh_profile : "1:1 profile"
users ||--o{ availability : "sets availability"
users ||--o{ recitations : "records recitation"
users ||--o| wallet : "owns wallet"
users ||--o{ session : "books as student"
users ||--o{ session : "conducts as sheikh"
users ||--o{ payment : "pays / receives"
users ||--o{ review : "submits"
users ||--|| streak : "tracks streak"
session ||--o| payment : "1:1 payment"
session ||--o| review : "1:1 review"
wallet ||--o{ wallet_transaction : "has transactions"
payment ||--o| wallet_transaction : "triggers transaction"
session ||--o| wallet_transaction : "triggers transaction"
users {
bigint userId PK
varchar email UK
varchar passHash
varchar fullName
boolean isActive
varchar phone UK
role_enum role
timestamp createdAt
}
student_profile {
bigint studentId PK, FK
gender_enum gender
date birthdate
quraan_level_enum quraan_level
}
sheikh_profile {
bigint sheikhId PK, FK
text bio
specialization_enum specialization
int yearsOfExperience
varchar certificatesURL
decimal hourlyRate
decimal ratingAVG
live_status_enum liveStatus
timestamp lastActiveAt
}
availability {
bigint availabilityId PK
day_of_week_enum dayOfWeek
time startTime
time endTime
bigint sheikhId FK
}
recitations {
bigint recitationId PK
varchar surahName
int ayahStart
int ayahEnd
decimal wordScore
decimal tashkeelScore
jsonb mistakesReportJson
bigint studentId FK
timestamp createdAt
}
session {
bigint sessionId PK
timestamp scheduledStart
timestamp scheduledEnd
timestamp actualStart
timestamp actualEnd
timestamp studentJoinedAt
timestamp sheikhJoinedAt
timestamp studentLeftAt
timestamp sheikhLeftAt
session_status_enum status
decimal price
text sessionNotes
bigint studentId FK
bigint sheikhId FK
}
payment {
bigint paymentId PK
decimal amount
varchar currency
payment_method_enum paymentMethod
payment_status_enum paymentStatus
varchar transaction_id UK
bigint sessionId FK, UK
bigint studentId FK
bigint sheikhId FK
}
review {
bigint reviewId PK
int rate
text comment
bigint sessionId FK, UK
bigint studentId FK
}
wallet {
bigint walletId PK
decimal balance
bigint userId FK, UK
}
wallet_transaction {
bigint transactionId PK
decimal amount
transaction_type_enum transactionType
bigint walletId FK
bigint paymentId FK
bigint sessionId FK
}
```
### 4.1 Schema Optimization & Indexes
* **Foreign Keys:** Mappings are managed via cascading constraints (`ON DELETE CASCADE`) for profile data, while critical records (Sessions, Payments) use `ON DELETE RESTRICT` to protect audit trails.
* **Indexing Strategy:**
* Composite index on `sessions (sheikh_id, status, scheduled_start)` for dashboard rendering.
* Composite index on `sheikh_profile (status, ratingAVG)` for search rankings.
* Indexes on search filters (`users.role`, `availability.dayOfWeek`, `payments.paymentStatus`).
---
## 5. Architectural Workflows & Sequences
### 5.1 Real-Time WebRTC Peer-to-Peer Calling Flow
This flow enables media streams to bypass backend servers. Handshaking is done over the WebSocket STOMP broker.
```mermaid
sequenceDiagram
participant Student as Student Browser
participant WS as Backend STOMP Broker
participant Sheikh as Sheikh Browser
Note over Student, Sheikh: Pre-conditions: Both join session room
Student->>WS: Connects & Subscribes to /topic/session/{id}
Sheikh->>WS: Connects & Subscribes to /topic/session/{id}
Student->>WS: Send Signal {type: 'join', sender: StudentId}
WS-->>Sheikh: Forward 'join' payload
Note over Sheikh: Received Join -> Initialize Handshake
Sheikh->>Sheikh: Fetch camera/mic streams via getUserMedia()
Sheikh->>Sheikh: Create RTCPeerConnection & Add local media tracks
Sheikh->>Sheikh: Create SDP Offer
Sheikh->>WS: Send Signal {type: 'offer', data: SDP_Offer}
WS-->>Student: Forward 'offer' payload
Note over Student: Received Offer -> Formulate Answer
Student->>Student: Fetch camera/mic streams via getUserMedia()
Student->>Student: Create RTCPeerConnection & Add local media tracks
Student->>Student: Set Remote Description (SDP_Offer)
Student->>Student: Create SDP Answer
Student->>WS: Send Signal {type: 'answer', data: SDP_Answer}
WS-->>Sheikh: Forward 'answer' payload
Note over Sheikh: Set Remote Description (SDP_Answer)
Note over Student, Sheikh: ICE Candidate Exchange (Parallel)
Student->>WS: Send Signal {type: 'ice-candidate', data: Candidate}
WS-->>Sheikh: Forward candidate
Sheikh->>WS: Send Signal {type: 'ice-candidate', data: Candidate}
WS-->>Student: Forward candidate
Note over Student, Sheikh: Handshake Complete. P2P Direct Media Pipeline Established.
```
### 5.2 AI Recitation Evaluation Lifecycle
Automated speech recognition and Tajweed/Tashkeel correction processing pipeline.
```mermaid
sequenceDiagram
participant Student as Student Browser
participant Spring as Spring Boot Backend
participant FFmpeg as FFmpeg / JAVE2
participant AI as AI Model Service (FastAPI)
Student->>Student: Records voice using MediaRecorder (WebM/AAC)
Student->>Spring: POST /api/student/recitations (Multipart: File + Surah)
Note over Spring: Upload received -> Audio transcoding
Spring->>FFmpeg: Transcode input file -> WAV (PCM 16kHz, mono)
FFmpeg-->>Spring: WAV Stream / File
Spring->>AI: POST /analyze (Multipart: WAV File + Surah Number)
Note over AI: 1. ASR (Automatic Speech Recognition)<br/>2. Text Alignment with Surah Text<br/>3. Tashkeel & word-accuracy comparison
AI-->>Spring: JSON Report {surah_info, overall_stats, ayahs[]}
Spring->>Spring: Map details, compute scores & generate mistakes list
Spring->>Spring: Save Recitation entity (mistakesReportJson column = JSONB)
Spring-->>Student: Return RecitationDetailsDto
```
### 5.3 Stripe Payments & Payout Split Routing
Stripe Payment Intents for student collection, combined with Stripe Connect Express accounts to route money to teachers.
```mermaid
sequenceDiagram
participant Student as Student Browser
participant Backend as Spring Boot Backend
participant Stripe as Stripe API
participant Sheikh as Sheikh Wallet (Stripe Connect)
Student->>Backend: POST /api/payments/initiate/card (Session Details)
Backend->>Stripe: Create PaymentIntent (Amount, metadata)
Stripe-->>Backend: Return PaymentIntent Details (clientSecret)
Backend-->>Student: Return { clientSecret, publishableKey }
Note over Student: Render Stripe Credit Card element
Student->>Stripe: Submit card details + Confirm Payment (clientSecret)
Stripe-->>Student: Return Success
Student->>Backend: POST /api/payments/confirm-payment/{intentId}
Backend->>Stripe: Query status of PaymentIntent
Stripe-->>Backend: Return status (Succeeded)
Backend->>Backend: Update Payment status -> PAID, Session -> SCHEDULED
Backend-->>Student: Confirm success (200 OK)
Note over Student, Backend: Time passes -> Session completes
Backend->>Backend: Trigger Payout routing
Backend->>Backend: Calculate Split: Sheikh (85%), Commission (15%)
Backend->>Stripe: Create Transfer (Amount = 85%, Destination = sheikhAccountId)
Stripe->>Sheikh: Route payout to bank account
Stripe-->>Backend: Return transfer confirmation
Backend->>Backend: Update Payment record -> PAYOUT_DONE
```
---
## 6. Key Design Patterns & Engineering Best Practices
### 6.1 Eliminating JPA N+1 Query Bottlenecks
To prevent excessive queries during operations like mapping collections, the backend follows optimized loading rules:
1. **Strict Lazy Loading by Default:** All `@ManyToOne` and `@OneToOne` database mappings are annotated with `FetchType.LAZY`.
2. **JOIN FETCH Queries for Collection Mapping:** When resolving lists of objects, custom JPQL queries use `JOIN FETCH` to retrieve relations in a single query:
```java
@Query("SELECT s FROM Session s JOIN FETCH s.student JOIN FETCH s.sheikh LEFT JOIN FETCH s.payment WHERE s.student.id = :studentId")
List<Session> findByStudentIdWithUsers(@Param("studentId") Long studentId);
```
3. **Projections for Performance Statistics:** For aggregate metrics, queries map directly to flat DTO projections using constructors instead of reading full entity trees:
```java
@Query("SELECT new com.yourcompany.quranapp.quran_app_backend.dashboard.sheikh.dto.MyStudentsStats(COUNT(DISTINCT s.student.id), COALESCE(SUM(s.price), 0)) FROM Session s WHERE s.sheikh.id = :sheikhId")
MyStudentsStats getMyStudentsStats(@Param("sheikhId") Long sheikhId);
```
### 6.2 Event-Driven Lifecycle Check Schedulers
To handle session outcomes (e.g. no-shows or unpaid requests), the backend sets up scheduled checks when sessions are created or on server boot:
* **Unpaid Cancellations:** Runs 5 minutes before `scheduledStart`. If payment status is pending, session changes to `CANCELLED`.
* **Student No-Show Checks:** Runs 1 minute after `scheduledStart`. If neither party joins, session is marked as `MISSED` and student receives a refund.
* **Sheikh No-Show Checks:** Runs 10 minutes after `scheduledStart`. If sheikh fails to join, session is marked as `MISSED` and student receives a refund.
Startup scheduling listeners reconstruct these checks on server launch:
```java
@EventListener(ApplicationReadyEvent.class)
public void rescheduleExistingSessionsOnStartup() {
List<Session> scheduled = sessionStatusRepository.findByStatus(SessionStatus.SCHEDULED);
for (Session session : scheduled) {
scheduleMissedCheck(session.getId(), session.getScheduledStart());
scheduleSheikhNoShowCheck(session.getId(), session.getScheduledStart());
}
}
```
### 6.3 Optimistic UI Updates & Error Boundaries
* **Optimistic Dashboards:** Frontend state changes (e.g., accepting/declining classes) update user state immediately, then send requests to the backend. The UI reverts state only if a network error occurs.
* **Component Isolation:** Layouts utilize `ErrorBoundary` elements, isolating widget failures so that an error in a single component (e.g., a stats chart) does not break the entire dashboard.