Mémo · carte du code · 8 septembre 2026

La carte de Mémo

Ce que fait chaque fichier, et par où passe chaque geste — depuis le doigt sur l'écran jusqu'à la ligne écrite dans Postgres.

28fichiers JS
14 855lignes
4onglets
15pages pleines
39tables
43fonctions SQL
60migrations
La règle de circulation

Un seul chemin, partout

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.

La base est la source de vérité
un geste → await l'écriture → recharger ce domaine → redessiner

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.

La seule exception assumée : cocher un article de liste. Le doigt a raison avant le réseau — la case se coche sur place, l'écriture part ensuite, et si la base refuse, la case revient. Les échos du temps réel y sont rassemblés une demi-seconde après le dernier, au lieu d'un rendu complet par case.
Les surfaces

Quatre onglets, quinze pages

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.

Onglet 1

Calendrier

La grille du mois et l'agenda d'un jour.

  • calendar.js
Onglet 2 · défaut

Tâches

Urgent, l'agenda du jour, En retard, À garder en tête — quatre blocs qui se partagent la hauteur restante.

  • today.js · composer.js
  • lists.js · notes.js
Onglet 3

Projets

Une seule liste, triée par ce qui presse. Le genre est écrit sur la carte, le filtre démarre éteint.

  • projects.js · creation.js
  • dialogs.js · hints.js
Onglet 4

Notes

Des notes qui tiennent toutes seules : titre, et une suite de blocs texte, image, lien.

  • carnets.js
notifPage notifications messagesPage discussions archivePage archive + miroir profilePage compte spacesPage espaces + membres modelesPage mes listes projMenuPage options d'un projet rythmePage quand ça revient productSheetPage fiche produit adminPage back office companyPage bureau d'entreprise
Les liens

Dix flux, du geste à la ligne

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.

Démarrage

auth.js → db.js
session Google→ bootstrapHousehold→ loadMySpaces→ Promise.all — 18 loadX()→ renderAll · renderProjects · renderCarnets→ subscribeRealtime

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.

Écrire une tâche

composer.js → db.js → today.js
barre d'écriture→ addTask→ createTask→ tasks→ loadTasks→ renderAll

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 projet depuis un modèle

projects.js → dialogs.js → db.js
recherche du catalogue→ selectCatalogItem→ openAddSheet→ createSimpleProject→ updateProjetRythme→ projects · project_tasks · project_hints→ loadProjects

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.

Un projet composé à la main

creation.js → db.js
l'atelier→ ouvrirCreationProjet→ choisirGenreProjet→ enregistrerCreation→ creerProjetEnEtapes→ project_waves + project_tasks

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.

Le rythme, et les dates qui se posent seules

rythme.js → db.js
page « quand ça revient »→ ouvrirRythme→ rythmeVersLigne→ recur_kind · recur_weekdays · recur_monthdays…→ occurrencesRythme→ genererOccurrencesAgenda→ tasks (source_task_id)

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.

Une note

carnets.js → db.js
l'atelier de note→ majBlocCarnet — à chaque frappe→ enregistrerCarnet→ sauverCarnet→ note_cards + note_blocks→ loadCarnets

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.

Cocher un article de liste

lists.js → db.js
la case→ onToggleListItem→ majAffichageArticle — sur place→ ecrireArticleCoche→ list_items→ rechargerArticlesBientot — 500 ms

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.

Être invité dans un espace

db.js → app.js
quelqu'un t'invite→ canal « moi- » (temps réel)→ rattraperCeQuiMeConcerne→ loadMySpaces + loadPendingInvitations→ renderSpaceSwitcher

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.

Lier une note à une tâche

notes.js → carnets.js → db.js
icône de lien dans le fil→ ouvrirChoixCarnet→ lierNotePage — recherche · tri · alphabet→ choisirCarnetALier→ notes.carnet_id→ loadNotes

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.

Un produit commandité qu'on ouvre

lists.js → db.js → produit.js
article écrit à la main→ findProductForTitle — nomsDuGenre→ zonePourVille (adresse du profil)→ placementPourProduit→ consommerClic→ placements.clics_utilises

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.

