Vibe Coding — ton premier app sans savoir coder — 7. Base de données : tes données partout

19 min read min de lecture
Chapitre 07

Base de données : tes données partout

Chapitre 7 sur 10 · 70%

Objectifs de ce chapitre

  • Comprendre ce qu’est une base de données et comment elle s’organise
  • Migrer ton app du localStorage vers une vraie base en ligne
  • Garantir que chaque utilisateur ne voit que ses propres données

La pièce manquante

Les élèves de Tom se connectent maintenant avec leur e-mail — mais Lina, fidèle au poste, signale que ses habitudes du CDI ne sont toujours pas sur son téléphone. Normal : l'authentification dit qui est là, mais les données, elles, vivent encore dans le localStorage de chaque appareil. Il manque un lieu central où ranger les habitudes de chaque compte : une base de données en ligne. C'est le chantier de ce chapitre, et c'est probablement le plus transformateur du cours — après lui, ton app cesse d'être un gadget de navigateur pour devenir un vrai service.

Le changement de logique tient en une phrase : au lieu que chaque navigateur garde sa propre copie des données, tous les appareils lisent et écrivent au même endroit, un serveur de base de données. Ton app devient un guichet : elle affiche ce que dit la base, et elle y enregistre chaque action. Lina coche « Lecture » sur son téléphone ; la coche part dans la base ; le lendemain au CDI, l'app demande à la base « montre-moi les habitudes de Lina » et tout est là.

Une base de données, concrètement

