00 — Aviso al lector
Este documento es lectura honesta del estado de Norte a fecha de enero de 2027. Cubre las decisiones de design system y producto tomadas durante la construcción del build #77, en fase pre-lanzamiento de la cohorte fundadora (200 plazas lifetime).
La pieza cierra la serie de Casos Vivos y es la más distinta de las cinco. Si los cuatro casos anteriores documentan productos que añaden superficies (lorsclub añade /preguntar, Lo Peix añade audioguías, lavigencia añade Vigía y Brief, bodados añade agentes IA con acción real), Norte documenta un producto que se define por lo que rechaza construir. Sin dashboard móvil. Sin settings en la app. Sin historial de chats. Sin badges. Sin streams consultables. Sin notificaciones reactivas.
La pregunta que organiza el caso es la inversa de lo habitual en oficio de diseño: en lugar de “qué exponemos al usuario”, el sistema pregunta “qué le quitamos al usuario para protegerlo de sí mismo”. Esto exige disciplina de DS distinta. Y exige documentarlo con cuidado porque toca un área (TDAH, alta capacidad, 2e) donde la línea entre wellness y reclamo médico hay que mantenerla con rigor.
Sin AI-slop. Sin “elevar”. Sin “transformar”. Quien necesite ese lenguaje no es el público de este documento.
01 — La decisión que cambia todo
Las personas con TDAH, altas capacidades o doble excepcionalidad (2e) no tienen un problema de herramientas insuficientes. Tienen un problema de decisiones que no pueden permitirse procesar. Cada toggle, cada notificación, cada elección de configuración consume presupuesto de energía ejecutiva que ya está fragmentado.
El mercado de productividad y bienestar responde con lo opuesto a lo que estas personas necesitan: dashboards con cuatro métricas, gráficos de tendencias, streams de chat abiertos, badges de progreso, notificaciones reactivas a cada interacción. Cada superficie pensada para “engagement” funciona en usuarios neurotípicos. En usuarios con perfil de alta agencia + disfunción ejecutiva, esas mismas superficies se convierten en vectores de checking compulsivo y reaseguración.
La decisión fundacional de Norte es la opuesta: la app decide cuándo aparecer, ejecuta lo necesario, y desaparece. El usuario nunca consulta streams abiertos. Configuración y métricas viven exclusivamente en la web. El móvil es solo ejecución.
Cita literal del producto: “Una sola tarea visible a la vez. Sin lista, sin backlog, sin ‘ver más’.”
Esta decisión obliga a reescribir cinco preguntas básicas que un equipo de design system suele dar por sentadas:
- ¿Qué es engagement cuando el usuario sufre del exceso de él? Una métrica antagonista del producto.
- ¿Qué es jerarquía visual cuando cada decisión es coste? Una sola superficie visible a la vez, sin scroll, sin tabs, sin menús.
- ¿Qué es accesibilidad cuando el usuario es neurodivergente? Diseño que protege de uno mismo, no solo legibilidad WCAG.
- ¿Qué es el componente principal cuando no hay pantallas? El widget como pieza efímera con timeout máximo.
- ¿Qué es la voz cuando una palabra mal elegida medicaliza al usuario? Vocabulario clínico prohibido en producto público.
Norte está construido respondiendo a estas cinco preguntas con disciplina. El resto del documento explica cómo.
02 — Los cuatro pilares no negociables
Antes de entrar en el sistema, las cuatro decisiones de producto que el resto de arquitectura sirve. Si alguna se rompe, el producto deja de funcionar como tesis.
Decision Elimination
Una sola tarea visible a la vez. La pantalla principal no tiene lista de tareas. No tiene backlog. No tiene “ver más”. El usuario abre Norte y ve una frase, un botón, nada más. El componente <DecisionWidget /> materializa este pilar: H1 con la tarea, un botón “Hecho”, silencio alrededor.
Flow Lock
Cuando Norte detecta flow (hiperfoco), bloquea la app. El usuario que abre la app durante una sesión de trabajo intenso recibe: “Estás en flow. Norte vuelve después.” Sin botón de cierre. Auto-cierra en 3 segundos. No registra la apertura como uso. Es una interrupción rechazada, no un evento de engagement.
Para un Design System Architect senior esta decisión es la más subrayable: una app que detecta que no la necesitas y se cierra sola es la inversión exacta del modelo de retención estándar. La empresa que mide DAU/MAU como KPI primario no construye Flow Lock.
AI Refusal Layer
El coach IA del producto rechaza preguntas de reaseguración compulsiva antes de llamar al LLM. “¿Lo estoy haciendo bien?” no llega al modelo. Una capa de reglas regex detecta el patrón, devuelve una respuesta fija que no alimenta la compulsión, y no registra la interacción en el historial conversacional.
Esto exige decisión arquitectónica: el LLM no es input universal, es servicio condicionado por una capa de control previa. Detalle en §05.
Anti-compulsion Design
Cuatro restricciones operativas codificadas como componentes del sistema:
- Rate-limit de aperturas: más de 6 por hora → cooldown de 12 minutos.
- Widget timeout: ningún widget permanece más de 8 minutos. Auto-cierra.
- Batch windows: información solo en 3 ventanas diarias (09:00, 14:00, 20:00). Fuera, se acumula.
- Cero métricas consultables: el usuario no puede ver cuántas veces abrió Norte, cuánto tiempo pasó, qué porcentaje cumplió.
Cada una merece su propia sección. Las cuatro juntas son la diferencia entre un producto de bienestar que funciona y uno que se convierte en otra adicción más ligera.
03 — El sistema se mide por lo que oculta
Aquí está la decisión más subrayable del proyecto para un Design System Architect senior.
La mayoría de design systems documentan qué construyen. Norte documenta qué rechaza construir. Esto exige inversión disciplinaria que pocos productos consumer toman.
Lo que la app móvil no tiene
| No construido | Por qué |
|---|---|
| Settings dentro de la app | Cada toggle es una decisión. La disfunción ejecutiva convierte cada decisión en coste de energía. |
| Dashboard con métricas | Ver “cumpliste 4/7 días esta semana” refuerza checking compulsivo. |
| Lista de tareas con scroll | Backlog visible activa ansiedad de procesamiento. Una sola tarea, ninguna lista. |
| Historial de coach | Releer conversaciones es comportamiento compulsivo, no reflexivo. |
| Notificaciones reactivas | Notificación por cada acción del usuario es vector de checking. |
| Badges, racha, gamificación | El refuerzo por logro convierte el producto en máquina tragaperras. |
| Pull-to-refresh | El gesto refuerza expectativa de novedad constante. |
| Streams consultables | Cualquier feed scrollable es invitación a compulsión. |
Lo que se mueve a la web
Configuración, analytics futuros, informes descargables, gestión de cuenta. El móvil ejecuta, la web configura. Esta separación no es producto-management estándar (las apps modernas duplican superficies para mantener al usuario en una sola plataforma). Es decisión de DS al servicio de tesis: cuando el dispositivo móvil está pegado al cuerpo, debe contener lo mínimo necesario para ejecutar, no para deliberar.
Para un DS senior
La lectura es directa. Cuando un sistema documenta lo que rechaza con la misma disciplina que documenta lo que incluye, la coherencia del producto deja de depender de la voluntad del operador. Cada feature request futura pasa por filtro objetivo: ¿esto rompe alguno de los cuatro pilares? Si la respuesta es sí, no se construye, aunque parezca evidente que “ayuda al usuario”.
Esto es DS bien resuelto aplicado al rol más difícil: el DS como guardián de la tesis del producto, no como ejecutor de features.
04 — Widgets, no pantallas: el componente principal del sistema
El componente principal de Norte no es una pantalla. Es un widget: pieza efímera que aparece cuando el motor de decisión lo decide, ejecuta su función, y desaparece.
Ocho tipos de widget + idle
| Widget | Trigger | Comportamiento |
|---|---|---|
cooldown | >6 aperturas/hora | Bloquea la app 12 min. “Es feature, no bug.” |
flow_protected | Flow lock activo + apertura | ”Estás en flow.” Auto-cierra 3s. Sin botón. |
batch_report | Ventana horaria (09/14/20h) | 3 bullets máximo. 1 vez por ventana. |
meal | Ventana de comida ±30 min | Plato concreto rotativo (7 por tipo). Botón “Hecho”. |
workout | Toca entreno hoy | Lanza sesión. Router push a /workout/start. |
breath | HRV rojo / estrés | 4-7-8 guiado, 3 ciclos, autocierra. |
decision | Default con tarea activa | Una frase H1. Un botón “Hecho”. Nada más. |
null (idle) | Sin tarea ni contexto | Solo texto en pantalla. Sin widget. |
Lo que distingue widget de pantalla
Una pantalla invita a explorar. Tiene navegación, tabs, breadcrumbs, scroll, historial. El usuario entra y decide cuánto tiempo permanece, qué consulta, qué consume.
Un widget aparece, cumple su función y desaparece. No hay historial de widgets. No hay “ver widgets anteriores”. No hay breadcrumbs. El usuario no navega por widgets — el motor de decisión presenta exactamente uno.
Para un DS senior la decisión es operativa: cuando el componente principal del sistema es efímero por diseño, todo el resto del sistema se simplifica. No hay router complejo. No hay estado global de “pantalla actual”. No hay deeplinks profundos. Solo hay tarea visible o no.
Timeout como propiedad estructural
Todos los widgets tienen timeout máximo de 8 minutos. Si quedan abiertos por bug o inacción del usuario, auto-cierran. Esto previene el caso más sutil de daño: un modal que atrapa al usuario en estado de procesamiento indefinido.
Esto es decisión de DS que merece subrayar para cualquier producto que sirva audiencia neurodivergente: no asumas que el usuario va a cerrar lo que abriste. Si tu sistema abre algo, tu sistema lo cierra.
05 — La capa de rechazo: cuando el sistema dice “no” antes del LLM
Esta es la pieza más distintiva del producto y la que merece más atención de cualquier DS lead que opere productos con IA conversacional.
El problema
Las personas con perfiles OCD/TDAH/2e usan chats de IA como herramienta de reaseguración compulsiva:
- “¿Lo estoy haciendo bien?”
- “¿Seguro que no me equivoco?”
- “¿Debería comprobar otra vez?”
- “¿Qué pasa si no estoy haciendo lo correcto?”
Responder estas preguntas — incluso respondiéndolas bien — refuerza la compulsión. El usuario obtiene alivio temporal. La próxima vez vuelve antes y con más urgencia. El ciclo es conocido en clínica como reassurance seeking y la respuesta terapéutica estándar es ERP (Exposure and Response Prevention): no responder a la pregunta.
La solución arquitectónica
Norte intercepta estas preguntas antes de llamar al LLM. Cinco reglas con trece patrones regex detectan el tipo:
doing_right— preguntas sobre estar haciendo lo correcto.double_check— solicitudes de verificación adicional.sure— peticiones de confirmación de certeza.what_if— espirales contrafactuales.recheck— comprobaciones repetidas sobre lo mismo.
Cada regla tiene filtro de longitud máxima (60-120 caracteres) para evitar falsos positivos en mensajes largos donde la pregunta aparece como parte de una reflexión legítima.
El detalle del determinismo
Cuando una pregunta matchea una regla, la respuesta se selecciona deterministicamente vía hash del mensaje. Sin randomness. Misma pregunta → misma respuesta. Esto es crítico: el usuario que pregunta dos veces lo mismo no recibe variación que pueda interpretar como información nueva. La respuesta es estable, lo que la convierte en feedback claro de que el sistema no va a responder al patrón.
La interacción no se registra
Cuando el sistema detecta reaseguración compulsiva y responde con la línea fija, no registra la interacción en el historial conversacional. El usuario que abre el coach mañana no ve “ayer preguntaste si lo estabas haciendo bien”. El patrón no se acumula como contexto.
Esto es decisión arquitectónica con consecuencias claras: el historial del coach es activo curado, no log de todo lo que el usuario escribió. El sistema decide qué entra al historial.
Por qué esto es DS y no producto
Tres consecuencias.
Vocabulario codificado. Las cinco reglas + trece patrones son tokens de detección. Cuando aparece un nuevo patrón compulsivo en producción, se añade al regex. La protección mejora retroactivamente para todos los usuarios sin intervención manual.
Respuestas como pieza editorial. Las respuestas fijas están escritas con voz pautada. No son disclaimers legales (“como AI no puedo…”). Son frases editoriales:
“No necesitas confirmación. Sigue con lo que estabas haciendo.”
Voz directa, sin medicalización, sin acusación al usuario. Para un DS senior es voz editorial codificada al nivel del sistema, equivalente a la sanitización en dos capas de lavigencia o el vocabulario prohibido de bodados.
Unicode y acentos correctamente manejados. Detalle pequeño que separa al sistema funcional del sistema regresivo: JavaScript \b es ASCII-only. Sin soporte explícito de acentos (é, í, á), una pregunta en castellano correcto se escapa de la detección. El sistema maneja esto explícitamente. La voz del producto es es-ES, así que el detector lo es también.
Posicionamiento responsable
El sistema está basado en principios de ERP trasladados a producto, sin claims médicos, posicionado explícitamente como wellness. Esto es decisión de marca que merece subrayar en cualquier producto que toque salud mental: el rigor terapéutico se preserva en la arquitectura, no en el marketing.
06 — Rate-limit como feature, no como castigo
Una de las decisiones operativas más visibles del producto: más de 6 aperturas por hora dispara un cooldown de 12 minutos. La séptima apertura no carga la pantalla principal. Carga el componente <CooldownWidget /> con copy directa que comunica la decisión.
El razonamiento
Seis aperturas por hora es generoso para uso legítimo de un producto que se posiciona como “una decisión visible”. Si el usuario abre Norte siete veces en una hora, la séptima señal no es necesidad funcional — es checking compulsivo. Responder a esa apertura cargando la pantalla principal refuerza el ciclo.
El cooldown no es castigo. Es intervención de diseño. La copy lo declara explícitamente: “Es feature, no bug.”
Cómo se implementa
Cada apertura se registra con timestamp en almacenamiento local persistente (MMKV). El sistema mantiene la ventana de la última hora con cap defensivo de 50 entries para evitar uso patológico que rompa el storage. Cuando el contador llega a 6 en la ventana móvil, el motor de decisión devuelve widget: 'cooldown' independientemente del resto del contexto.
Lo que el cooldown no es
- No es deshabilitar la app. Las funciones críticas del sistema (notificaciones programadas para batch windows, flow detection) siguen activas en segundo plano.
- No es un timer visible. El usuario no ve “8 min 23s restantes”. Vería el contador como recurso a manipular. Solo ve “Norte vuelve más tarde” sin precisión temporal.
- No es escalable. Después del cooldown, el contador se resetea. No hay “ahora 3 horas porque has insistido”. El sistema no castiga, intercepta el patrón puntualmente.
Para un DS lead
La pregunta operativa replicable: ¿qué patrón de uso de tu producto indica daño y no engagement? Si tu sistema tiene métricas que correlacionan con bienestar negativo del usuario, ese patrón es candidato a intervención de diseño antes que a optimización para engagement.
Aplicable a cualquier producto consumer que toque comportamiento compulsivo: redes sociales, trading apps, dating, news feeds, e-commerce con scarcity. El patrón del rate-limit anti-compulsión es replicable. Lo que cuesta es el coraje de aplicarlo.
07 — Batch windows: información agrupada, no on-demand
La regla operativa: Norte solo reporta cambios en tres ventanas diarias (09:00, 14:00, 20:00). Fuera de esas ventanas, la información se acumula. Una vez mostrada, no se repite ese día.
Por qué esto es decisión de DS
La intuición clásica de producto dice que la información debe estar disponible cuando el usuario la solicite. Pull-to-refresh es estándar. Notificación inmediata por cada cambio relevante es estándar. Stream consultable 24/7 es estándar.
Norte rompe los tres estándares. Información batched no on-demand. Cero notificaciones reactivas. Cero stream consultable.
El razonamiento: cuando un usuario con disfunción ejecutiva tiene acceso a “ver lo último” en cualquier momento, el acto de consultar consume el presupuesto de energía que debería ir a ejecutar. La satisfacción de revisar reemplaza el trabajo real. El stream se convierte en compulsión disfrazada de productividad.
Las tres ventanas son la cantidad mínima de exposición a información agregada que un día humano tolera sin perder contexto. Más sería ruido. Menos sería ceguera.
Cómo se implementa
El motor de decisión consulta hora local del usuario y devuelve widget: 'batch_report' solo si:
- La hora está dentro de la ventana (±30 minutos de las 09:00, 14:00 o 20:00).
- El usuario abrió la app durante la ventana (no se interrumpe fuera).
- Hay información acumulada que reportar.
- No se ha mostrado el batch report de esta ventana hoy.
Una vez mostrado, el flag se persiste en MMKV con clave last_batch_window_shown:{YYYY-MM-DD}:{window}. La misma ventana no se repite. La siguiente se desbloquea solo al cruzar la hora.
Tres bullets máximo
El widget muestra 3 bullets máximo. No 5, no 10, no “ver más”. Si hay más información acumulada de tres puntos relevantes, el sistema prioriza y descarta. La pérdida de información de baja prioridad es coste aceptado a cambio de respetar el límite cognitivo del usuario.
Para un DS senior la decisión es operativa: cuando defines un límite duro, lo cumples siempre. El sistema que tiene “3 bullets máximo… excepto si hay info crítica que muestra 4” deja de ser sistema y se convierte en suma de excepciones.
08 — El motor de decisión: prioridad determinista
Toda la lógica anterior converge en una pieza arquitectónica: el hook useNorteDecision() que evalúa contexto y devuelve un único { widget, payload }.
Orden de prioridad estricto
1. cooldown — anti-compulsión es prioridad absoluta
2. flow_protected — proteger el flow supera todo
3. batch_report — información batched, no on-demand
4. meal — ventana temporal con plato concreto
5. workout — si toca y HRV lo permite
6. breath — HRV bajo, intervención suave
7. decision — la tarea visible por defecto
8. idle (null) — nada que hacer, silencio
Por qué este orden
Cada nivel del orden codifica una decisión de marca:
Cooldown primero. El usuario en patrón compulsivo es el usuario más necesitado de intervención. Su decisión personal de “abrir Norte siete veces en una hora” no se respeta como input legítimo; se interpreta como síntoma. Mostrar una tarea durante un cooldown rompería la propia tesis del producto.
Flow segundo. Cuando el usuario está produciendo a niveles altos, interrumpirlo es daño, aunque la interrupción sea bienintencionada. El sistema prioriza protegerlo sobre cualquier información que el sistema considerara relevante.
Batch en tercero. Antes de mostrar tarea individual, el sistema ofrece la imagen agregada del momento si toca ventana. La información estructurada precede a la siguiente acción concreta.
Meal antes que workout antes que breath. El cuerpo precede a la mente. La regulación nerviosa (breath) es la última intervención porque las anteriores (comer, moverse, completar tarea) son las que típicamente resuelven el malestar sin necesidad de técnica específica.
Decision como default. Si no toca cooldown, ni flow, ni batch, ni cuerpo, el sistema vuelve a la tesis básica: una tarea visible. Una decisión.
Idle como output legítimo. No hay tarea, no toca nada → solo texto en pantalla. Sin widget. El producto acepta el silencio como respuesta válida.
Para un DS senior
La pregunta replicable: ¿tu sistema tiene orden de prioridad determinista entre componentes que compiten por el espacio principal? Si la respuesta es “depende del contexto”, la coherencia del producto depende de la interpretación de cada situación. Si la respuesta es una lista numerada explícita, la coherencia es estructural.
Norte tiene la lista numerada explícita. Es la diferencia entre app que se siente coherente y app que se siente caótica.
09 — Tokens y design system visual
Norte tiene design system formalizado con disciplina inusual para una app pre-lanzamiento. Pivot desde paleta light (estilo Headspace inicial) a paleta dark con una sola accent, decisión de DS al servicio de la tesis.
Paleta dark editorial
Backgrounds Text
───────────────────────────────── ─────────────────────────────
bg.primary #0B0B0E near-black text.primary #F5F2EC warm off-white
bg.secondary #15151A elevation 1 text.secondary #A8A39A warm medium
bg.tertiary #1F1F26 elevation 2 text.tertiary #6E6962 warm muted
bg.elevated #27272F elevation 3 text.faint #3F3B36 hairlines
Accents Borders
───────────────────────────────── ─────────────────────────────
accent.bone #E8E2D4 warm bone border.subtle #222226
accent.alert #D97757 terracotta border.strong #33333A
accent.calm #7FA88A sage green
Una sola accent: la decisión más radical del DS
Múltiples colores de accent crean jerarquías que invitan a comparar, priorizar, elegir. Cada decisión de “¿este es el botón importante?” consume energía. Norte tiene una sola accent (bone) para todos los CTAs, textos destacados, botones primarios.
Terracotta y sage existen exclusivamente como semáforos de estado corporal (alerta o calma) — nunca para CTAs. Esta separación estricta es la versión más radical de la regla “color como token semántico, no decorativo” que aparece en otros casos de la serie.
La consecuencia: cualquier diseñador externo que reciba el sistema y proponga “un segundo botón verde para destacar X” recibe una respuesta de DS: “no”. El sistema no acepta segundas opciones de accent porque romper la regla rompe la tesis.
Tipografía Sora en todas las superficies
Sora como única familia tipográfica para display, sans y body. Sin secundaria sans. Sin transición entre familias.
Leading global de 1.4 (más respiración que el estándar 1.2). Decisión deliberada al servicio del usuario: el texto con más aire reduce carga cognitiva. El usuario con disfunción ejecutiva lee mejor con interlineado generoso.
JetBrains Mono solo aparece en la web (para código en futuras secciones técnicas). En la app móvil, Sora cubre todos los casos.
Reglas de uso codificadas
El sistema documenta explícitamente:
accent.bone→ única accent para CTAs, textos destacados, botones.accent.alert(terracotta) → exclusivamente para estados corporales que requieren acción.accent.calm(sage) → exclusivamente para estados corporales positivos.- Nunca se usan colores para gamificación, badges o engagement loops.
La última regla es la que cualquier diseñador formado en design systems clásicos rompería sin pensarlo. Norte la codifica como invariante del sistema.
10 — La autenticación como pieza arquitectónica
Detalle técnico que merece subrayar para cualquier DS lead que opere productos cross-platform: Norte construye autenticación propia con cero dependencias externas, usando Web Crypto API y HMAC-SHA256.
Tres tipos de token con TTL distinto
| Token | TTL | Transporte | Uso |
|---|---|---|---|
| Magic link | 15 min | URL param | Email → web login |
| Sesión web | 90 días | Cookie HttpOnly Secure SameSite=Lax | Dashboard web |
| Device token | 1 año | Bearer header · MMKV en móvil | Bridge móvil↔web |
Por qué esto es decisión de DS y no de plomería
Tres consecuencias.
Sin SDK de auth externo (Supabase, Firebase, Auth0, Clerk). Norte se compromete con Cloudflare Pages + Workers, y la autenticación queda como código propio del proyecto. No hay vendor lock-in en auth.
Edge-compatible nativo. Web Crypto API funciona en Cloudflare Workers sin polyfills. Cero cold-start adicional por auth. Cero coste recurrente por usuario activo.
Bridge móvil↔web limpio. La web genera un device token vía endpoint que intercambia cookie por Bearer. El móvil lo captura por deep link (lorsbio://auth?token=...) o Universal Link. El token se persiste en MMKV y sirve para sincronizar perfil y futuras llamadas autenticadas.
Para un DS senior la lectura es operativa: cuando construyes un sistema con disciplina de simplicidad, auth es uno de los componentes que más cuesta no externalizar. Norte demuestra que con Web Crypto + HMAC-SHA256 + tokens con TTL explícito, el sistema es portable y libre de dependencias críticas.
11 — Stripe sin SDK: edge-first commerce
Patrón replicable que merece subrayar.
Norte usa Stripe vía REST directo, sin SDK, porque el SDK oficial de Stripe no es edge-compatible. El producto vende en tres modos:
- Norte Pro Anual €129/año
- Norte Pro Mensual €14,99/mes con trial de 14 días
- Lifetime Cohorte Fundadora €299 una sola vez, 200 plazas
El flujo en cinco pasos
/empezar?plan=lifetime
↓
POST /api/checkout {plan: "lifetime", email}
↓
Stripe Checkout Session (REST directo, mode: "payment", €299)
↓ (usuario paga)
Stripe → POST /api/stripe-webhook
↓ (checkout.session.completed verificado por firma)
├── sendMagicLink(email) → email con link de acceso
├── notifyJoan(email, plan) → notificación interna
└── incrementCount() → KV founder counter +1
↓
Usuario click magic link → /api/auth/verify → cookie → /app
Lo que se descubre del flujo
El producto no crea cuenta antes de pagar. La cuenta nace del pago. Esto elimina superficie de “registrarse → confirmar email → log in → comprar” que la mayoría de productos imponen como tres a cinco pasos.
El magic link llega tras el pago. El usuario hace click una vez. La cookie de sesión queda en el navegador 90 días. La cuenta existe a partir de ese momento.
Para un DS senior la lectura es directa: cuando tu producto define cuándo nace la cuenta, controlas el journey entero. Cuando aceptas el modelo estándar de “primero regístrate, después convierte”, cedes ese control al precedente del sector.
El contador live de cohorte fundadora
/api/founder-count lee del KV de Cloudflare y devuelve plazas ocupadas. La landing renderiza progreso visible: “X de 200 plazas ocupadas”. La urgencia es honesta (200 plazas es real, no scarcity manufacturada), el contador es source of truth servido desde edge.
Detalle de implementación: el contador se incrementa solo desde el webhook de Stripe, después de verificar firma. No hay manipulación posible desde cliente. Esta es disciplina de DS aplicada a UX de commerce: la confianza del usuario en el contador depende de que el contador no pueda mentir.
12 — La landing como exposición ordenada de la tesis
todoennorte.com tiene 13 secciones ordenadas que exponen la tesis del producto sin pedir nada al usuario hasta la sección 11 (pricing). La estructura merece descomponerse porque es lectura del oficio editorial aplicado a producto consumer.
Las 13 secciones
| # | Sección | Función |
|---|---|---|
| 1 | Hero | Video background + tagline + CTA. Eyebrow: “Para cabezas brillantes y caóticas” |
| 2 | FloatingNav | Navegación sticky mínima |
| 3 | PhoneShowcase | Mockup de la app text-first |
| 4 | Problem | ”Tu cabeza no para. Tu sistema de productividad tampoco.” |
| 5 | DayInFiveMoments | 6 momentos del día mostrando los 4 pilares en acción |
| 6 | NoCommitments | 6 promesas (incluye refusal layer + rate-limit como features) |
| 7 | ForIntenseMinds | TDAH/AC/2e nombrado sin medicalización |
| 8 | FounderStory | Historia personal de Joan |
| 9 | Inside | 8 features: 4 pilares + 4 sistemas |
| 10 | Roadmap | Suite futura: Norte · Move · Sleep · Pause · Calm |
| 11 | Pricing | Toggle anual/mensual + card lifetime fundadora con contador live |
| 12 | FAQ | Preguntas frecuentes |
| 13 | Footer | Links legales + contacto |
La sección crítica: NoCommitments
La sección 6 es la que merece más atención del documento. Las restricciones del producto se exponen como features:
- “Norte rechaza preguntas de reaseguración compulsiva.”
- “Norte bloquea más de 6 aperturas por hora con un cooldown.”
- “Norte se cierra cuando detecta flow.”
- “Norte no tiene dashboard, no tiene métricas, no tiene historial.”
Esto es decisión de comunicación que cualquier marketer convencional contradiría. Lo natural sería ocultar lo que la app no hace. Norte hace lo opuesto: declara explícitamente lo que rechaza hacer y lo presenta como ventaja competitiva.
Para un DS senior la lectura: cuando la disciplina del sistema es radical (cero settings, cero engagement loops, una sola accent), la comunicación honesta de esa disciplina es activo de marca. Los usuarios que entienden la tesis se quedan. Los que esperan otro producto se van. La auto-selección reduce churn antes de que el churn exista.
ForIntenseMinds: nombrar sin medicalizar
La sección 7 nombra TDAH, altas capacidades y 2e como audiencia primaria sin caer en lenguaje clínico ni en promesas terapéuticas. La copy se posiciona como wellness con rigor, no como dispositivo médico.
Cita literal del eyebrow del hero: “Para cabezas brillantes y caóticas”. La voz combina dos registros (brillantes + caóticas) que el usuario reconoce como descripción honesta de sí mismo sin sentirse diagnosticado por una app.
Esta es decisión de marca que cualquier producto que toque salud mental debe tomar consciente: la línea entre nombrar al usuario para que se reconozca y nombrarlo desde su patología hay que mantenerla con disciplina editorial. Norte está del lado correcto.
13 — Lo que NO se construyó
Para un Design System Architect senior esta sección suele ser la más útil del documento. En el caso de Norte es la pieza central.
| No construido | Por qué | Qué ocupó su lugar |
|---|---|---|
| Settings dentro de la app | Cada toggle es una decisión. La disfunción ejecutiva convierte cada decisión en coste. | Configuración exclusivamente en la web. El móvil ejecuta. |
| Dashboard con métricas consultables | Ver “cumpliste X días” refuerza checking compulsivo. | Cero superficie de métricas en móvil. Web tiene analytics futuros con disciplina distinta. |
| Lista de tareas con scroll | Backlog visible activa ansiedad de procesamiento. | Una sola tarea visible (<DecisionWidget />). |
| Historial de coach conversacional | Releer conversaciones es comportamiento compulsivo. | Historial curado: las respuestas de refusal no entran. |
| Notificaciones reactivas | Vector de checking compulsivo. | Información solo en 3 batch windows diarias. |
| Badges, racha, gamificación | Convierten el producto en máquina tragaperras. | Sin sistema de logros. |
| Pull-to-refresh | Gesto que refuerza expectativa de novedad. | Sin gesto disponible. |
| Streams consultables | Cualquier feed scrollable es invitación a compulsión. | Cero superficie scrollable. |
| Múltiples colores de accent | Crean jerarquías que invitan a comparar. | Una sola accent (bone) para todos los CTAs. |
| Settings de notificación granulares | Cada toggle es decisión. | Comportamiento del sistema es fijo. |
| Onboarding largo con tour de features | Imposible procesar 7 pantallas de tutorial. | Onboarding mínimo en web pre-pago. La app se entiende usándola. |
| Modo oscuro / claro toggleable | Decisión innecesaria. La app es dark editorial. | Dark fijo. No es preferencia, es identidad de marca. |
| App nativa para Android | El usuario primario está en iOS. Fragmentar plataformas multiplica deuda. | Solo iOS + web. Android posible si la cohorte fundadora lo demanda con datos. |
| Apple Watch / Wearable companion | Una pantalla extra que consulta es vector adicional. | Sin app de watch. |
| Integración con otras apps de productividad | Norte es la app, no se integra con la competencia que rompe la tesis. | Producto cerrado. |
El patrón
Cada “no” preserva una decisión más profunda: Norte es sistema operativo para mentes con perfil específico, no app de productividad genérica. Aplicación rigurosa del “you are what you say no to” llevada al extremo.
Para un DS senior cada “no” se traduce en componentes que no se construyen, pantallas que no existen, settings que no hay que mantener. El producto es radicalmente más simple porque la lista de noes es radicalmente más larga.
14 — Voz editorial codificada en sistema
Norte tiene voz editorial pautada que vive en tres lugares del sistema.
En las respuestas fijas del refusal layer
“No necesitas confirmación. Sigue con lo que estabas haciendo.”
Voz directa, sin medicalización, sin disclaimer legal, sin acusación. La respuesta es activo editorial codificado. Cada nueva respuesta del refusal layer pasa por el mismo filtro de voz.
En el copy de los widgets
- Cooldown: “Es feature, no bug.”
- Flow protected: “Estás en flow. Norte vuelve después.”
- Meal: “Lo eligió Norte. Ya está todo en la nevera.”
Frases con voz reconocible. Funcionales (informan), editoriales (suenan a marca), respetuosas con el usuario (no infantilizan).
En la landing pública
Once frases citables del producto vivo:
- “Para cabezas brillantes y caóticas.”
- “Tu cabeza no para. Tu sistema de productividad tampoco.”
- “Una sola tarea visible a la vez.”
- “El sistema operativo para mentes de alta agencia con disfunción ejecutiva.”
- “Norte decide cuándo aparecer.”
- “Lo eligió Norte. Ya está todo en la nevera.”
- “Es feature, no bug.”
- “Norte vuelve después.”
- “Sin lista, sin backlog, sin ‘ver más’.”
- “Cero opciones de customización desde la app.”
- “Información solo en tres ventanas diarias.”
Tres registros conviven: clínico-respetuoso (nombra TDAH/2e sin patologizar), operativo (declara qué hace el sistema), íntimo (habla al usuario que se reconoce). La densidad por línea es alta. El cliché está prohibido.
Por qué esto es DS y no marketing
Si la voz solo vive en el cerebro del fundador, cada texto nuevo (nueva sección de landing, nueva respuesta del refusal, nuevo widget) la degrada. Si vive como pauta operativa (respuestas fijas, copy estable por widget, vocabulario aprobado), la voz sobrevive a la fatiga del fundador y a colaboraciones futuras.
Norte está en pre-lanzamiento, operado por un fundador único. La codificación de la voz como sistema parece sobreingeniería ahora. La razón de hacerlo ahora es la opuesta: es el momento más fácil para codificarla, antes de que crezca el equipo o el corpus de copy.
15 — Lo que un DS Architect senior se lleva de aquí
Cinco decisiones aplicables a tu propio sistema, ordenadas por dificultad creciente.
1. Documentar lo que el sistema rechaza con la misma disciplina que lo que incluye (fácil)
Si tu producto tiene tesis clara, documentar explícitamente las features que no se construyen y por qué es activo de DS. Cada feature request futura pasa por filtro objetivo. Aplicable a cualquier producto consumer con disciplina editorial.
2. Una sola accent para todo el sistema (fácil-medio)
Si tu producto codifica jerarquía con color, fuerza disciplina: una sola accent para todos los CTAs. Las secundarias existen solo para señalética (estados de error, success, warning), nunca para variedad estética. Reduce decisiones tanto del usuario como del operador.
3. Widgets efímeros en lugar de pantallas persistentes (medio)
Cuando tu sistema sirve a usuarios que sobrecargan de información (atención fragmentada, ansiedad de checking, audiencias neurodivergentes), considera widgets con timeout máximo en lugar de pantallas con historial. El componente principal del sistema cambia. La complejidad de routing cae. El usuario consume lo necesario y vuelve a su vida.
4. Rate-limit y cooldown como features anti-compulsión (medio-difícil)
Cuando tu producto puede ser usado en patrón compulsivo, el rate-limit que detecta el patrón e interrumpe es intervención de diseño, no castigo. Aplicable a redes sociales, trading apps, news feeds, e-commerce con scarcity, dating apps. La pregunta operativa: ¿qué patrón de uso correlaciona con daño en mi usuario y no con engagement saludable?
5. Capa de rechazo antes del LLM (difícil)
Si tu producto incorpora IA conversacional, considera una capa de reglas que rechaza ciertos patrones de input antes de llamar al modelo. No por seguridad (que ya hace el modelo), sino por bienestar del usuario (cortar reaseguración compulsiva, evitar reforzar dependencias parasociales, no responder a preguntas cuya respuesta daña). Es la pieza más difícil porque exige decidir conscientemente que tu producto no responde a algunas preguntas aunque pudiera. La mayoría de productos no toma esa decisión nunca.
Esta última es la pregunta que va a separar al equipo que construye productos consumer responsables del equipo que añade chatbots a todo en los próximos 18 meses.
16 — Anexo técnico
Para quien quiera verificar las afirmaciones del documento contra el código.
Stack
| Capa | Tecnología |
|---|---|
| Mobile runtime | React Native 0.76 + Expo SDK 52 + Expo Router |
| Mobile state | MMKV (persistencia local) + useSyncExternalStore (singleton stores) |
| Mobile animations | Reanimated 3 (FadingText cross-fade, TypingDots, WidgetHost scale) |
| Web framework | Next.js 14 App Router con output: 'export' (full static) |
| Web styling | Tailwind CSS 3 con paleta dark custom |
| Edge functions | Cloudflare Pages Functions (TypeScript, Web Crypto API) |
| Auth | Magic link + HMAC-SHA256 tokens (Web Crypto, zero deps) |
| Resend API (transactional) con DKIM server-side, SPF/DMARC alineado | |
| Pagos | Stripe Checkout Sessions vía REST directo (sin SDK, edge-compatible) |
| KV storage | Cloudflare KV (perfil de usuario, contador de cohorte fundadora) |
| Fonts | Sora (display + sans) + JetBrains Mono (mono web) |
| CI / Build | pnpm workspaces + TypeScript strict + Expo EAS Build |
Estructura del monorepo
bios/
├── apps/
│ ├── mobile/ # React Native + Expo SDK 52 + Expo Router
│ ├── web/ # Next.js 14 (static export) → Cloudflare Pages
│ └── api/ # (reservado para futura API dedicada)
├── packages/
│ ├── shared/ # Design tokens, tipos compartidos
│ └── db/ # (reservado para schema de base de datos)
└── pnpm-workspace.yaml
Números del repositorio
- Archivos
.ts/.tsx: aproximadamente 110 (mobile src + web app) - Build actual: #77
- Dependencias externas para auth: 0 (Web Crypto API nativo)
- SDK de Stripe en edge: 0 (REST directo, edge-compatible)
- Reglas de refusal: 5 reglas + 13 patrones regex
- Tipos de widget: 8 + null (idle)
- Ventanas de batch: 3 al día (09:00, 14:00, 20:00)
- Cap anti-compulsión: 6 aperturas por hora
- Timeout de widget: 8 minutos máximo
- Token TTL magic link: 15 minutos
- Token TTL sesión: 90 días
- Token TTL device: 1 año
- Plazas cohorte fundadora: 200
Endpoints serverless (Cloudflare Pages Functions)
| Endpoint | Método | Función |
|---|---|---|
/api/auth/magic | POST | Genera magic link, envía email vía Resend |
/api/auth/verify | GET | Verifica token, crea sesión, redirect /app |
/api/auth/me | GET | Lee sesión (cookie o Bearer) |
/api/auth/logout | POST | Borra cookie de sesión |
/api/auth/device-token | GET | Intercambia cookie web → Bearer móvil |
/api/profile | GET/PUT | CRUD perfil en Cloudflare KV |
/api/checkout | POST | Crea Stripe Checkout Session (annual/monthly/lifetime) |
/api/stripe-webhook | POST | Verifica firma Stripe, envía magic link + notifica |
/api/waitlist | POST | Captura lead plan-aware, notifica a Joan |
/api/founder-count | GET | Contador de plazas cohorte fundadora (KV) |
Reglas del refusal layer
| Regla | Pattern típico | Respuesta fija |
|---|---|---|
doing_right | ”¿lo estoy haciendo bien?" | "No necesitas confirmación. Sigue con lo que estabas haciendo.” |
double_check | ”¿debería comprobar otra vez?” | Línea fija con voz Norte |
sure | ”¿seguro que está bien?” | Línea fija con voz Norte |
what_if | ”¿qué pasa si me equivoco?” | Línea fija con voz Norte |
recheck | ”¿puedo revisarlo otra vez?” | Línea fija con voz Norte |
Cinco reglas con trece patrones totales. Selección de respuesta determinista vía hash del mensaje (sin randomness). Soporte explícito de Unicode/acentos (é, í, á) para castellano.
Motor de decisión
useNorteDecision() devuelve { widget, payload }
Orden de prioridad determinista:
1. cooldown ← anti-compulsión es prioridad absoluta
2. flow_protected ← proteger el flow supera todo
3. batch_report ← información batched, no on-demand
4. meal ← ventana temporal con plato concreto
5. workout ← si toca y HRV lo permite
6. breath ← HRV bajo, intervención suave
7. decision ← la tarea visible por defecto
8. idle (null) ← nada que hacer, silencio
Verificación reproducible
# Inventario de archivos TypeScript
find apps/mobile/src apps/web/app -name "*.ts" -o -name "*.tsx" | wc -l
# → ~110
# Build actual en app.json
grep -E '"buildNumber":' apps/mobile/app.json
# → "buildNumber": "77"
# Tipos de widget
grep -E "widget.*=" apps/mobile/src/engine/norteEngine.ts | grep -oE "'[a-z_]+'" | sort -u
# → 'batch_report', 'breath', 'cooldown', 'decision', 'flow_protected', 'meal', 'workout' + null
# Reglas de refusal
grep -cE "rule:" apps/mobile/src/coach/coachRefusal.ts
# → 5
# Cap de aperturas
grep -E "MAX_OPENS_PER_HOUR" apps/mobile/src/engine/norteEngine.ts
# → MAX_OPENS_PER_HOUR = 6
# Ventanas de batch
grep -E "BATCH_WINDOWS" apps/mobile/src/engine/norteEngine.ts
# → [9, 14, 20]
# Plazas cohorte fundadora
grep -E "FOUNDER_LIMIT" apps/web/app/api/founder-count/route.ts
# → FOUNDER_LIMIT = 200
# Endpoints serverless
ls apps/web/functions/api/**/*.ts | wc -l
# → 10
URLs públicas verificables:
- Landing pública:
https://todoennorte.com - Pricing con contador live:
https://todoennorte.com/#pricing - Endpoint público del contador:
https://todoennorte.com/api/founder-count - Dashboard web tras login:
https://todoennorte.com/app
Roadmap declarado (suite Norte)
| App | Función | Estado |
|---|---|---|
| Norte | Sistema operativo diario (decisiones, flow, coach) | Build #77, pre-lanzamiento |
| Move | Entrenamiento integrado con energía y HRV | Planificado |
| Sleep | Optimización de sueño sin tracking nocturno compulsivo | Planificado |
| Pause | Respiración y regulación nerviosa | Planificado |
| Calm | Journaling guiado (ERP-informed, no libre) | Planificado |
Glosario
| Término | Definición canónica |
|---|---|
| Decision Elimination | Pilar 1. Una sola tarea visible. Sin lista, sin backlog. |
| Flow Lock | Pilar 2. La app se cierra cuando detecta hiperfoco activo. |
| AI Refusal Layer | Pilar 3. Capa de reglas que rechaza preguntas de reaseguración antes del LLM. |
| Anti-compulsion Design | Pilar 4. Restricciones operativas codificadas (rate-limit, timeout, batch windows). |
| Widget | Componente efímero de la app que aparece, ejecuta y desaparece. Ocho tipos + idle. |
| Batch window | Ventana horaria fija (09:00, 14:00, 20:00) en que se reporta información agregada. |
| Cooldown | Estado de bloqueo de 12 minutos tras detectar checking compulsivo (>6 aperturas/hora). |
| Flow protected | Estado en que la app rechaza interacción durante hiperfoco detectado. |
| AgentGuard | Capa de auth + rate-limit aplicada a cada llamada al coach. |
| norteEngine | Hook useNorteDecision() que evalúa contexto y devuelve { widget, payload }. |
| Cohorte fundadora | Primeras 200 plazas a precio lifetime €299. Contador live en KV. |
| Bridge móvil↔web | Mecanismo de intercambio de cookie web por device token Bearer móvil. |
| 2e | Doble excepcionalidad (alta capacidad + neurodivergencia). Audiencia nombrada explícitamente. |
| ERP | Exposure and Response Prevention. Principio terapéutico trasladado a producto sin claims médicos. |
Caso todoennorte.com · Lectura desde dentro del oficio · Versión 1.0 · Enero 2027 Autoría: Joan Arbó · joanarbo.com