Allez directement au contenu principal
Guide de tutorat

Créez une application mobile Next.js à partir de zéro avec Capacitor 8

Guide étape par étape pour créer un nouveau projet Next.js 15 et le transformer en applications mobiles natives iOS et Android à l'aide de Capacitor 8. Parfait pour commencer avec un développement mobile centré sur l'utilisateur.

Crédits de l'article

Martin Donadieu

Auteur

Valeria

Relecteur

Jordan

Éditeur

Créez une application mobile Next.js à partir de zéro avec Capacitor 8

Introduction

Vous souhaitez créer une application mobile avec Next.js à partir de zéro ? Ce guide vous accompagne dans la création d'un projet Next.js 15 entièrement configuré pour la mobilité dès le départ, puis dans la création d'applications natives iOS et Android à partir de Capacitor 8.

À la fin de ce tutoriel, vous disposerez d'une application mobile fonctionnelle exécutée sur des simulateurs que vous pourrez continuer à développer et publier ultérieurement sur l'App Store et Google Play.

Temps requis : ~30 minutes

Ce que vous construisez :

  • Un nouveau projet Next.js 15 avec App Router
  • Configuration d'exportation statique pour la mobilité
  • Capacitor 8 with essential plugins
  • Applications natives iOS et Android
  • Configuration de développement avec rechargement en direct

Vous avez déjà une application Next.js ? Consultez Convertissez votre application Next.js en application mobile au lieu de cela.

Prérequis

Assurez-vous d'avoir ces éléments installés :

  • Node.js 18+ (vérifiez avec node --version)
  • Bun gestionnaire de packages (curl -fsSL https://bun.sh/install | bash)
  • Xcode (seulement pour macOS, pour le développement iOS)
  • Android Studio pour le développement Android

Étape 1 : Créez un nouveau projet Next.js

Commencez par créer un projet Next.js 15 vierge :

bunx create-next-app@latest my-mobile-app

Lorsque vous êtes invité à choisir, sélectionnez ces options :

  • TypeScript : Oui (recommandé)
  • ESLint : Oui
  • Tailwind CSS : Oui (recommandé pour la mise en forme mobile)
  • src/ répertoire : Oui
  • Routeur d'application : Oui (recommandé)
  • Alias d'importation : Par défaut (@/*)

Accédez à votre projet :

cd my-mobile-app

Étape 2 : Configurez Next.js pour l'exportation statique

Capacitor nécessite des fichiers HTML/JS/CSS statiques. Configurez Next.js pour l'exportation statique en mettant à jour next.config.ts:

import type { NextConfig } from 'next';

const nextConfig: NextConfig = {
  output: 'export',
  images: {
    unoptimized: true,
  },
  // Ensure trailing slashes for proper routing in Capacitor
  trailingSlash: true,
};

export default nextConfig;

Pourquoi ces paramètres ?

  • output: 'export' — Génère du HTML statique au lieu de nécessiter un serveur Node.js
  • images: { unoptimized: true } — Désactive l'optimisation d'image Next.js (nécessite un serveur)
  • trailingSlash: true — Assure un routage correct dans la vue WebView native

Étape 3 : Ajoutez les scripts mobiles

Mettez à jour votre package.json avec des scripts de développement mobile :

{
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint",
    "mobile": "bun run build && bunx cap sync",
    "mobile:ios": "bun run mobile && bunx cap open ios",
    "mobile:android": "bun run mobile && bunx cap open android"
  }
}

Testez la construction :

bun run build

Vous devriez voir un out répertoire avec vos fichiers statiques.

Étape 4 : Installez Capacitor 8

Installez les packages de base de Capacitor :

bun add @capacitor/core
bun add -D @capacitor/cli

Installez les plugins essentiels dont la plupart des applications mobiles ont besoin :

bun add @capacitor/app @capacitor/keyboard @capacitor/splash-screen @capacitor/status-bar @capacitor/preferences

Ce que font ces plugins :

  • @capacitor/app — Événements de cycle de vie de l'application (avant-plan/arrière-plan, liens profonds)
  • @capacitor/keyboard — Contrôler le comportement du clavier
  • @capacitor/écran d'accueil — Contrôle de l'écran d'accueil natif
  • @capacitor/barre de statut — Personnaliser la barre de statut du dispositif
  • @capacitor/préférences — Stockage de valeurs clés (comme localStorage mais natif)

Étape 5 : Initialiser Capacitor

Initialisez Capacitor avec les détails de votre projet :