Si tu as déjà ouvert un tableur, tu connais 80 % du concept. Une base de données est un ensemble de tables ; chaque table ressemble à une feuille de calcul avec des colonnes (les types d'informations) et des lignes (les enregistrements). Chaque ligne possède un identifiant unique (id), et — c'est la partie magique — une ligne peut pointer vers une autre : la colonne user_id d'une habitude dit « cette habitude appartient à cet utilisateur ». C'est ce qu'on appelle une relation, et c'est elle qui relie proprement les données aux comptes du chapitre 6.

Le modèle de Tom est minimaliste : une table habits (une ligne par habitude, avec son nom et le user_id de son propriétaire) et une table checks (une ligne par jour coché, reliée à son habitude). Deux tables, quatre colonnes utiles chacune — résiste à la tentation d'en prévoir dix « pour plus tard ». Tu n'as pas besoin d'écrire ce qui suit toi-même, mais sache le lire : c'est le langage SQL que l'IA générera pour créer les tables.

sql
create table habits (
  id uuid primary key default gen_random_uuid(),
  user_id uuid references auth.users not null,
  name text not null,
  created_at timestamptz default now()
);

create table checks (
  id uuid primary key default gen_random_uuid(),
  habit_id uuid references habits not null,
  day date not null
);

Lis-le comme du presque-français : « crée une table habits ; chaque ligne a un id unique, appartient à un utilisateur, porte un nom, et garde sa date de création ». La ligne references auth.users est la relation : impossible de créer une habitude orpheline, sans propriétaire. Demande toujours à l'IA de t'expliquer le schéma qu'elle propose — c'est dans ces lectures commentées que tu apprends le plus.

flowchart LR
  T["Téléphone de Lina"] -->|"Coche une habitude"| B["Base de données Supabase"]
  O["Ordinateur du CDI"] -->|"Même compte"| B
  B -->|"Renvoie les mêmes données"| T
  B -->|"Renvoie les mêmes données"| O
Un seul lieu de vérité : tous les appareils d'un même compte lisent et écrivent dans la même base.

La sécurité d’abord : chacun voit ses données

Question cruciale avant d'écrire la moindre donnée : qu'est-ce qui empêche l'app de Lina de lire les habitudes de Karim ? Réponse : rien, par défaut. C'est à toi de l'exiger, via ce que Supabase appelle la Row Level Security (RLS) — la « sécurité au niveau des lignes ». Le principe est limpide : chaque table reçoit une règle du type « un utilisateur ne peut lire et modifier que les lignes dont le user_id est le sien ». La base elle-même refuse tout le reste, quoi que fasse le code de l'app.

Sans RLS activée, n'importe quel utilisateur connecté peut techniquement lire les données de tous les autres — il suffit de quelques manipulations dans la console du navigateur. Exige toujours, mot pour mot, dans ton prompt : « active la Row Level Security avec une règle par table : chaque utilisateur n'accède qu'à ses propres lignes ». C'est non négociable.

Migrer sans rien perdre

Tes utilisateurs existants ont des données dans leur localStorage : les jeter serait leur faire payer ta montée en gamme. Le plan de migration est classique et élégant : à la première connexion d'un utilisateur, l'app regarde s'il reste des données locales, et lui propose de les importer dans son compte. Après import réussi, le localStorage est nettoyé, et la base devient l'unique source de vérité. Voici le prompt complet de Tom — remarque qu'il découpe lui-même le chantier en étapes :

PROMPT
Fais évoluer mon app de suivi d'habitudes du localStorage vers Supabase.
Contexte : l'authentification par lien magique fonctionne déjà (chapitre précédent).
Étapes que je veux, dans cet ordre :
1. crée les tables habits et checks, liées à l'utilisateur connecté via user_id
2. active la Row Level Security avec une règle par table : chaque utilisateur ne lit et ne modifie que ses propres lignes
3. fais lire et écrire l'app dans la base au lieu du localStorage : ajout, suppression, cochage, calcul du streak
4. à la première connexion d'un utilisateur qui a encore des données locales, propose-lui de les importer dans son compte, puis nettoie le localStorage
Fais UNE étape à la fois et attends que je confirme mon test avant de passer à la suivante.
À chaque étape, explique-moi en deux phrases ce que tu as fait.

Ce prompt condense tout ce que tu as appris : la vision complète annoncée d'emblée (chapitre 3), le découpage en étapes testables (chapitre 4), la sécurité exigée explicitement, et la demande d'explication qui transforme chaque étape en leçon. Quand l'IA aura fini l'étape 1, va voir tes tables dans le tableau de bord Supabase (onglet « Table Editor ») : voir tes données « en vrai », dans l'interface du service, rend tout le concept concret.

Tester la persistance pour de vrai

La migration touche au cœur de ton app : le test doit être à la hauteur. Ne te contente pas de « ça a l'air de marcher » — déroule un scénario complet, avec plusieurs comptes et plusieurs appareils. Voici la checklist de Tom :

  • Persistance : coche une habitude, recharge la page, ferme le navigateur, reviens — la coche est toujours là.
  • Multi-appareils : coche sur ton téléphone, recharge sur l'ordinateur — la coche apparaît.
  • Isolation : crée deux comptes de test, ajoute des habitudes différentes dans chacun, et vérifie qu'aucun ne voit les données de l'autre.
  • Migration : sur un navigateur qui a d'anciennes données locales, connecte-toi et vérifie que l'import est proposé, puis que tout est arrivé dans le compte.
  • Déconnexion : déconnecté, l'app ne doit afficher aucune donnée.

Pour le test d'isolation — le plus important — fais-toi aider activement. L'IA est excellente pour générer des scénarios de test plus malins que les tiens :

PROMPT
J'ai créé deux comptes de test : eleve1@test.fr et eleve2@test.fr.
Donne-moi un scénario de test pas à pas pour vérifier que :
- chaque compte ne voit que ses propres habitudes et coches
- une coche faite sur un appareil apparaît sur un autre appareil du même compte après rechargement
- un utilisateur déconnecté ne voit aucune donnée
Explique-moi ensuite comment vérifier directement dans le tableau de bord Supabase que chaque ligne de habits porte le bon user_id, et comment tester que la Row Level Security bloque vraiment un accès croisé.
Prends l'habitude d'ouvrir le tableau de bord Supabase en parallèle de tes tests : tu y vois les lignes apparaître en direct quand tu coches dans l'app. C'est le meilleur moyen de comprendre ce qui se passe « derrière » — et de repérer immédiatement une ligne avec un user_id manquant ou faux.

Latence et états de chargement

Un changement subtil accompagne la migration : tes données ne sont plus instantanées. Avec localStorage, tout était sur place ; avec une base en ligne, chaque lecture et chaque écriture fait un aller-retour réseau de quelques dizaines ou centaines de millisecondes. La plupart du temps, c'est imperceptible — mais sur une connexion lente, une liste qui met une seconde à s'afficher sans aucun indicateur donne l'impression d'une app cassée. Demande à l'IA d'ajouter des états de chargement (« un petit indicateur pendant que les habitudes se chargent ») et un message clair si le réseau échoue (« impossible de joindre le serveur, réessaie »).

C'est aussi le moment d'apprendre un réflexe de pro : tester ton app en simulant un mauvais réseau. Dans les outils de développement du navigateur (F12), l'onglet « Network » permet de brider la connexion (« Slow 3G »). Trente secondes de test dans ces conditions te montrent exactement ce que vivront tes utilisateurs les moins bien connectés — et ce qu'il faut améliorer.

Le plan gratuit de Supabase couvre très largement une app comme celle de Tom : 500 Mo de base de données, c'est des années de coches d'habitudes. Ne te préoccupe pas des limites avant d'avoir des centaines d'utilisateurs actifs — et ce jour-là, ce sera un bon problème à avoir.

Ce que Tom vient de gagner

Mesure le chemin : l'app de Tom a maintenant des comptes, des données centralisées, sécurisées ligne par ligne, et synchronisées entre tous les appareils. Lina coche au CDI, vérifie son streak dans le bus, et tout est cohérent. Mais il y a un gain plus discret : Tom dispose désormais d'un vrai backend. Toutes les fonctionnalités « impossibles » d'avant — envoyer des e-mails, accepter un paiement, brancher de l'IA — deviennent accessibles, car elles ont enfin un endroit où s'appuyer. C'est exactement le programme du prochain chapitre.

🛠️ À toi de jouer

Contexte

Tom consacre son week-end à la migration : c'est le chantier le plus structurant depuis le début du projet, et il veut le faire proprement — tables, sécurité, migration des données existantes, tests multi-comptes. Suis le même chemin sur ton app, étape par étape, sans jamais avancer avant d'avoir validé l'étape en cours. À la fin, tes données te suivront partout.

Consignes

  1. Décris à l’IA ton modèle de données en français (« une table pour…, une table pour… ») et demande-lui le schéma SQL commenté.
  2. Envoie le prompt de migration en exigeant explicitement la Row Level Security, une étape à la fois.
  3. Après l’étape des tables, ouvre le tableau de bord Supabase et vérifie leur structure dans le Table Editor.
  4. Déroule la checklist complète : persistance, multi-appareils, isolation entre deux comptes de test, migration des données locales.
  5. Demande l’ajout d’états de chargement et d’un message d’erreur réseau, puis teste en mode « Slow 3G » via F12.
  6. Commit final : « migration base de données complète et testée » — c’est un jalon majeur de ton projet.
Indice — Si l'app affiche une liste vide après la migration alors que la base contient des lignes, c'est presque toujours la RLS qui bloque (règle manquante ou mal écrite). Donne à l'IA le message d'erreur de la console ET ta règle RLS actuelle : le diagnostic est immédiat.

En résumé

  • Une base de données en ligne est le lieu central où tous les appareils lisent et écrivent les mêmes données.
  • Tables, colonnes, lignes : une base ressemble à un tableur, avec des identifiants uniques et des relations.
  • La colonne user_id relie chaque donnée à son propriétaire — c’est le pont avec l’authentification du chapitre 6.
  • La Row Level Security est non négociable : sans elle, chaque utilisateur peut techniquement lire les données des autres.
  • Migre sans perte : propose l’import des données locales à la première connexion, puis nettoie le localStorage.
  • Teste sérieusement : persistance, multi-appareils, isolation entre comptes, et comportement en réseau lent.
  • Avec un vrai backend, les fonctionnalités avancées (e-mails, paiement, IA) deviennent enfin accessibles.

Quiz — vérifie ta compréhension

1. Quel problème la base de données résout-elle, que l’authentification seule ne résolvait pas ?

L'authentification dit QUI est là ; la base de données stocke QUOI au même endroit pour tous les appareils. Les deux ensemble donnent la synchronisation que Lina attendait.

2. À quoi sert la colonne user_id dans la table habits ?

user_id pointe vers l'utilisateur propriétaire : c'est la relation qui permet d'afficher à chacun ses habitudes, et à la RLS de bloquer les autres.

3. Que se passe-t-il si tu oublies d’activer la Row Level Security ?

Par défaut, rien n'isole les lignes entre utilisateurs. La RLS fait appliquer la règle « chacun ses lignes » par la base elle-même — exige-la mot pour mot dans ton prompt.

4. Comment migrer les données localStorage des utilisateurs existants sans les perdre ?

L'import à la première connexion préserve l'historique de chacun : la base devient ensuite l'unique source de vérité. Tes utilisateurs ne paient pas ta montée en gamme.

5. Après migration, la liste s’affiche vide alors que la base contient bien des lignes. Quelle est la cause la plus probable ?

C'est le symptôme classique : la base refuse la lecture car la règle RLS ne reconnaît pas l'utilisateur. Console + règle RLS envoyées à l'IA = diagnostic immédiat.

Auteur(s)

R

REHOUMA Haythem

Haythem Rehouma est un ingénieur et architecte IA et cloud, formateur et enseignant technique, avec un profil orienté IA médicale, AWS, MLOps, LLM/RAG et vision par ordinateur.