Top Fans — Technical Reference
Where this lives
Backend
apps/backend/graphql/types/top-fans.type.js—TopFan,GiftablePost,RewardTopFanInput,RewardTopFanResponse; queriestopFans/myGiftablePosts/topFanIds; mutationrewardTopFan.apps/backend/graphql/resolvers/top-fans.resolver.jsapps/backend/managers/*/top-fans.manager.js— blends gifts + tips + comments into the ranking and applies rewards.
Frontend
apps/frontend-nextjs/src/page-components/TopFansPage.tsx(routed at/top-fans) — the leaderboard.apps/frontend-nextjs/src/components/rewards/RewardFanModal.tsx— the reward flow.
GraphQL
type TopFan {
user: User!
rank: Int!
giftCoins: Int! giftCount: Int!
tipCoins: Int! tipCount: Int!
commentsCount: Int!
totalCoins: Int! # giftCoins + tipCoins
score: Int! # blended ranking (coins + comments weighted)
}
input RewardTopFanInput {
fanUserId: ID!
"coins | free_subscription | creator_subscription | premium_post"
rewardType: String!
amount: Int # required for coins
conversationId: ID # required for free_subscription (group access)
postId: ID # required for premium_post
message: String
}
extend type Query {
"period: week | month | all (default month)"
topFans(period: String, limit: Int): [TopFan!]!
myGiftablePosts(limit: Int): [GiftablePost!]!
topFanIds(userId: ID!, period: String, limit: Int): [ID!]!
}
extend type Mutation {
rewardTopFan(input: RewardTopFanInput!): RewardTopFanResponse!
}
Notes
topFansranks the viewing creator's own fans;topFanIds(userId)ranks fans for any creator so their supporters can be badged in comments/feed.- The score blends gift coins, tip coins, and comment count;
totalCoinsis the coin-only subtotal (gifts + tips). - Rewards reuse existing systems:
coinsis a coin transfer,free_subscriptiongrants conversation access,premium_postunlocks a paid post for the fan.