Aller au contenu

Migrer une app Lovable vers Next.js : faut-il le faire, et comment sans tout casser

Récupérer le code, sécuriser Supabase, puis migrer vers Next.js seulement si un besoin le justifie : quand le faire, quand rester en Vite, et comment.

Mustapha Hamadi, Développeur Full-Stack12 min de lecture

Sommaire

« Il faut passer sur Next.js. » Le conseil arrive vite dès qu’une application faite avec Lovable commence à avoir des utilisateurs. Il n’est pas faux en soi. Il est simplement prématuré tant qu’on ne sait pas ce que la migration doit résoudre, et dangereux si on la lance avant d’avoir récupéré le code et fermé les failles de la base.

Nous avons repris et mis en production une douzaine d’applications générées par IA, parmi lesquelles une application RH et une messagerie chiffrée interne d’entreprise sur laquelle il a fallu corriger de nombreuses failles de sécurité. Notre position est simple : la migration vers Next.js n’est jamais un réflexe. C’est un chantier qui se justifie par un besoin précis, et qui se mène par étapes, sans arrêter l’application.

D’abord, savoir ce que vous avez entre les mains

La question « faut-il migrer vers Next.js » n’a pas la même réponse selon l’outil et la date de création du projet. Regardez le code plutôt que la réputation de l’outil.

Origine du projetPile techniqueRendu des pages
Lovable, projet créé avant le 13 mai 2026React, Vite, React Routerdans le navigateur
Lovable, projet créé depuis le 13 mai 2026TanStack Startsur le serveur
v0Next.jsselon le code généré
BoltVite ou Next.js selon le projetselon le framework

Lovable a fait de TanStack Start la pile par défaut des nouveaux projets le 13 mai 2026 : les pages sont rendues en HTML sur le serveur avant d’être envoyées. Les projets plus anciens restent des applications React et Vite rendues dans le navigateur, mais Lovable sert aux moteurs de recherche vérifiés des copies pré-rendues de leurs pages publiées. Côté v0, la documentation cite Next.js, React, TypeScript, Tailwind CSS et shadcn/ui : une application v0 n’a rien à migrer, elle est déjà sur Next.js. Pour Bolt, ouvrez le package.json : la présence de vite ou de next vous répond (toutes pages consultées le 12 octobre 2026).

Cet article concerne donc surtout les applications React et Vite : les projets Lovable antérieurs à mai 2026, et une partie des projets Bolt.

Avant toute migration : récupérer, sécuriser, stabiliser

Récupérer le code

Tant que le code ne vit que dans Lovable, on ne peut ni le relire correctement, ni le migrer. La synchronisation GitHub de Lovable fonctionne dans les deux sens : ce que Lovable modifie arrive sur GitHub, et ce que vous poussez sur la branche active revient dans Lovable. Quelques règles à connaître :

  • une seule branche à la fois : par défaut la branche principale du dépôt, mais on peut en choisir une autre ;
  • un dépôt privé par défaut, créé par Lovable sous votre compte ou votre organisation ;
  • pas d’import d’un dépôt existant : l’export va de Lovable vers GitHub, pas l’inverse, et une reconnexion après déconnexion crée un nouveau dépôt.

Sur les plans payants, le bouton Download codebase permet aussi de télécharger le projet en .zip. Attention à ce que la FAQ de Lovable précise : la base de données est à part, et son export n’inclut ni les fichiers stockés, ni le code des Edge Functions, ni les secrets. Si votre projet tourne sur Lovable Cloud plutôt que sur votre propre compte Supabase, la sortie se prépare comme un chantier à part entière : base, stockage, authentification et fonctions ne se déplacent pas en un clic. Bolt synchronise aussi avec GitHub, mais garde ses propres changements en cas de modifications simultanées des deux côtés.

Sécuriser Supabase

Une migration ne corrige aucune faille de la base. Une application Next.js qui interroge Supabase depuis le navigateur avec la clé publique dépend du Row Level Security exactement comme l’application Vite qu’elle remplace. Si les règles d’accès sont absentes ou trop larges, elles le resteront après la migration. Commencez par la check-list de sécurité Lovable et Supabase : RLS, clés exposées, fonctions, stockage, sauvegardes.