bunx cap init "My Mobile App" com.example.mymobileapp --web-dir out

Remplacez :

  • "My Mobile App" par le nom d'affichage de votre application
  • com.example.mymobileapp par l'ID de votre application (notation de domaine inversé)

Cela crée capacitor.config.tsMettez à jour avec la configuration du plugin :

import type { CapacitorConfig } from '@capacitor/cli';

const config: CapacitorConfig = {
  appId: 'com.example.mymobileapp',
  appName: 'My Mobile App',
  webDir: 'out',
  plugins: {
    SplashScreen: {
      launchShowDuration: 2000,
      launchAutoHide: true,
      androidScaleType: 'CENTER_CROP',
      splashFullScreen: true,
      splashImmersive: true,
    },
    Keyboard: {
      resize: 'body',
      resizeOnFullScreen: true,
    },
    StatusBar: {
      style: 'light',
    },
  },
};

export default config;

Étape 6 : Ajoutez les plateformes natives

Installez les packages de plateforme :

bun add @capacitor/ios @capacitor/android

Générez les projets natifs :

bunx cap add ios
bunx cap add android

Cela crée ios et android des

répertoires contenant les projets natifs.

Étape 7 : Construire et Exécuter

bun run mobile

Construire votre projet et synchronisez-l’avec les plateformes natives :

bun run mobile:ios

Ouvrez dans l'émulateur iOS :

bun run mobile:android

In Xcode (iOS):

  1. Sélectionnez un simulateur dans le menu déroulant des appareils
  2. Cliquez sur le bouton Démarrer ou appuyez sur Cmd + R

In Android Studio:

  1. Attendez que Gradle termine de synchroniser
  2. Sélectionnez un émulateur dans le menu déroulant des appareils
  3. Cliquez sur le bouton Exécuter ou appuyez sur Shift + F10

Étape 8 : Configurez Live Reload

Pour une mise en œuvre plus rapide, activez la reprise de charge en direct afin que les modifications apparaissent instantanément sur votre appareil.

  1. Trouvez votre adresse IP locale :
# macOS
ipconfig getifaddr en0

# Windows
ipconfig
  1. Create a development Capacitor config. Add to capacitor.config.ts:
import type { CapacitorConfig } from '@capacitor/cli';

const devConfig: CapacitorConfig = {
  appId: 'com.example.mymobileapp',
  appName: 'My Mobile App',
  webDir: 'out',
  server: {
    url: 'http://YOUR_IP_ADDRESS:3000',
    cleartext: true,
  },
  plugins: {
    // ... same plugin config
  },
};

const prodConfig: CapacitorConfig = {
  appId: 'com.example.mymobileapp',
  appName: 'My Mobile App',
  webDir: 'out',
  plugins: {
    // ... same plugin config
  },
};

const config = process.env.NODE_ENV === 'development' ? devConfig : prodConfig;

export default config;
  1. Démarrez le serveur de développement et copiez la configuration vers natif :
bun run dev &
NODE_ENV=development bunx cap copy
  1. Reconstruire dans Xcode/Android Studio

Maintenant, les modifications apportées à votre Next.js code se reflèteront automatiquement sur le dispositif.

Étape 9 : Créez votre première écran mobile

Créons une simple page d'accueil mobile-friendly. src/app/page.tsx:

'use client';

import { useEffect, useState } from 'react';
import { App } from '@capacitor/app';
import { Keyboard } from '@capacitor/keyboard';

export default function Home() {
  const [appInfo, setAppInfo] = useState<{ name: string; version: string } | null>(null);

  useEffect(() => {
    // Get app info on mount
    App.getInfo().then(setAppInfo).catch(console.error);

    // Handle back button on Android
    const backHandler = App.addListener('backButton', ({ canGoBack }) => {
      if (!canGoBack) {
        App.exitApp();
      } else {
        window.history.back();
      }
    });

    // Hide keyboard when tapping outside inputs
    const keyboardHandler = Keyboard.addListener('keyboardWillShow', () => {
      document.body.classList.add('keyboard-open');
    });

    return () => {
      backHandler.then(h => h.remove());
      keyboardHandler.then(h => h.remove());
    };
  }, []);

  return (
    <main className="min-h-screen bg-linear-to-b from-blue-500 to-blue-700 flex flex-col items-center justify-center p-6 text-white">
      <h1 className="text-4xl font-bold mb-4">My Mobile App</h1>
      <p className="text-xl mb-8 text-center opacity-90">
        Built with Next.js 15 + Capacitor 8
      </p>

      {appInfo && (
        <div className="bg-white/20 rounded-lg p-4 backdrop-blur-sm">
          <p className="text-sm">
            {appInfo.name} v{appInfo.version}
          </p>
        </div>
      )}

      <div className="mt-12 space-y-4 w-full max-w-sm">
        <button className="w-full py-4 px-6 bg-white text-blue-600 rounded-xl font-semibold text-lg shadow-lg active:scale-95 transition-transform">
          Get Started
        </button>
        <button className="w-full py-4 px-6 bg-white/20 text-white rounded-xl font-semibold text-lg backdrop-blur-sm active:scale-95 transition-transform">
          Learn More
        </button>
      </div>
    </main>
  );
}

