The Peer Learning Platform primarily relies on the Supabase JavaScript Client for interacting with the database, and a custom Node.js Express Backend for secure external API interactions (like the AI assistant).
Most data operations are performed directly from the React frontend using the supabase-js client. RLS (Row-Level Security) policies in the database ensure these requests are secure.
import { supabase } from '@/integrations/supabase/client';
const fetchSessions = async () => {
const { data, error } = await supabase
.from('study_sessions')
.select('*, profiles(username, avatar_url)')
.order('created_at', { ascending: false });
if (error) console.error(error);
return data;
};const sendMessage = async (sessionId: string, content: string, userId: string) => {
const { error } = await supabase
.from('chat_messages')
.insert({
session_id: sessionId,
content: content,
sender_id: userId
});
};For operations requiring secure handling of external API keys (e.g., OpenAI/OpenRouter), requests are sent to our custom backend.
Generates an AI summary of a chat session.
Endpoint: http://localhost:5000/api/ai/summary
Headers:
Authorization:Bearer <Supabase JWT Token>
Request Body:
{
"messages": [
{"role": "user", "content": "How does React context work?"},
{"role": "assistant", "content": "React context provides a way to pass data through the component tree without having to pass props down manually at every level."}
]
}Response:
{
"summary": "The user asked about React Context, and the assistant explained that it is used to avoid prop drilling."
}Security & Rate Limiting:
- Requires a valid Supabase JWT token.
- Protected by a custom, in-house rate limiter middleware (
backend/middlewares/rateLimiter.js) to prevent abuse.
These endpoints are triggered by a scheduled cron job and protected by the CRON_SECRET environment variable.
Auth: Authorization: Bearer <CRON_SECRET>
All cron requests must supply the CRON_SECRET token in the Authorization header. Requests without a valid CRON_SECRET receive a 401 Unauthorized response.
Atomically claims a batch of pending push notifications (up to 100) and dispatches them to subscribed devices. Uses push_claimed_at to prevent concurrent invocations from double-delivering the same notification.
Response:
{ "sent": 5, "processed": 5 }Finds upcoming study sessions starting within the next 15 minutes and inserts session_reminder notifications for all participants.
Response:
{ "inserted": 3 }Finds incomplete mentorship milestones that are due or overdue within the next 24 hours and inserts mentorship_reminder notifications for mentor and mentee.
Response:
{ "inserted": 2 }These endpoints support two authentication modes: WEBHOOK_SECRET for server-to-server calls, and a standard Supabase JWT for user-initiated calls.
Auth: Authorization: Bearer <WEBHOOK_SECRET> OR valid Supabase JWT token.
Requests carrying a valid WEBHOOK_SECRET bypass user-level auth. Requests without a WEBHOOK_SECRET fall back to the standard requireAuth middleware which validates the Supabase JWT.
Sends a browser push notification to all subscribed devices for a given user_id.
Request Body:
{
"user_id": "uuid",
"title": "New message",
"body": "Alice sent you a message.",
"action_url": "/messages"
}Response:
{ "sent": 1, "failed": 0 }Security: Standard users may only send push notifications to themselves (IDOR prevention). Webhook callers authenticated via WEBHOOK_SECRET may send to any user.
Uploads generic project resources with magic byte validation.
Auth: Requires a valid Supabase JWT token in Authorization: Bearer <token> or access_token cookie.
Content-Type: multipart/form-data
Form Fields:
file(File, required): The file to upload.folder(string, required): Permitted values areavatarsorresources.
Response (200 OK):
{
"success": true,
"data": {
"url": "https://<supabase-url>/storage/v1/object/public/resources/user-id/filename.pdf"
}
}Uploads user profile photos (avatars) with magic byte validation.
Auth: Requires a valid Supabase JWT token in Authorization: Bearer <token> or access_token cookie.
Content-Type: multipart/form-data
Form Fields:
profilePhoto(File, required): The profile image file (max size: 2 MiB).
Response (200 OK):
{
"success": true,
"fileUrl": "https://<supabase-url>/storage/v1/object/public/avatars/user-id/filename.png"
}Authenticated multipart uploads are written to Supabase Storage. Storage paths are generated on the server from the caller's user id — clients cannot choose arbitrary object keys.
General-purpose upload for avatars, profiles, and resources buckets.
Auth: valid Supabase JWT (Authorization header or access_token cookie)
Form fields:
folder: one ofavatars,profiles,resourcesfile: the file to upload
Validation:
- MIME type must match the destination folder allow-list
- Magic byte / content-type verification rejects spoofed uploads
- Binary content and null bytes are rejected for text resource uploads
Profile-photo upload into the profiles bucket (2MB limit).
Auth: valid Supabase JWT (Authorization header or access_token cookie)
Form fields:
profilePhoto: JPEG, PNG, WebP, or GIF image
Validation:
- 2MB size limit
- Strict image MIME allow-list
- Magic byte verification that file content matches the declared image type
- Per-user rate limit (10 uploads per hour)