Skip to content
Learni
Voir tous les tutoriels
Base de données

Comment démarrer avec Supabase en 2026

Read in English

Introduction

Supabase est une plateforme open-source qui combine une base de données PostgreSQL, l'authentification, le stockage et les abonnements en temps réel, le tout avec une API REST et GraphQL prêtes à l'emploi. Contrairement à Firebase, Supabase repose sur SQL standard, ce qui le rend plus puissant pour les relations complexes et les migrations.

Pourquoi l'utiliser en 2026 ? Les apps web modernes exigent scalabilité, sécurité Row Level Security (RLS) et intégration facile avec Next.js ou React. Ce tutoriel beginner vous guide de zéro : création de projet, auth, CRUD sur tables et realtime. À la fin, vous aurez une app todo list fonctionnelle connectée à Supabase.

Avantage clé : dashboard intuitif pour configurer sans code, puis client JS pour l'intégration. Économisez des semaines de dev backend. (128 mots)

Prérequis

  • Un compte gratuit sur supabase.com
  • Node.js 18+ installé
  • Connaissances basiques en HTML/JS (pas de framework requis)
  • Un éditeur de code comme VS Code
  • Navigateur moderne pour tester

Étape 1 : Créer votre projet Supabase

Connectez-vous sur app.supabase.com et créez un nouveau projet. Choisissez un nom, une région proche (ex: Europe West) et un mot de passe DB fort. Attendez 2 minutes pour l'initialisation.

Notez l'URL du projet et la clé anon (public) dans Settings > API. Ces valeurs sont essentielles pour le client JS. Activez l'authentification par email dans Authentication > Settings > Enable Email.

Installer le client Supabase JS

terminal
mkdir supabase-todo-app
cd supabase-todo-app
npm init -y
npm install @supabase/supabase-js

Cette commande initialise un projet Node et installe le client officiel Supabase JS, compatible browsers et server. Utilisez npm run dev plus tard pour un serveur local si besoin. Évitez les versions outdated : toujours la latest (^2.x en 2026).

Configurer le client Supabase

supabase.js
import { createClient } from '@supabase/supabase-js'

const supabaseUrl = 'https://your-project.supabase.co'
const supabaseAnonKey = 'your-anon-key-here'

export const supabase = createClient(supabaseUrl, supabaseAnonKey)

Remplacez your-project et your-anon-key par vos valeurs du dashboard. Ce client singleton gère toutes les connexions. Utilisez la clé anon pour le frontend (sûre publiquement) ; service_role pour admin server-side. Piège : ne committez jamais les clés dans Git.

Étape 2 : Créer une table Todos

Dans le dashboard Supabase > Table Editor, créez une table todos avec ces colonnes :

  • id (uuid, primary key, default gen_random_uuid())
  • task (text, not null)
  • is_complete (boolean, default false)
  • user_id (uuid, references auth.users(id))

Activez RLS : ALTER TABLE todos ENABLE ROW LEVEL SECURITY;. Ajoutez une policy : CREATE POLICY user_todos ON todos FOR ALL USING (auth.uid() = user_id); via SQL Editor pour sécurité par utilisateur.

Créer la table via SQL

create-table.sql
CREATE TABLE todos (
  id UUID DEFAULT gen_random_uuid() PRIMARY KEY,
  task TEXT NOT NULL,
  is_complete BOOLEAN DEFAULT false,
  user_id UUID REFERENCES auth.users(id) ON DELETE CASCADE
);

ALTER TABLE todos ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users can manage own todos" ON todos
  FOR ALL
  USING (auth.uid() = user_id)
  WITH CHECK (auth.uid() = user_id);

Exécutez ce SQL complet dans le SQL Editor du dashboard. RLS protège les données : seul le proprio accède à ses todos. Analogie : comme un coffre-fort par utilisateur. Piège : oubliez ON DELETE CASCADE et les orphelins polluent la DB.

S'inscrire et se connecter

auth.js
import { supabase } from './supabase.js'

export async function signUp(email, password) {
  const { data, error } = await supabase.auth.signUp({
    email,
    password,
  })
  if (error) throw error
  return data
}

export async function signIn(email, password) {
  const { data, error } = await supabase.auth.signInWithPassword({
    email,
    password,
  })
  if (error) throw error
  return data
}

export async function signOut() {
  const { error } = await supabase.auth.signOut()
  if (error) throw error
}

Ces fonctions gèrent auth email/password. signUp envoie un email de confirmation (activez dans dashboard). Toujours checker error. En prod, ajoutez CAPTCHA via settings. Piège : passwords <6 chars échouent silencieusement.