Mise à jour

Étape 10 : Gestion de la zone de sécurité

Les appareils mobiles disposent de notches, d'indicateurs d'accueil et de barres de statut. Ajoutez une gestion de la zone de sécurité avec Tailwind. src/app/globals.css:

@tailwind base;
@tailwind components;
@tailwind utilities;

:root {
  --sat: env(safe-area-inset-top);
  --sar: env(safe-area-inset-right);
  --sab: env(safe-area-inset-bottom);
  --sal: env(safe-area-inset-left);
}

body {
  padding-top: var(--sat);
  padding-right: var(--sar);
  padding-bottom: var(--sab);
  padding-left: var(--sal);
}

/* Prevent text selection on mobile */
* {
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

/* Allow text selection in inputs */
input, textarea {
  -webkit-user-select: auto;
  user-select: auto;
}

/* Keyboard handling */
.keyboard-open {
  --sab: 0px;
}

Mise à jour

Structure du projet

my-mobile-app/
├── android/              # Android native project
├── ios/                  # iOS native project
├── out/                  # Static build output
├── src/
│   ├── app/
│   │   ├── globals.css
│   │   ├── layout.tsx
│   │   └── page.tsx
│   └── ...
├── capacitor.config.ts   # Capacitor configuration
├── next.config.ts        # Next.js configuration
├── package.json
└── ...

Votre projet devrait ressembler à ceci :

Étapes suivantes

Vous avez maintenant une application mobile Next.js fonctionnelle. Voici ce que vous devez faire ensuite : 

  • Icônes de l'application : Remplacez les icônes par défaut dans ios/App/App/Assets.xcassets et android/app/src/main/res
  • Écran de démarrage : Personnalisez dans les projets natifs ou utilisez @capacitor/splash-screen config
  • Liens profonds : Configurez les schémas de URL pour votre application

Ajoutez plus de fonctionnalités

  • Appareil photo : bun add @capacitor/camera
  • Localisation : bun add @capacitor/geolocation
  • Notifications push : bun add @capacitor/push-notifications
  • Le système de fichiers : bun add @capacitor/filesystem

Interface utilisateur native et transitions

Utilisez les plugins Capgo au lieu de Konsta UI pour un sentiment mobile natif :

bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync

Pour les zones sûres de Tailwind, ajoutez @capgo/tailwind-capacitor:

bun add -D tailwind-capacitor

Voir Utilisation de @capgo/capacitor-native-navigation, Utilisation de @capgo/capacitor-transitions, et le le dépôt de tailwind-capacitor pour la configuration spécifique à Next.js.

Résolution des problèmes de disposition iOS (Vueport, Zone de sécurité et débordement horizontal)

Si le contenu semble être coupé, décalé ou scrollable horizontalement sur iOS, ajouter plus ou ajuster le tag Vueport seul ne suffit généralement pas. Travaillez ces vérifications dans l'ordre. overflow-x: hidden Assurez-vous que le tag meta Vueport est appliqué correctement

App Router

): export (app/de viewport Pages Router app/layout.tsx:

import type { Viewport } from 'next';

export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  viewportFit: 'cover',
};

): placez le tag meta Vueport dans (pages/protectedTokens pages/_app.tsxpas _document.tsx.

Gérer l'espace sûr iOS à partir d'un seul enveloppe racine

Créez une coquille d'application unique et appliquez-y une marge d'espace sûr là — et non dans plusieurs composants imbriqués :

html,
body,
#__next {
  width: 100%;
  min-height: 100%;
  margin: 0;
  padding: 0;
  overflow-x: hidden;
}

* {
  box-sizing: border-box;
}

