Core Concepts
This document explains the key architectural patterns and data models used in the FriendZone application.
Authentication and Route Protection
The application uses next-auth for authentication, specifically with a Google OAuth provider.
Authentication Flow
- Configuration (
src/lib/auth.ts): This file sets upnext-auth. It configures theUpstashRedisAdapterto store session and user data in Redis. It also defines thejwtandsessioncallbacks to enrich the session token with the user's database ID. - Login Page (
src/app/(auth)/login/page.tsx): The login page provides a simple button that triggers thesignIn('google')function fromnext-auth/react. - Middleware (
src/middleware.ts): A crucial part of the security model. The middleware checks every incoming request to sensitive routes (like/dashboard).- If a user is not authenticated and tries to access a protected route, they are redirected to
/login. - If an authenticated user tries to access
/login, they are redirected to/dashboard.
- If a user is not authenticated and tries to access a protected route, they are redirected to
Real-time Communication with Pusher
Pusher is used to push real-time updates to connected clients, avoiding the need for clients to constantly poll the server for new data.
Setup (src/lib/pusher.ts)
pusherServer: A server-side instance of Pusher used in API routes to trigger events.pusherClient: A client-side instance used in React components to subscribe to channels and bind to events.
Channels and Events
The application uses a specific channel naming convention managed by toPusherKey() to ensure compatibility.
-
Friend Requests:
- Channel:
user:{userId}:incoming_friend_requests - Event:
incoming_friend_requests - Triggered: When a user sends a friend request in
POST /api/friends/add. - Listened by:
FriendRequests.tsxandFriendRequestSidebarOptions.tsxto update the UI in real-time.
- Channel:
-
New Friends:
- Channel:
user:{userId}:friends - Event:
new_friend - Triggered: When a user accepts a friend request in
POST /api/friends/accept. - Listened by:
SidebarChatList.tsxto add the new friend to the chat list, andFriendRequestSidebarOptions.tsxto decrement the request counter.
- Channel:
-
Chat Messages:
- Channel:
chat:{chatId} - Event:
incoming-message - Triggered: When a message is sent in
POST /api/message/send. - Listened by:
Messages.tsxto display the new message in the chat window.
- Channel:
-
New Chat Notifications:
- Channel:
user:{friendId}:chats - Event:
new_message - Triggered: When a message is sent in
POST /api/message/send. - Listened by:
SidebarChatList.tsxto show a notification toast and update the unread message count for the relevant chat.
- Channel:
Redis Data Model
Upstash Redis is used as the application's database due to its high performance, which is ideal for a real-time chat application.
-
User Data:
user:{userId}: A JSON string containing the user'sid,name,email, andimage.user:email:{email}: A simple key that stores theuserIdcorresponding to an email address. This allows for quick lookups when adding a friend by email.
-
Friend Relationships:
user:{userId}:friends: A Redis Set containing the IDs of all users who are friends with{userId}. Sets are efficient for checking membership (e.g., are these two users friends?).
-
Friend Requests:
user:{userId}:incoming_friend_requests: A Redis Set containing the IDs of all users who have sent a friend request to{userId}.
-
Chat Messages:
chat:{chatId}:messages: A Redis Sorted Set. Each member of the set is a JSON string representing a message object. Thescorefor each member is the messagetimestamp. This allows for efficient, chronologically ordered retrieval of messages.