Étape 3 : Gérer les Todos (CRUD)

Créer : Ajoutez un todo lié à l'utilisateur connecté.
Lire : Fetch todos de l'utilisateur.
Update/Delete : Modifiez/supprimez par ID.
Utilisez supabase.from('todos').select('*') pour queries simples.

Fonctions CRUD pour Todos

todos.js
import { supabase } from './supabase.js'

const userId = supabase.auth.getUser().data.user.id // À appeler après login

export async function addTodo(task) {
  const { data, error } = await supabase
    .from('todos')
    .insert([{ task, user_id: userId }])
  if (error) throw error
  return data
}

export async function getTodos() {
  const { data, error } = await supabase
    .from('todos')
    .select('*')
    .eq('user_id', userId)
  if (error) throw error
  return data
}

export async function toggleTodo(id, isComplete) {
  const { error } = await supabase
    .from('todos')
    .update({ is_complete: isComplete })
    .eq('id', id)
  if (error) throw error
}

export async function deleteTodo(id) {
  const { error } = await supabase
    .from('todos')
    .delete()
    .eq('id', id)
  if (error) throw error
}

Code CRUD complet avec RLS intégré. .eq('user_id', userId) filtre auto via policy. userId vient de session auth. Testez avec console.log. Piège : fetch userId avant login = null, crash.

Subscription Realtime

realtime.js
import { supabase } from './supabase.js'

function subscribeToTodos(callback) {
  return supabase
    .channel('todos')
    .on(
      'postgres_changes',
      {
        event: '*',
        schema: 'public',
        table: 'todos',
        filter: `user_id=eq.${supabase.auth.getUser().data.user.id}`,
      },
      callback
    )
    .subscribe()
}

export { subscribeToTodos }

Abonnez-vous aux changements DB en temps réel. '*' écoute insert/update/delete. Filtre par user_id pour perf. Appelback reçoit payload. Déconnectez avec .unsubscribe(). Piège : sans filter, overload sur gros traffic.

Exemple HTML/JS complet

index.html
<!DOCTYPE html>
<html>
<head><title>Supabase Todos</title></head>
<body>
  <input id="task" placeholder="Nouvelle tâche">
  <button onclick="addTodo()">Ajouter</button>
  <button onclick="signIn()">Login</button>
  <ul id="todos"></ul>
  <script type="module">
    import { supabase } from './supabase.js'
    import { addTodo, getTodos, toggleTodo, deleteTodo, signIn, signUp } from './todos.js'
    import { subscribeToTodos } from './realtime.js'

    let todos = []

    async function loadTodos() {
      todos = await getTodos()
      render()
    }

    function render() {
      const ul = document.getElementById('todos')
      ul.innerHTML = todos.map(t => `
        <li>
          <span style="text-decoration: ${t.is_complete ? 'line-through' : 'none'}">${t.task}</span>
          <button onclick="toggleTodo('${t.id}')">Toggle</button>
          <button onclick="deleteTodo('${t.id}')">Suppr</button>
        </li>
      `).join('')
    }

    window.addTodo = addTodo
    window.getTodos = loadTodos
    window.toggleTodo = async(id) => {
      const todo = todos.find(t => t.id === id)
      await toggleTodo(id, !todo.is_complete)
      loadTodos()
    }
    window.deleteTodo = async(id) => {
      await deleteTodo(id)
      loadTodos()
    }
    window.signIn = () => { /* Implémentez UI login */ alert('Login simulé') }

    subscribeToTodos(() => loadTodos())
    loadTodos()
  </script>
</body>
</html>

Page HTML autonome : tapez une tâche, ajoutez, tooglez en realtime. Import modules ES. Remplacez signIn par form réel. Servez via npx serve .. Piège : CORS – activez dans Supabase dashboard > Auth > URL config.

Bonnes pratiques

  • Toujours utiliser RLS : Bloque accès non auth même si query mal filtrée.
  • Clés séparées : anon frontend, service_role server-only via env vars.
  • Queries optimisées : Indexez colonnes filtrées (ex: CREATE INDEX ON todos(user_id);).
  • Gestion erreurs : Wrappez tout en try/catch, toastez user-friendly.
  • Migrations SQL : Versionnez schémas via GitHub repo Supabase.

Erreurs courantes à éviter

  • Oublier email confirmation : Users bloqués en 'confirmed=false'.
  • Pas de filter user_id : RLS bypass si policy mal écrite, data leak.
  • Client sans await : Promesses rejetées silencieusement, UI cassée.
  • Ignorer realtime cleanup : Subscriptions fuient mémoire sur multi-tabs.

Pour aller plus loin