.app-shell {
  min-height: 100dvh;
  width: 100%;
  padding-top: env(safe-area-inset-top);
  padding-right: env(safe-area-inset-right);
  padding-bottom: env(safe-area-inset-bottom);
  padding-left: env(safe-area-inset-left);
}

Enveloppez tout le contenu de la page à l'intérieur .app-shell. La duplication de la marge d'espace sûr dans les en-têtes, les modaux et les enveloppes de disposition rend souvent l'interface utilisateur coupée ou trop grande.

Avec @capgo/tailwind-capacitor, vous pouvez exprimer la même marge avec des utilitaires comme pt-safe pb-safe px-safe sur cette coquille unique.

Fixez Capacitor iOS contentInset à never context : Page/zone : Page de mise à jour en direct. Rôle : Étiquette de l'interface utilisateur courte ou élément de navigation. Clé de message `live_update_dynamic_label_to` (Étiquette de mise à jour dynamique vers).

In capacitor.config.ts, préfèrez l'insérer nativement désactivé et laissez CSS (ou la navigation native) gérer l'espace sûr : contentInsetMode: 'css'Mélanger les __CAPGO_KEEP_0__ automatiques de contenu avec les marges CSS est une cause courante de double espace.

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'my-app',
  webDir: 'out',
  ios: {
    contentInset: 'never',
  },
};

Mixing Capacitor’s automatic content inset with CSS env(safe-area-inset-*) L'élément coupable est généralement un élément utilisant

, Tailwind

, une largeur fixe en pixels, ou une large 100vwDans l'inspecteur Web Safari, exécutez : w-screenAvec Tailwind, remplacez min-width.

par

[...document.querySelectorAll('*')]
  .filter(el => el.scrollWidth > document.documentElement.clientWidth)
  .map(el => ({
    el,
    tag: el.tagName,
    class: el.className,
    scrollWidth: el.scrollWidth,
    clientWidth: document.documentElement.clientWidth,
  }));

avec w-screen par w-full lorsque possible. De nombreux problèmes de débordement horizontal proviennent de 100vw / w-screenune mise en page de zone de sécurité dupliquée, ou d'un conteneur de largeur fixe — et non de la balise meta viewport elle-même.

Mises à jour hors ligne

Configurer Capgo pour envoyer des mises à jour sans résubmission de l'application sur l'app store :

bunx @capgo/cli init

Résolution de problèmes

context : Support / page de support premium ou section de support du pied de page. Rôle : Titre de section ou de page. Vu dans : page support-policy.astro. Message clé `support_policy_troubleshooting_title` (Titre de la politique de support de résolution de problèmes). La construction faille avec « Impossible de trouver le module » bun install Exécuter

et réessayer. iOS : « Aucune identité de signature trouvée »

Android : « emplacement de SDK non trouvé » Créer android/local.properties avec sdk.dir=/path/to/android/sdk

Les modifications ne s'affichent pas sur le dispositif Assurez-vous d'avoir exécuté bun run mobile après avoir apporté des modifications. Pour le rechargement en direct, vérifiez que l'adresse IP est correcte et que le serveur de développement est en cours d'exécution.

Ressources

Prêt à expédier votre application ? Découvrez comment Capgo peut vous aider à livrer des mises à jour plus rapidement — inscrivez-vous à un compte gratuit aujourd'hui.

Continuez de Build a Next.js Mobile App from Scratch avec Capacitor 8

Si vous utilisez Build a Next.js Mobile App from Scratch avec Capacitor 8 pour planifier l'automatisation CI/CD, connectez-l’avec Capgo CI/CD pour le flux de travail du produit dans Capgo CI/CD, Capgo Native Builds pour le flux de travail du produit dans Capgo Native Builds, Capgo Integrations for the product workflow in Capgo Integrations, Intégration CI/CD pour les détails d'implémentation dans l'Intégration CI/CD, et GitHub Actions Integration for the implementation detail in GitHub Actions Integration.

Mises à jour instantanées pour les applications Capacitor

Lorsqu'un bug de la couche web est en ligne, expédiez la correction par le biais de Capgo au lieu d'attendre des jours pour l'approbation de la boutique d'applications. Les utilisateurs reçoivent la mise à jour en arrière-plan tandis que les modifications natives restent dans la voie de revue normale.

Support humain de Martin

Démarrer maintenant

Dernières actualités de notre Blog

Capgo vous donne les meilleures informations dont vous avez besoin pour créer une application mobile vraiment professionnelle.