Incorporación (Onboarding) — Referencia técnica
Dónde vive esto
Backend
apps/backend/graphql/resolvers/user-social.resolver.js— mutationcompleteOnboarding(interests)(aplica el mínimo de 5 seguidos, estableceisOnboardingCompleted)apps/backend/graphql/resolvers/user-search-discovery.resolver.js— queryinterestSuggestions(limit, interests)apps/backend/data-access-services/user/user.access-service.js—getUsersByInterests()(superposición de intereses),getSuggestedUsers()(relleno amplio)apps/backend/data-access-services/user/user-follow.access-service.js—getFollowingCount()usado por la validación de los 5 seguidos
Frontend
apps/frontend-nextjs/src/page-components/OnboardingPage.tsx— el flujo de dos pasos (intereses → seguir ≥5) + cuadro de búsqueda + cierre de sesiónapps/frontend-nextjs/src/app/onboarding/page.tsx— rutaapps/frontend-nextjs/src/components/ProtectedRoute.tsx— la validación (redirige a los usuarios sin terminar hacia/onboarding, no renderiza nada mientras tanto)apps/frontend-nextjs/src/components/Login.tsx— la redirección posterior al inicio de sesión envía directo a/onboardinga los usuarios sin terminarapps/frontend-nextjs/src/lib/interests.ts— catálogo de intereses compartido (slugs + etiquetas)
Checklist de implementación técnica
-
completeOnboarding(interests: [String!]): User!— requieregetFollowingCount(userId) >= 5del lado del servidor, estableceisOnboardingCompleted+onboardingCompletedAt, guarda los intereses -
interestSuggestions(limit, interests): [User!]!— usa los intereses pasados (en vivo durante la incorporación) o los intereses guardados de quien mira; se completa congetSuggestedUserspara que la lista nunca quede corta - Validación persistente —
ProtectedRouteredirige cuandouser.isOnboardingCompleted === false(la bandera viene del payload de login/registro; volver a iniciar sesión la vuelve a activar) -
isOnboardingCompletedagregado a las selecciones de usuario de login / verificación de 2FA / OAuth (Firebase, Apple, teléfono, passkey) enLogin.tsx; la mutationRegisterno solicita el campo, así queLogin.tsxlo asigna por defecto afalseahí (las cuentas nuevas siempre necesitan incorporación)
GraphQL
type Query {
interestSuggestions(limit: Int, interests: [String!]): [User!]!
}
type Mutation {
completeOnboarding(interests: [String!]): User!
}
type User {
isOnboardingCompleted: Boolean! # self-only
# ...
}
Notas
- Los intereses se guardan en
user.interests(text[]) — el atributo del modelo Sequelize esinterestTags(campointerests) para evitar colisionar con la asociación muchos-a-muchos existenteInterest, llamadainterests. - Reutiliza la columna existente
is_onboarding_completed, por lo que no hay migración para la validación en sí; la columnauser.interestsse incluye en20260721120000-add-interests-to-user.