Ce que fait chaque fichier, et par où passe chaque geste — depuis le doigt sur l'écran jusqu'à la ligne écrite dans Postgres.
C'est le point de départ de toute lecture du code : les 213 fonctions de db.js suivent la même règle, sans exception volontaire sauf une.
Aucune fonction ne modifie l'état en mémoire à la main après une écriture. On écrit, on relit, on redessine. Le temps réel emprunte exactement le même chemin : un changement venu d'un autre appareil déclenche le même loadX() et le même rendu. C'est ce qui rend le code mécanique — au prix d'un peu de réseau, négligeable à l'échelle d'un foyer.
Les onglets vivent dans .phone et se croisent par goTo(). Les pages sont des .notif-page qui se posent par-dessus — c'est le langage de toute décision dans l'app.
La grille du mois et l'agenda d'un jour.
Urgent, l'agenda du jour, En retard, À garder en tête — quatre blocs qui se partagent la hauteur restante.
Une seule liste, triée par ce qui presse. Le genre est écrit sur la carte, le filtre démarre éteint.
Des notes qui tiennent toutes seules : titre, et une suite de blocs texte, image, lien.
Chaque flux nomme les fonctions réellement appelées, dans l'ordre. Le départ est le geste ; les cadres pointillés sont des tables.
Puis trois moteurs se déclenchent seuls, sans qu'on les demande : genererOccurrencesAgenda pose les dates à venir, relancerProjetsRecurrents fait revenir les projets, avancerProjetsProgressifs fait passer les étapes échues.
Sans date, la tâche tombe dans le backlog (backlog_items). Au bout de deux jours sans être faite, renderOverdue la remonte dans « En retard ».
Un modèle qui porte des étapes ne passe pas par la feuille : il ouvre l'atelier déjà rempli, parce que la feuille ne sait poser des dates que sur une liste plate.
Rien n'est écrit avant « Terminer ». Entre-temps tout vit dans l'objet creation ; un brouillon peut être posé dans project_drafts pour reprendre plus tard.
Toute l'arithmétique est en UTC : une date d'agenda est un jour du calendrier, pas un instant — en heure locale, un changement d'heure fait dériver « une semaine sur deux ». Un filigrane par tâche (recur_generated_until) ne recule jamais, pour qu'une date effacée à la main ne revienne pas.
Le modèle est écrit à chaque touche mais l'écran n'est pas redessiné : un rendu par frappe reprendrait le curseur. Une empreinte de l'état enregistré dit s'il y a lieu de demander quoi que ce soit en sortant.
Le seul flux qui court-circuite la règle de circulation, volontairement. Une liste se coche par rafales ; un aller-retour réseau et deux rendus complets par case rendaient le geste pénible.
Un canal à part, filtré sur la personne et non sur l'espace actif : une invitation est par définition une ligne créée dans un foyer dont on n'est pas encore membre, qu'aucun filtre par espace ne peut voir.
Le fil porte un lien vers le carnet, jamais une copie de son contenu : trois tâches peuvent renvoyer à la même note de rendez-vous sans qu'elle se dédouble. Depuis la même page, creerNoteEtLier fabrique la note et pose le lien d'un seul geste — sauverCarnet rend l'identifiant, faute de quoi l'enregistrement suivant créait un doublon.
Quatre décisions dans l'ordre : quel produit l'article désigne — le genre et ses appellations —, dans quelle zone habite l'acheteur, quel contrat gagne — le local bat le national, puis un tirage pondéré par le prix, retenu pour la session —, et enfin le décompte, qui ne facture qu'un clic par personne, par contrat, par jour. Le navigateur ne touche pas au compteur : revoke update lui retire les colonnes, et consommer_clic est le seul chemin.
Dans l'ordre où index.html les charge — l'ordre compte : chacun peut appeler ceux d'avant.
| Fichier | Rôle | Lignes |
|---|---|---|
| supabase-client.js | L'URL, la clé, et le client sb. Tout passe par lui. | 14 |
| emailjs-client.js | L'envoi des invitations par courriel. | 30 |
| data.js | L'état en mémoire et les constantes : catégories, couleurs, catalogue codé en dur. | 147 |
| db.js | Le cœur. Toutes les lectures, toutes les écritures, le bootstrap, le temps réel, les moteurs. | 3 460 |
| utils.js | Dates, échappement, format — ce dont tout le monde a besoin. | 118 |
| who.js | Choisir qui fait quoi : les pastilles de personne. | 161 |
| notes.js | Les commentaires posés sur une tâche, une liste, un projet — et le lien vers un carnet. | 354 |
| carnets.js | Les notes qui tiennent toutes seules — l'onglet Notes. | 588 |
| hints.js | Les indications d'un projet, et la suite mêlée tâches + indications. | 522 |
| rythme.js | Le moteur de récurrence : cinq genres, l'arithmétique UTC, la page de réglage. | 431 |
| agenda-google.js | L'intégration Google, dormante derrière un drapeau. | 207 |
| agenda-ics.js | L'abonnement calendrier, en lecture seule. | 107 |
| today.js | L'écran du jour : les quatre blocs et le partage de leur hauteur. | 372 |
| lists.js | Les listes et leurs articles, où qu'ils s'affichent. | 444 |
| produit.js | La fiche d'un produit, ses comparables, et l'ordre — épinglé, payé, recommandé. | 183 |
| catalogue.js | Le catalogue ouvert pour de bon : produits, services, et d'où vient chaque fiche. | 246 |
| composer.js | La barre d'écriture du bas et ses options. | 345 |
| calendar.js | La grille du mois. | 101 |
| projects.js | Les cartes de projet, le filtre par genre, le tri par urgence, le menu. | 1 165 |
| creation.js | L'atelier : composer un projet, ses étapes, ce qui les termine. | 830 |
| dialogs.js | La confirmation partagée et la feuille d'ajout depuis un modèle. | 220 |
| admin.js | Le back office : catalogue, soumissions, produits et services, comptes, entreprises. | 1 667 |
| dashboard.js | Les chiffres de la plateforme. | 208 |
| archive.js | L'historique, et le miroir de la charge. | 360 |
| company.js | Le bureau d'entreprise : équipe, produits et services, statistiques. | 861 |
| messages.js | Les discussions d'espace et le soutien. | 288 |
| app.js | La navigation, l'en-tête, les espaces, le clavier, la mise en page. | 1 291 |
| auth.js | La connexion Google, et le démarrage. C'est la seule porte d'entrée. | 135 |
Toutes sous RLS — aucune ne rend une seule ligne à un appelant non connecté, vérifié table par table. Vingt-cinq sont publiées en temps réel. La sécurité passe par des fonctions security definer — my_household_ids(), peut_gerer(), est_fondateur() — pour éviter qu'une règle qui lit members ne se referme sur elle-même.
| Domaine | Tables |
|---|---|
| Foyer | households · members · contacts · user_prefs |
| Le quotidien | categories · tasks · backlog_items · task_history · notifications |
| Listes | lists · list_items |
| Projets | projects · project_waves · project_tasks · project_hints · project_drafts |
| Notes | notes (commentaires) · note_cards + note_blocks (carnets) |
| Modèles | templates · template_tasks · template_hints · template_feedback |
| Catalogue | catalog_templates · catalog_template_tasks · catalog_template_hints |
| Discussions | messages · support_messages |
| Entreprises | companies · company_members · products · product_events |
| Vitrine | commerces_publics — une VUE, pas une table : elle choisit les colonnes publiques d une entreprise, ce que la RLS ne sait pas faire (elle travaille par ligne). |
| Commandite | zones (les 17 régions, chacune avec les villes qui y mènent) · placements (le contrat : un produit, une zone, un prix au clic, un solde) |
| Plateforme | platform_admins · platform_settings |
| Agenda externe | google_links · google_events · agenda_ics |
Deux fonctions Edge en Deno servent ce que le navigateur ne doit pas toucher : agenda-google (les jetons OAuth ne sont jamais lisibles côté client) et agenda-ics (le flux d'abonnement).
Des règles arrivées par correction, pas par principe. Chacune répare une chose qui s'est mal passée.
Tout ce qui demande de choisir s'ouvre en pleine page, sur le patron .notif-page : flèche de retour, titre, corps. Une fenêtre laisse le travail visible derrière et invite à hésiter — et sur un téléphone, elle passait sous les autres couches.
Toute barre qui sert à choisir ce qu'on regarde prend la même forme : pleine largeur sur fond sombre, l'onglet choisi éclairci. Définie une seule fois dans base.css. Un contrôle posé dans une rangée à côté d'un menu déroulant, lui, reste une pastille.
Ce qui distingue un filtre d'un onglet tient à ça : un onglet, on est toujours dedans, et l'état de repos cache les deux tiers. Éteint, l'état de repos est complet.
Réservé aux gestes qui viennent par rafales. Ailleurs, on attend l'écriture — c'est ce qui garde le code mécanique.
schema.sqlCinquante et une sections numérotées, toutes en if not exists. schema.sql décrit une installation neuve et ne se roule jamais sur la base en service — ça s'est produit une fois, et l'utilisateur s'est retrouvé sans droits d'admin.
Toute écriture qui touche une colonne récente se replie sur une version sans elle quand PostgREST répond 42703 ou PGRST204. Un diagnostic au démarrage nomme les sections manquantes dans la console.
Pas ce que fait la ligne — ce qu'on a essayé avant, et pourquoi ça n'allait pas. C'est la mémoire du projet.