Les fichiers

Qui fait quoi

Dans l'ordre où index.html les charge — l'ordre compte : chacun peut appeler ceux d'avant.

FichierRôleLignes
supabase-client.jsL'URL, la clé, et le client sb. Tout passe par lui.14
emailjs-client.jsL'envoi des invitations par courriel.30
data.jsL'état en mémoire et les constantes : catégories, couleurs, catalogue codé en dur.147
db.jsLe cœur. Toutes les lectures, toutes les écritures, le bootstrap, le temps réel, les moteurs.3 460
utils.jsDates, échappement, format — ce dont tout le monde a besoin.118
who.jsChoisir qui fait quoi : les pastilles de personne.161
notes.jsLes commentaires posés sur une tâche, une liste, un projet — et le lien vers un carnet.354
carnets.jsLes notes qui tiennent toutes seules — l'onglet Notes.588
hints.jsLes indications d'un projet, et la suite mêlée tâches + indications.522
rythme.jsLe moteur de récurrence : cinq genres, l'arithmétique UTC, la page de réglage.431
agenda-google.jsL'intégration Google, dormante derrière un drapeau.207
agenda-ics.jsL'abonnement calendrier, en lecture seule.107
today.jsL'écran du jour : les quatre blocs et le partage de leur hauteur.372
lists.jsLes listes et leurs articles, où qu'ils s'affichent.444
produit.jsLa fiche d'un produit, ses comparables, et l'ordre — épinglé, payé, recommandé.183
catalogue.jsLe catalogue ouvert pour de bon : produits, services, et d'où vient chaque fiche.246
composer.jsLa barre d'écriture du bas et ses options.345
calendar.jsLa grille du mois.101
projects.jsLes cartes de projet, le filtre par genre, le tri par urgence, le menu.1 165
creation.jsL'atelier : composer un projet, ses étapes, ce qui les termine.830
dialogs.jsLa confirmation partagée et la feuille d'ajout depuis un modèle.220
admin.jsLe back office : catalogue, soumissions, produits et services, comptes, entreprises.1 667
dashboard.jsLes chiffres de la plateforme.208
archive.jsL'historique, et le miroir de la charge.360
company.jsLe bureau d'entreprise : équipe, produits et services, statistiques.861
messages.jsLes discussions d'espace et le soutien.288
app.jsLa navigation, l'en-tête, les espaces, le clavier, la mise en page.1 291
auth.jsLa connexion Google, et le démarrage. C'est la seule porte d'entrée.135
La base

Trente-neuf tables, par domaine

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.

DomaineTables
Foyerhouseholds · members · contacts · user_prefs
Le quotidiencategories · tasks · backlog_items · task_history · notifications
Listeslists · list_items
Projetsprojects · project_waves · project_tasks · project_hints · project_drafts
Notesnotes (commentaires) · note_cards + note_blocks (carnets)
Modèlestemplates · template_tasks · template_hints · template_feedback
Cataloguecatalog_templates · catalog_template_tasks · catalog_template_hints
Discussionsmessages · support_messages
Entreprisescompanies · company_members · products · product_events
Vitrinecommerces_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).
Commanditezones (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)
Plateformeplatform_admins · platform_settings
Agenda externegoogle_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).

Les conventions

Ce qui a été décidé, et qui tient

Des règles arrivées par correction, pas par principe. Chacune répare une chose qui s'est mal passée.

01

Des pages, jamais de fenêtre flottante

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.

02

La bande noire choisit une vue

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.

03

Le filtre démarre éteint

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.

04

Le geste avant le réseau, quand ça se répète

Réservé aux gestes qui viennent par rafales. Ailleurs, on attend l'écriture — c'est ce qui garde le code mécanique.

05

Le SQL est idempotent, et jamais schema.sql

Cinquante 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.

06

Le code dégrade au lieu d'échouer

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.

07

Les commentaires disent pourquoi, en français

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.

mémo avec brio · v271 unload-app-five.vercel.app Relevé sur le code au 8 septembre 2026. Le détail technique La présentation Pour les commerces Ouvrir l'application