Stabiliser

Avant de déplacer le code, il faut pouvoir vérifier qu’on ne l’a pas cassé. Écrivez des tests de bout en bout sur les trois ou quatre parcours qui comptent (inscription, connexion, action principale, paiement s’il existe) et faites-les passer sur l’application actuelle. Ils serviront de filet à chaque étape. Gelez aussi les nouvelles fonctionnalités le temps du chantier. Les autres défauts récurrents du code généré, au-delà du framework, sont détaillés dans ce qu’il faut reprendre sur un MVP codé par IA.

Les bonnes raisons de passer à Next.js

Une migration se justifie quand elle répond à l’un de ces besoins, sans solution plus légère.

Des pages publiques qui doivent être référencées. Une application Vite envoie une page HTML presque vide, que le JavaScript remplit ensuite. Pour un catalogue ou des fiches publiques à faire indexer, le rendu côté serveur est un vrai atout. Nuance importante : le pré-rendu que Lovable sert aux robots vérifiés couvre déjà une partie du besoin tant que l’application est publiée chez Lovable, et la mise à niveau vers TanStack Start apporte le rendu serveur sans quitter la plateforme. Next.js devient pertinent quand vous voulez maîtriser le rendu page par page, en dehors de Lovable.

Du code serveur pour cacher des secrets et des appels tiers. Une clé OpenAI ou Stripe n’a rien à faire dans le navigateur. Les Edge Functions de Supabase règlent déjà ce problème. Next.js apporte une autre option : des Route Handlers et des Server Functions dans le même dépôt que l’interface, avec les variables d’environnement serveur. Utile quand la logique serveur grossit.

Le premier affichage. Le guide officiel de migration de Vite vers Next.js l’explique : dans une application rendue côté client, le navigateur doit télécharger et exécuter tout le code avant de lancer la moindre requête de données, et les composants qui chargent leurs données l’un après l’autre créent des cascades de requêtes. Si vos utilisateurs attendent devant un écran de chargement, c’est une raison valable.

Une équipe qui connaît Next.js. Si ceux qui maintiendront l’application travaillent au quotidien sur Next.js, s’aligner sur leurs outils réduit le coût de chaque évolution.

Quand rester en Vite

Rester sur React et Vite est souvent la bonne décision.

  • L’application est derrière une connexion. Tableau de bord, back-office, outil interne : aucun moteur de recherche n’y entre, et une application monopage hébergée sur un CDN reste simple et peu coûteuse à exploiter.
  • Vous voulez continuer à construire avec Lovable. La FAQ est claire : Lovable ne propose pas de choix de framework, et pour une autre pile il faut poursuivre le travail en dehors de Lovable.
  • Le besoin est le référencement, et l’application reste chez Lovable. La mise à niveau vers TanStack Start se lance depuis le projet. La documentation prévient que certaines bibliothèques qui ne fonctionnent que dans le navigateur peuvent casser le rendu serveur sans que les vérifications de la mise à niveau le détectent. Testez-la sur une branche.
  • Le budget et le calendrier sont serrés. Pendant la migration, vous ne livrez rien de nouveau. Si l’échéance est une levée ou un lancement, la priorité est la sécurité et les briques qui manquent, pas le framework. Nous détaillons ce qui pèse sur la facture dans le prix d’une reprise d’app Lovable, Bolt ou v0.

Migrer sans tout casser : la méthode progressive

Le principe, recommandé par le guide officiel de Next.js lui-même : obtenir le plus vite possible une application Next.js qui fonctionne, en gardant d’abord le routeur existant, puis adopter les fonctionnalités de Next.js une par une.

Étape 1 : faire tourner l’application telle quelle dans Next.js

On installe next, on crée un next.config.mjs avec output: 'export', qui produit une application monopage, puis un layout racine qui reprend le contenu de index.html. Une route attrape-tout app/[[...slug]]/page.tsx renvoie toutes les adresses vers un composant client qui charge votre App existant, avec React Router inchangé, rendu uniquement dans le navigateur grâce à dynamic(() => import('../../App'), { ssr: false }). Rien ne change pour l’utilisateur, et vos tests de bout en bout doivent passer.

