Skip to content

Discovery Module

Location: apps/api/src/modules/discovery/

Aggregate roots: ConnectionIntent

The Discovery context implements "Make Connections" (CON-01..03). Users declare a ConnectionIntent and are matched against compatible candidates based on shared interest count, intent compatibility, and optional geo/interest filters.


Intent Types

IntentCompatible With
networkingnetworking
friendsfriends
romanticromantic
mentormentee
menteementor
collabcollab

Prisma Model

connection_intents

FieldTypeNotes
userIdUUID PK FKOne per user
intentStringSee intent types above
noteString?Card text (shown in discovery feed)
isActiveBooleanfalse = hidden from candidates
updatedAtDateTime
createdAtDateTime

Key Methods

MethodDescription
upsertIntent(userId, dto)Set/update intent
getIntent(userId)Get current intent
getCandidates(userId, filters)Ranked candidates by shared interest count
getMentors(userId, filters)Mentors with expertise gap ≥ minExpertiseGap
getPeopleDirectory(userId, opts)Browseable user directory with isFollowing field

Candidate Ranking

getCandidates algorithm:

  1. Exclude: self, banned users, opted-out users (isActive=false).
  2. Filter by intentCompatibility(viewerIntent).
  3. Optional geo filter: city and/or country.
  4. Optional interest filter: interestSlug (must share that specific interest).
  5. Count shared interests via user_interests join.
  6. Sort: shared interest count DESC, then createdAt ASC.
  7. Paginate with cursor (userId-based).

Mentor Matching

getMentors finds users who:

  1. Have ConnectionIntent.intent = 'mentor' and isActive = true.
  2. Share at least one interest with the viewer.
  3. Mentor's UserInterest.expertise exceeds viewer's by minExpertiseGap (default 2, clamped 1..4).
  4. Optional: filter by a specific interestSlug.

HTTP Endpoints

All under /api/v1/discovery/. Require JwtAuthGuard.

MethodPathDescription
PUT/discovery/intentUpsert my intent { intent, note?, isActive? }
GET/discovery/intentGet my intent
GET/discovery/candidatesRanked discovery candidates
GET/discovery/mentorsMentor matches ?interestSlug&minExpertiseGap
GET/discovery/peoplePeople directory ?q&cursor&limit

Query Parameters for /discovery/candidates

ParamTypeNotes
intentString?Override stored intent for query
interestSlugString?Filter by shared interest
countryString?Geo filter
cityString?Geo filter
minSharedInt?Min shared interests (default 1)
limitInt?Page size (default 20, max 50)
cursorString?userId cursor for pagination

People Directory

GET /discovery/people returns paginated users with:

  • id, username, firstName, lastName, profilePicUrl
  • isFollowing: boolean — whether the viewer follows this user
  • sharedInterests: number — count of shared interests

Used by the mobile "People" tab and contact picker.

Regulus — invite-only social-knowledge platform