Skip to content

Interests Module

Location: apps/api/src/modules/interests/

Aggregate roots: Interest (catalog), UserInterest


Catalog Hierarchy

The interest catalog is a 3-level tree:

L1 — Category         (e.g. Philosophy)
 └── L2 — Sub-interest    (e.g. Existentialism)
      └── L3 — Deep interest  (e.g. Heidegger's Being and Time)
  • L1 nodes have parentId = null and level = 1
  • L2 nodes have level = 2 and parentId pointing to L1
  • L3 nodes have level = 3 and parentId pointing to L2
  • Each node has a slug (URL-safe), name, path (dotted ltree-style), and optional accentColor token

Accent Color Palette

TokenColor
inkDark charcoal
goldAmber
sageGreen
coralRed-orange
cyanTeal
plumPurple

Catalog Caching

The full catalog tree is cached in-process for 10 minutes. Both onboarding and the search screen hit this endpoint on every mount. Cache is invalidated on any interest create/update/delete (admin only).


User Interests

Each UserInterest row captures a user's engagement with one catalog entry.

Depth Scale

ValueLabelMeaning
1CuriousJust exploring
2ReadingActively learning
3PracticingApplying in practice
4DeepAdvanced understanding
5LifeworkCore to who you are

Expertise Scale

Self-rated expertise (1–5) is distinct from depth. Depth = engagement level; expertise = perceived skill level. Both are stored independently.


Reputation Rollup

When reputation is recorded for an L3 interest, it rolls up to parents using these ratios:

LevelRatio
L3 (target)1.0
L2 (parent)0.5
L1 (grandparent)0.25

This means earning 10 rep in heidegger-being-and-time also adds 5 to existentialism and 2.5 (rounded) to philosophy.

For L2 targets:

LevelRatio
L2 (target)1.0
L1 (parent)0.5

Events Emitted

EventPayloadTrigger
interests.user_selected{userId, interestId, depth}User adds/changes interest
interests.depth_changed{userId, interestId, oldDepth, newDepth}Depth update only

API Endpoints

MethodPathDescription
GET/interests/catalogFull tree, 3 levels deep
GET/interests/catalog?level=1Filter by level
GET/interests/:idOrSlugSingle interest with children
GET/me/interestsMy selections with depth + expertise
POST/me/interestsAdd or update interest
PATCH/me/interests/:idUpdate depth/expertise/description
DELETE/me/interests/:idRemove selection

Admin Endpoints

MethodPathDescription
GET/admin/interestsFull list with user counts
POST/admin/interestsCreate catalog entry
PATCH/admin/interests/:idUpdate entry
DELETE/admin/interests/:idSoft-delete (clears isCustom, keeps rows)

Onboarding Flow

During AI-assisted onboarding, interests are suggested by the AI reflection session via AssistantSuggestion. The user selects from suggestions; accepted suggestions are written to UserInterest via POST /ai/apply-suggestions.

The onboarding drill-down UI presents L1 → L2 → L3 in a three-step picker.

Regulus — invite-only social-knowledge platform