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 theUpstashRedisAdapter
to store session and user data in Redis. It also defines thejwt
andsession
callbacks 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.tsx
andFriendRequestSidebarOptions.tsx
to 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.tsx
to add the new friend to the chat list, andFriendRequestSidebarOptions.tsx
to 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.tsx
to 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.tsx
to 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 theuserId
corresponding 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. Thescore
for each member is the messagetimestamp
. This allows for efficient, chronologically ordered retrieval of messages.