This project has been created as part of the 42 curriculum by fkarika, jstudnic, jgrigorj, vmileshk.
ft_transcendence - AI Collaborative Workspace
ft_transcendence is an invite-only collaborative workspace built as a full-stack web application.
The project focuses on:
- structured collaboration through organizations, projects, and channels
- real-time communication through channel chat and direct messages
- scoped document management
- AI-assisted retrieval over uploaded documents
- role-based access control and ownership management
The goal of the project is to provide a coherent internal collaboration tool where messaging, permissions, documents, and AI all follow the same domain model.
- registration and login
- OAuth login with Google, GitHub, and 42
- invite-only organizations
- organization ownership transfer
- projects and channels
- organization-scoped direct messages
- real-time messaging
- online presence
- document upload and management
- AI question answering over uploaded documents
- AI conversation history per scope
- data export in JSON / CSV / XML
- account deletion with cascade cleanup
- Terms of Service and Privacy Policy
Before running the project, make sure the following are installed:
- Docker
- Docker Compose
make
Optional but useful:
- a configured OAuth application for Google / GitHub / 42
- SMTP configuration for invite emails
- an OpenRouter API key per user for AI functionality
Copy the example environment files:
cp be/.env.example be/.env
cp fe/.env.example fe/.envFill in the required values in:
be/.envfe/.env
Important configuration notes:
- backend runs on Express
- frontend runs on Vite / React
- MongoDB is started through Docker Compose
- Nginx provides the HTTPS entrypoint
- on some rootless / campus Docker setups, the app is exposed on
https://localhost:8443instead ofhttps://localhost
If the project is running on https://localhost:8443, OAuth redirect URIs must use the same port:
https://localhost:8443/api/auth/oauth/google/callbackhttps://localhost:8443/api/auth/oauth/github/callbackhttps://localhost:8443/api/auth/oauth/42/callback
From the repository root:
makeThis starts:
- backend
- frontend
- nginx
- mongo
Open the application in the browser:
https://localhost- or
https://localhost:8443on environments where privileged ports are unavailable
Useful commands:
make logs
make ps
make down
make rebuild- Register or log in.
- Create an organization.
- Invite another user into the organization.
- Accept the invite from the second account.
- Create a project.
- Add members to the project.
- Create or open a channel.
- Send channel messages and verify realtime updates.
- Open a DM thread and verify realtime updates.
- Upload a document in organization / project / channel scope.
- Ask AI a question about the uploaded documents.
- Export user data.
- Transfer organization ownership.
- Verify that an organization owner cannot delete their account before transferring ownership.
- Assigned role(s):
PO | PM | Developer - Responsibilities:
- product coordination, scope alignment, and feature integration across frontend and backend
- keeping documentation aligned with the final product scope
- implemented core backend flows for authentication, permissions, organizations, memberships, documents, ai llm calls, and account lifecycle
- Assigned role(s):
Tech Lead | Developer - Responsibilities:
- frontend technical leadership: full React/Vite/shadcn rewrite of the workspace UI, design system (tokens, primitives, app shell), routing, realtime integration, and end-to-end UX polish across auth, organizations, projects, channels, messages, documents, and AI
- AI-facing frontend: AI ask panel with streaming responses, persistent conversations, @-mentions, and configurable OpenRouter key/model
- cross-cutting quality: code/security review pass, accessibility, skeleton loaders, error boundaries, lazy routes, mobile layouts, and authenticated session refresh on 401
- Assigned role(s):
Developer - Responsibilities:
- implemented OAuth 2.0 authentication flows for Google, GitHub, and 42, including provider app registration and frontend OAuth integration
- contributed feature ideas and product-level functionality suggestions
- performed end-to-end testing across core application flows to improve stability and reliability
- Assigned role(s):
Developer - Responsibilities:
- implemented email notification system for organization invitations
- developed functionality to export user data in multiple formats
- performed comprehensive testing of the entire application to ensure stability and reliability
- The project was divided into clear feature areas: authentication, organization and access management, realtime messaging, document workflows, AI integration, and deployment.
- Tasks were assigned by feature ownership so team members could work in parallel without unnecessary overlap.
- Each feature was developed in its own branch before being reviewed and merged into the shared development branch.
- Integration work focused on keeping frontend, backend, permissions, and infrastructure aligned with the same product model.
- This workflow allowed parallel implementation while keeping the application coherent and consistent.
- The team met approximately once per week on campus to review progress and discuss the next implementation steps.
- During these syncs, the team discussed newly completed work, current blockers, feature priorities, and which parts of the product still needed to be implemented or refined.
- Planning and follow-up were handled by assigning concrete tasks with informal deadlines. Once a team member finished a part of the work, they opened a pull request into the
devbranch, where it was reviewed byfkarikabefore merge.
Tools we used:
- GitHub
- Slack
Communication channels we used:
- Slack
- in-person meetings
- React
- Vite
- React Router
- CSS modules / plain CSS files
- Node.js
- Express
- Socket.IO
- Zod
- MongoDB
- Docker
- Docker Compose
- Nginx
- OpenRouter
- OAuth providers: Google, GitHub, 42
- Nodemailer
- React was chosen for fast UI iteration and component-based structure.
- Express was chosen for a lightweight REST backend with clear routing and middleware control.
- MongoDB was chosen because the project domain is document-oriented and contains nested, relationship-heavy application data.
- Socket.IO was chosen to implement realtime presence and chat updates with a practical event-based API.
- Docker Compose was chosen to make the project reproducible and easy to run for evaluators.
- Nginx was used as a reverse proxy and HTTPS entrypoint.
The backend uses MongoDB collections to represent:
- users
- refresh tokens
- organizations
- organization memberships
- organization invites
- projects
- project memberships
- channels
- channel messages
- direct message threads
- direct message messages
- documents
- document chunks
- AI conversations
- AI messages
- user AI settings
- one user can belong to many organizations
- one organization contains many projects
- one project contains many channels
- one organization contains many invites
- one project has many memberships
- one channel has many messages
- one DM thread has many DM messages
- one document has many extracted chunks
- one AI conversation has many AI messages
All main collections and their important fields are listed below.
-
Useremail: stringusername: stringpasswordHash: string | nullavatarUrl: string | nulllastSeenAt: Date | nullproviders.google: string | nullproviders.github: string | nullproviders.fortyTwo: string | nullcreatedAt: DateupdatedAt: Date
-
RefreshTokenuserId: ObjectIdtokenId: stringexpiresAt: DaterevokedAt: Date | nullcreatedAt: DateupdatedAt: Date
-
UserAiSettingsuserId: ObjectIdapiKey.encryptedValue: string | nullapiKey.iv: string | nullapiKey.authTag: string | nullapiKey.preview: string | nullchatModel: string | nullcreatedAt: DateupdatedAt: Date
-
Organizationname: stringdescription: stringavatarUrl: string | nullorganizationOwnerId: ObjectIdcreatedAt: DateupdatedAt: Date
-
OrganizationMembershiporganizationId: ObjectIduserId: ObjectIdrole: "organizationMember"joinedAt: DatecreatedAt: DateupdatedAt: Date
-
OrganizationInviteorganizationId: ObjectIdemail: stringinvitedUserId: ObjectId | nullcreatedBy: ObjectIdstatus: "pending" | "accepted" | "declined" | "revoked"createdAt: DateupdatedAt: Date
-
ProjectorganizationId: ObjectIdname: stringdescription: stringcreatedBy: ObjectIdcreatedAt: DateupdatedAt: Date
-
ProjectMembershipprojectId: ObjectIduserId: ObjectIdrole: "projectOwner" | "projectMember"addedBy: ObjectIdcreatedAt: DateupdatedAt: Date
-
ChannelprojectId: ObjectIdname: stringisDefaultGeneral: booleancreatedBy: ObjectIdcreatedAt: DateupdatedAt: Date
-
ChannelMessagechannelId: ObjectIdsenderId: ObjectIdcontent: stringcreatedAt: DateupdatedAt: Date
-
DMThreadorganizationId: ObjectIdparticipantIds: ObjectId[]participantKey: stringcreatedAt: DateupdatedAt: Date
-
DMMessagedmThreadId: ObjectIdsenderId: ObjectIdcontent: stringcreatedAt: DateupdatedAt: Date
-
DocumentscopeType: "organization" | "project" | "channel"organizationId: ObjectIdprojectId: ObjectId | nullchannelId: ObjectId | nulltitle: stringoriginalFilename: stringstoredFilename: stringmimeType: stringsize: numberfileUrl: stringuploadedBy: ObjectIdprocessingStatus: "pending" | "completed" | "failed"processingError: string | nullprocessedAt: Date | nullembeddingStatus: "not_started" | "completed" | "failed"embeddingError: string | nullembeddedAt: Date | nullcreatedAt: DateupdatedAt: Date
-
DocumentChunkdocumentId: ObjectIdorganizationId: ObjectIdscopeType: "organization" | "project" | "channel"projectId: ObjectId | nullchannelId: ObjectId | nullchunkIndex: numbertext: stringtokenCount: numberembedding: number[] | nullembeddingModel: string | nullembeddedAt: Date | nullcreatedAt: DateupdatedAt: Date
-
AiConversationuserId: ObjectIdscopeType: "organization" | "project" | "channel"organizationId: ObjectIdprojectId: ObjectId | nullchannelId: ObjectId | nulltitle: string | nullcreatedAt: DateupdatedAt: Date
-
AiMessageconversationId: ObjectIdrole: "user" | "assistant"content: stringsources: Array<{ documentId: ObjectId; title: string; originalFilename: string; scopeType: "organization" | "project" | "channel"; chunkIndex: number }>createdAt: Date
Detailed documentation of database schema:
- Description:
- registration, login, logout, refresh session
- profile editing
- avatar upload / removal
- password change
- account deletion
- Team member(s):
fkarika,jstudnic
- Description:
- Google, GitHub, and 42 login
- provider account linking by email / provider ID
- Team member(s):
jstudnic,jgrigorj
- Description:
- create organizations
- invite members
- accept / decline invites
- remove members
- transfer organization ownership
- Team member(s):
fkarika,jstudnic,vmileshk
- Description:
- create projects
- add project members
- promote / demote project owners
- create / edit / delete channels
- Team member(s):
fkarika,jstudnic
- Description:
- organization DMs
- project channel messages
- realtime delivery with Socket.IO
- presence / online status
- Team member(s):
fkarika,jstudnic
- Description:
- upload PDF / Markdown / text files
- scope documents to organization / project / channel
- embed documents for AI retrieval
- open / delete / manage files
- Team member(s):
fkarika,jstudnic
- Description:
- retrieval over uploaded documents
- AI ask with grounded answers
- streaming responses
- scoped AI conversations
- Team member(s):
fkarika,jstudnic
- Description:
- export user data in JSON / CSV / XML
- Privacy Policy and Terms of Service pages
- Team member(s):
fkarika,vmileshk
-
Real-time features - 2 pts
- Why chosen: realtime communication is central to the product.
- How implemented: Socket.IO for presence, DMs, and channel messages.
- Team member(s):
fkarika,jstudnic
-
User interaction - 2 pts
- Why chosen: the project is fundamentally collaborative.
- How implemented: messaging, profile system, and trusted user interaction through invite-only organization membership.
- Team member(s):
fkarika,jstudnic
-
Standard user management and authentication - 2 pts
- Why chosen: authentication and user lifecycle are core to the platform.
- How implemented: local auth, OAuth, avatars, profile editing, password management, account deletion, online status.
- Team member(s):
fkarika,jstudnic
-
Advanced permissions system - 2 pts
- Why chosen: the app depends on clear role boundaries across organizations, projects, and documents.
- How implemented: organization owner / member roles, project owner / member roles, scoped authorization checks.
- Team member(s):
fkarika,jstudnic
-
Organization system - 2 pts
- Why chosen: organizations are the top-level collaboration boundary.
- How implemented: invite-only membership, organization ownership, transfer, project nesting.
- Team member(s):
fkarika,jstudnic
-
RAG system - 2 pts
- Why chosen: AI over uploaded knowledge is one of the product’s core differentiators.
- How implemented: document chunking, embeddings, retrieval by scope, grounded answers with sources.
- Team member(s):
fkarika,jstudnic
-
LLM system interface - 2 pts
- Why chosen: AI answers and summaries are a key part of the user-facing workflow.
- How implemented: OpenRouter-backed chat generation, streaming, AI conversations.
- Team member(s):
fkarika,jstudnic
-
Frontend framework: React - 1 pt
- Why chosen: component-based UI with fast iteration.
- How implemented: Vite + React + React Router frontend.
- Team member(s):
fkarika,jstudnic
-
Backend framework: Express.js - 1 pt
- Why chosen: lightweight, explicit routing and middleware model.
- How implemented: modular route/controller/service backend.
- Team member(s):
fkarika,jgrigorj,vmileshk
-
File upload and management - 1 pt
- Why chosen: documents are the base knowledge source for AI.
- How implemented: scoped uploads, validation, file serving, deletion, embedding.
- Team member(s):
fkarika,jstudnic
-
OAuth 2.0 authentication - 1 pt
- Why chosen: improves usability and modern authentication support.
- How implemented: Google, GitHub, and 42 OAuth flows.
- Team member(s):
jgrigorj
-
Custom-made design system - 1 pt
- Why chosen: the project needed a consistent first-party UI language across all product areas.
- How implemented: shared Tailwind v4 and shadcn/ui-based design tokens and reusable components used across auth, organizations, messaging, documents, AI, and legal screens.
- Team member(s):
jstudnic
-
Custom module: User data export in JSON / CSV / XML - 1 pt
- Why chosen: authenticated users should be able to download their own accessible workspace data in practical machine-readable formats.
- How implemented: authenticated export endpoint with JSON, CSV, and XML output for profile, memberships, and accessible workspace data.
- Team member(s):
vmileshk
-
Custom module: Email notification system for organization invites - 1 pt
- Why chosen: organization invites are a key workflow and need reliable delivery.
- How implemented: backend email sending with secure invite links and FE invite acceptance flow.
- Team member(s):
vmileshk
14 (major) + 7 (minor) = 21 points
This section must be filled with real contribution ownership.
- Features implemented:
- authentication and profile flows, including avatar management, password change, and account deletion
- organization, project, and channel management flows, including ownership transfer and permission-sensitive UI behavior
- realtime messaging and presence integration for DMs and channel chat
- document upload, embedding flow integration, legal pages, and multiple backend/frontend consistency fixes
- Modules contributed to:
- Real-time features
- User interaction
- Standard user management and authentication
- Advanced permissions system
- Organization system
- RAG system
- LLM system interface
- File upload and management
- Challenges faced:
- keeping permissions, document scope, chat behavior, and AI access consistent across organization, project, and channel levels while features were still evolving
- How they were solved:
- by centralizing access rules in backend service / utility layers, iterating on FE state synchronization after mutations, and validating behavior end-to-end across REST, realtime, document, and AI flows
- Features implemented:
- full frontend rewrite from a legacy CSS-modules SPA to a typed React + Vite + shadcn stack with a coherent design system (tokens, primitives, app shell, layout, routing, and lazy-loaded routes)
- authentication and account flows on the frontend: login, register, OAuth entry points, password change, account deletion, and OAuth-only account handling
- organizations, projects, and channels on the frontend: org rail, project member management for org owners, channel rename/delete, organization ownership transfer, and pending-invite notification
- realtime messaging UX: channel and DM layouts, optimistic-to-server message reconciliation with deduping, unread badges, last-message preview, message ordering, "Sending" indicator, and composer auto-refocus
- documents and AI frontend: document panels, hierarchical org-wide @-mention picker, streaming AI ask panel scoped to organization / project / channel, and persistent conversations with mention highlighting
- privacy policy and terms of service pages with markdown rendering and auth-screen entry links
- quality and polish: error boundary, skeleton loaders, a11y labels, mobile breakpoints, automatic session refresh on 401, and a deep security / code review pass with subsequent fixes
- Modules contributed to:
- Frontend framework: React
- Real-time features
- User interaction
- Standard user management and authentication
- Advanced permissions system
- Organization system
- LLM system interface
- File upload and management
- Challenges faced:
- migrating the live frontend to a new stack in phases without blocking other team members or breaking integration points with the backend, realtime layer, and AI flow
- keeping optimistic UI, realtime socket events, and React Query caches in sync so that messages, presence, invites, and AI streaming felt consistent under reconnects and race conditions
- coordinating UI affordances with the backend permissions model so that organization, project, and channel scopes behaved correctly at every action (invite, transfer, remove, delete, rename)
- How they were solved:
- delivered the rewrite in numbered phases (scaffold → auth → orgs → shell → messages/docs/ai → tests → shadcn swap) so each phase was independently reviewable and integrable
- centralized realtime hooks and React Query cache updates with explicit dedupe and replace logic for optimistic messages, and wired session refresh into the api client to recover from 401s
- aligned every UI mutation with the backend contract by reviewing routes / DTOs alongside frontend work, and tightened the rough edges through a dedicated security and code-review pass
- Features implemented:
- implemented OAuth 2.0 authentication flows for Google, GitHub, and 42, including provider app registration and frontend OAuth integration
- performed end-to-end testing across core application flows to improve stability and reliability
- Modules contributed to:
- Backend framework: Express.js
- OAuth 2.0 authentication
- Challenges faced:
- aligning three different OAuth providers with a single login flow while keeping callback handling, account linking, and session creation consistent
- making the redirect URIs work reliably across local and campus environments, including setups that require a non-default HTTPS port
- How they were solved:
- by centralizing the OAuth callback and token exchange logic on the backend and normalizing the provider-specific profile data before creating or linking accounts
- by validating the flow end-to-end in both frontend and backend, then documenting the exact callback URLs required for each environment
- Features implemented:
- email notification system for organization invites with secure invite links
- user data export functionality in JSON, CSV, and XML formats
- testing and validation of core application flows across authentication, organizations, and data handling
- Modules contributed to:
- Backend framework: Express.js
- Custom module: User data export
- Custom module: Email notification system
- Challenges faced:
- ensuring correct data aggregation and formatting across different export formats
- integrating email notifications reliably with invite workflow
- How they were solved:
- by implementing structured data mapping for each export format and testing outputs
- by integrating Nodemailer with backend logic and validating invite flow end-to-end
- React documentation: https://react.dev/
- Express documentation: https://expressjs.com/
- MongoDB documentation: https://www.mongodb.com/docs/
- Socket.IO documentation: https://socket.io/docs/v4/
- Docker documentation: https://docs.docker.com/
- Nginx documentation: https://nginx.org/en/docs/
- OpenRouter documentation: https://openrouter.ai/docs
-
AI was used for:
- debugging support
- code explanation
- refactoring suggestions
- documentation drafting
- architecture discussion
- wording improvements for prompts and README content
-
AI was not used as an unreviewed source of truth.
-
All generated suggestions were manually reviewed, adapted, tested, and integrated by the team.
-
Final implementation decisions remained with the team members.
- no standalone friend system outside organization membership
- no message attachments
- no message editing / deletion
- no document versioning
- no push notifications
- no audit log
- no private per-channel membership rules
- Main project overview: readme.md
- Backend API reference: docs/API_REFERENCE.md
- System design notes: docs/SYSTEM_DESIGN.md
- Database diagram: docs/DB_DIAGRAM.md