~/progetti/dit/README.md

COOKIES_ADVICE PRIVACY_POLICY.

~/progetti/dit/README.md

Dit

{ date: “2026-05-14”, statut: “live”, modules_stack: 11 }

Signaux de présence minimaux entre personnes — pas de chat, pas de messages, juste la présence

Dit est une application mobile (iOS et Android) qui permet d'échanger des signaux de présence minimaux entre personnes. Pas de texte, pas d'images, pas de messages vocaux — juste deux primitives inspirées du code Morse : un Dit (·) signifie "je suis là", un Dah (—) signifie "reçu". L'application est pour tous ceux qui veulent rester en contact avec des personnes importantes sans la pression d'une conversation.

## Le concept

Dit est basé sur une observation simple : parfois vous voulez montrer à quelqu'un que vous pensez à lui — sans avoir à formuler un message. Inspiré de la vieille habitude d'appeler quelqu'un et de raccrocher avant qu'il ne réponde — un signal gratuit qui signifiait "je pense à toi" ou "rappelle-moi".

·Dit (·) — un signal court à une autre personne, avec une durée de vie configurable de 1 heure, 6 heures ou 24 heures
·Dah (—) — une confirmation en réponse, signifie "reçu" ou "je suis aussi là"
·Pas de Dit simultanément actif par paire d'utilisateurs — un signal à la fois, pas plus
·Tonalités de notification encodées en code Morse : ·· (lettre I = je) pour Dit, ··— (lettre U = tu) pour Dah

## Fonctionnalités principales

L'application comprend les domaines fonctionnels suivants :

·Authentification : Email + Mot de passe, Email OTP (sans mot de passe), Google OAuth, Facebook OAuth
·Système de contacts : Recherche par nom d'utilisateur, sauvegarde unilatérale et silencieuse, surnoms privés, résolution du nom d'affichage (surnom → nom → nom d'utilisateur)
·Livraison en temps réel : Les signaux sont livrés immédiatement via WebSocket lorsque le destinataire est en ligne
·Notifications push : tonalités Morse personnalisées, boutons d'action directement dans la notification (envoyer Dah sans ouvrir l'app), rappels programmés avant expiration
·Multi-appareil : Notifications sur tous les appareils, synchronisation de rejet entre appareils, suppression de jeton à la déconnexion
·Confidentialité : Visibilité du profil (Tous/Contacts/Aucun), blocage d'utilisateur avec suppression de données immédiate et irréversible, réponses 404 génériques sans indication de blocage
·Timeline de ping : Représentation visuelle en diagramme de séquence de tous les signaux entre deux utilisateurs, rendue avec Skia sur GPU

## Architecture

Quatre services indépendants qui communiquent exclusivement via une infrastructure partagée — aucun service n'appelle un autre directement :

·dit-api (NestJS + Fastify) : API REST pour auth, utilisateurs, contacts, création de ping, gestion des jetons push
·dit-ping (Go) : Moteur WebSocket pour livraison en temps réel, traitement Dah/Ignore, surveillance TTL, gestion de présence
·dit-notifications-worker (Node.js + BullMQ) : Livraison de notifications push via FCM, rappels programmés, nettoyage de jetons
·dit-mobile (React Native + Expo) : Client multiplateforme pour iOS et Android

## Stack technologique

Les choix techniques reflètent les exigences du produit :

·Mobile : React Native 0.83+, Expo SDK 55 (Bare Workflow), expo-router, React Native Skia, Reanimated 4, Unistyles v3, Zustand, Notifee
·Backend API : NestJS 11, Fastify, BetterAuth, Prisma, ioredis, BullMQ
·Moteur temps réel : Go 1.23+, Fiber v3, nhooyr.io/websocket, go-redis v9, pgx v5
·Notification worker : Node.js, BullMQ, Firebase Admin SDK, Zod
·Base de données : PostgreSQL 16 + TimescaleDB 2 (Hypertable pour Pings avec partitionnement de séries temporelles)
·Cache et file : Redis 7 (présence, Pub/Sub, file BullMQ, état TTL)
·Auth : BetterAuth (auto-hébergé), Système à deux jetons : Cookie de session (REST) + JWT HS256 de courte durée (WebSocket)
·Email : Brevo SMTP pour emails transactionnels
·Push : Firebase Cloud Messaging pour Android et iOS (proxy FCM-to-APNs)

## Système de design

Un système visuel cohérent traverse toute l'application :

·Couleur primaire : vert toxique (#2EF080 Dark, #00B84E Light)
·Système à deux polices : DM Mono pour les moments d'identité (horodatages, codes, signaux), System UI pour le texte de corps
·Animations : exclusivement Spring-Physics (Reanimated 4), quatre préréglages configurés
·DitPressable : composant interactif unique, combine Gesture Handler + Reanimated + Haptics
·PingTimeline : Canvas Skia avec design Dot-and-Thread, halos pulsants, points cliquables avec tooltips
·DitGlow : Effet de dégradé radial Skia sous la barre d'action avec animation de pulsation
·Floating tab bar : en forme de pilule avec arrière-plan flou et icônes animées avec spring

## Décisions de design importantes

Décisions qui façonnent le produit et l'architecture :

·Deux backends séparés sans contact runtime direct : dit-api crée des pings via REST, dit-ping traite les mises à jour de statut via WebSocket — communication uniquement via Redis Pub/Sub
·JWT validé indépendamment : le service Go valide les jetons avec le même secret, sans appeler l'API NestJS — Zero Runtime Coupling
·ProfileFormatterService comme seul applicateur de visibilité : chaque réponse API avec des données utilisateur passe par ce service
·Le blocage renvoie un 404 générique : l'utilisateur bloqué ne peut pas distinguer entre "bloqué" et "compte supprimé"
·FCM pour les deux plateformes : Firebase Admin SDK route automatiquement — FCM direct pour Android, proxy FCM-to-APNs pour iOS
·TimescaleDB pour Pings : le partitionnement de séries temporelles permet des requêtes efficaces basées sur le temps et un nettoyage automatique des données

## Ce que j'apprends

Perspectives du développement d'un système en temps réel avec quatre services indépendants :

·Définir des limites de propriété claires entre les services dès le premier jour — qui écrit quoi dans quelle table
·Redis Pub/Sub comme bus de communication entre services hétérogènes (TypeScript et Go) sans contact direct
·Confidentialité comme contrainte architecturale : erreurs génériques, visibilité centralisée, blocage destructif
·Préférer les animations Spring à withTiming — la différence de qualité perçue est significative
·Sons de notification comme élément de marque : les tonalités en code Morse rendent l'application instantanément reconnaissable sans marqueurs visuels

Dit est disponible sur Google Play Store. Un produit européen basé en Italie. Say nothing. Mean everything.

// stack
[react-native”, expo”, nestjs”, go”, postgres”, redis”, timescaledb”, websocket”, mobile”, real-time”, presence”, ]