Étape 2 : les variables d’environnement

Côté Vite, les variables préfixées par VITE_ sont exposées dans le code envoyé au navigateur, et la documentation de Vite précise qu’elles ne doivent pas contenir d’informations sensibles. Next.js fonctionne sur le même principe avec un autre préfixe : seules les variables NEXT_PUBLIC_ sont inscrites dans le code envoyé au navigateur, au moment du build. Les autres restent sur le serveur. On les lit avec process.env.NEXT_PUBLIC_..., écrit en toutes lettres : une lecture dynamique comme process.env[nom] n’est pas remplacée.

# Avant (Vite, application Lovable)
VITE_SUPABASE_URL=https://votre-projet.supabase.co
VITE_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...

# Après (Next.js)
NEXT_PUBLIC_SUPABASE_URL=https://votre-projet.supabase.co
NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY=sb_publishable_...
OPENAI_API_KEY=...        # sans préfixe : reste sur le serveur
SUPABASE_SECRET_KEY=...   # sans préfixe, et seulement si un traitement serveur l’exige

Le renommage mécanique VITE_ → NEXT_PUBLIC_ est le piège de cette étape. Si une clé secrète traînait déjà dans une variable VITE_, la renommer en NEXT_PUBLIC_ reproduit la fuite. La clé publiable Supabase peut être exposée ; la clé secrète, ou l’ancienne clé service_role, contourne toutes les règles RLS et ne doit jamais se retrouver dans un navigateur, ni avec l’un ni avec l’autre préfixe. Même chose pour les clés OpenAI, Stripe ou d’envoi d’e-mails. Révoquez-les, émettez-en de nouvelles, gardez-les côté serveur. Dernier détail : une variable NEXT_PUBLIC_ est figée au build, donc la modifier impose de reconstruire.

Étape 3 : passer les routes une par une à l’App Router

On remplace React Router progressivement : chaque page devient un dossier de app/ avec son page.tsx. Commencez par les pages publiques, celles qui ont le plus à gagner au rendu serveur, et gardez les écrans connectés pour la fin. Si les adresses changent, prévoyez des redirections permanentes pour ne pas perdre les liens existants ni le référencement acquis.

Dès que vous avez besoin de code serveur (rendu à la requête, Route Handlers, proxy d’authentification), il faut retirer output: 'export' : l’export statique ne prend pas en charge le proxy, et l’application devra tourner sur un serveur.

Étape 4 : Supabase côté serveur et authentification

Supabase recommande le paquet @supabase/ssr : createBrowserClient dans les composants client, createServerClient dans le code serveur, avec une gestion des cookies par getAll et setAll. Le client serveur ressemble à ceci, d’après la documentation de Supabase :

import { createServerClient } from '@supabase/ssr'
import { cookies } from 'next/headers'

export async function createClient() {
  const cookieStore = await cookies()
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
    {
      cookies: {
        getAll: () => cookieStore.getAll(),
        setAll(cookiesToSet) {
          try {
            cookiesToSet.forEach(({ name, value, options }) =>
              cookieStore.set(name, value, options)
            )
          } catch {
            // Appelé depuis un Server Component : le proxy rafraîchit la session.
          }
        },
      },
    }
  )
}

Quatre points à ne pas manquer :

  • le rafraîchissement de session passe par un fichier proxy.ts depuis Next.js 16, middleware.ts en version 15 et avant. La documentation de Supabase prévient qu’un proxy.ts n’est jamais appelé sur une version antérieure, et que les sessions ne sont alors jamais rafraîchies ;
  • côté serveur, on protège avec getClaims(), qui vérifie la signature du jeton, ou getUser(), qui interroge le serveur d’authentification. Jamais avec getSession(), qui lit le cookie sans le revalider ;
  • le proxy ne suffit pas : Next.js recommande de vérifier l’authentification et les droits dans chaque Server Function, car un changement de matcher peut retirer silencieusement la couverture du proxy ;
  • la session change de place : elle passe dans des cookies. Testez ce qui arrive aux utilisateurs déjà connectés au moment de la bascule, et prévoyez qu’ils puissent devoir se reconnecter une fois.

L’ancien paquet @supabase/auth-helpers-nextjs est déprécié : si un tutoriel l’utilise, il est périmé.

Étape 5 : déployer et basculer

Une application Next.js avec du code serveur se déploie sur un serveur Node.js, dans un conteneur Docker ou chez un hébergeur qui prend en charge Next.js. Configurez les variables d’environnement avant le build, ajoutez le nouveau domaine aux adresses de redirection autorisées dans les réglages d’authentification de Supabase, puis faites tourner la nouvelle version en parallèle sur un sous-domaine. Quand les tests passent sur les vraies données, basculez le domaine. Gardez l’ancienne version déployable quelques jours pour pouvoir revenir en arrière.

Ce qu’on garde

La migration touche le framework, pas le reste :

  • Supabase en entier : la base, les règles RLS, l’authentification, le stockage et les Edge Functions restent où ils sont. Seule la façon dont le front s’y connecte change ;
  • les composants shadcn/ui et Tailwind : ce sont des composants React ordinaires. Ceux qui utilisent de l’état, des effets ou des API du navigateur deviennent des Client Components, avec la directive 'use client' en tête de fichier ;
  • la logique métier, à condition qu’elle soit déjà sortie des composants. Si elle y est encore, c’est le moment de la ranger, comme nous l’expliquons dans notre article sur la dette technique d’un MVP.

Les risques à surveiller

  • Les bibliothèques qui supposent un navigateur : tout code qui lit window ou localStorage au chargement casse dès qu’il s’exécute sur le serveur.
  • Les régressions d’authentification : redirections en boucle, sessions perdues, pages protégées visibles un instant avant la redirection. Ce sont les régressions les plus visibles pour vos utilisateurs : chaque étape de l’authentification se teste avec des comptes réels.
  • Le coût d’opportunité : chaque semaine de migration est une semaine sans nouvelle fonctionnalité. Découpez le chantier pour livrer entre deux étapes.

Et Lovable, après la migration ?

Lovable n’est pas conçu pour éditer un projet Next.js. Une fois la branche principale migrée, laisser la synchronisation active sur cette branche, c’est prendre le risque qu’une génération réintroduise du code Vite dans un projet qui n’en a plus. Deux options honnêtes :

  • arrêter Lovable pour ce projet : vous déconnectez la synchronisation, et le dépôt devient la seule source du code. C’est le choix le plus simple ;
  • garder Lovable comme atelier de maquettes : vous prototypez de nouveaux écrans dans un projet Lovable séparé, puis un développeur les porte à la main dans l’application Next.js. Cela marche pour l’interface, beaucoup moins pour la logique.

Si continuer à générer avec Lovable compte plus que le framework, restez en Vite ou passez par la mise à niveau TanStack Start.

Par où commencer

Avant de décider du framework, récupérez le code dans un dépôt à votre nom, vérifiez la sécurité de Supabase et posez des tests sur les parcours critiques. Ensuite seulement, demandez-vous quel problème Next.js résoudrait. S’il n’y en a pas de précis, ne migrez pas.

Si vous hésitez, notre audit de reprise d’app Lovable, Bolt ou v0 tranche cette question avec le reste : sécurité, qualité du code, ce qui manque pour la production, et l’intérêt réel d’une migration, avec un verdict sous 48 h. Si la bonne réponse est de rester sur Vite, l’audit le dit. Pour un projet construit avec un autre outil, la démarche est la même dans notre offre de reprise de projet IA. Envoyez le lien de votre app sur WhatsApp ou décrivez-la via le formulaire, et retrouvez le détail de la démarche sur notre page reprise d’app Lovable.

Sujets

Partager

Vous avez un MVP à sortir ?

Périmètre tranché en une semaine, sprints démontrables, mise en production avec paiement et authentification.