Passer au contenu principal
Guide de tutorat

Build a Next.js Mobile App from Scratch with Capacitor 8

Step-by-step guide to creating a new Next.js 15 project and turning it into native iOS and Android mobile apps using Capacitor 8. Perfect for starting fresh with mobile-first development.

Martin Donadieu

Martin Donadieu

Spécialiste du contenu

Build a Next.js Mobile App from Scratch with 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 nouveau projet Next.js 15 configuré pour le mobile dès le départ, puis dans la mise en boîte de celui-ci en applications natives iOS et Android à l'aide de Capacitor 8.

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

Durée requise : ~30 minutes

Ce que vous allez construire :

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

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

Prérequis

Vérifiez que vous avez ces éléments installés :

  • Node.js 18+ (vérifiez avec node --version)
  • Bun gestionnaire de package (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 frais :

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 stylisation mobile)
  • src/ répertoire : Oui
  • App Router : Oui (recommandé)
  • Alias d'importation : Par défaut (@/*)

Naviguez vers votre projet :

cd my-mobile-app

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

Capacitor nécessite des fichiers HTML/JS/CSS statiques. Configurez Next.js pour l'export 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 des images Next.js (nécessite un serveur)
  • trailingSlash: true — Assure une navigation correcte dans la vue WebView native

Étape 3 : Ajoutez des 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 noyau 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ôle du comportement de la touche clavier
  • @capacitor/splash-screen — Contrôle de l'écran de splash natif
  • @capacitor/status-bar — Personnalisez la barre d'état du dispositif
  • @capacitor/préférences — Stockage clé-valeur (comme localStorage mais natif)

Étape 5 : Initialiser Capacitor

Initialisez Capacitor avec vos détails de projet :

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

Remplacez :

  • "My Mobile App" par le nom 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

Créez les projets natifs :

bunx cap add ios
bunx cap add android

Cela crée ios et android les répertoires contenant les projets natifs.

Étape 7 : Construire et Exécuter

Construire votre projet et synchroniser avec les plateformes natives :

bun run mobile

Ouvrir dans l'émulateur iOS :

bun run mobile:ios

Ou émulateur Android :

bun run mobile:android

Dans Xcode (iOS) :

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

Dans Android Studio :

  1. Attendez que Gradle termine de synchroniser
  2. Choisissez 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 un développement plus rapide, activez Live Reload afin que les modifications apparaissent instantanément sur votre appareil.

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

# Windows
ipconfig
  1. Créez un fichier de configuration de développement Capacitor. Ajoutez-l’à 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. Rebâtissez dans Xcode/Android Studio

Maintenant, les modifications apportées à votre Next.js code se reflèteront directement sur l'appareil.

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

Créons une simple page d'accueil mobile-friendly. Mettez à jour 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>
  );
}

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

Les appareils mobiles disposent de notches, d'indicateurs de maison et de barres de statut. Ajoutez une gestion de la zone de sécurité avec Tailwind.

Mise à jour 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;
}

Structure du projet

Votre projet devrait ressembler à ceci :

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
└── ...

Étapes suivantes

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

Configuration essentielle

  • 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 d'URL pour votre application

Ajoutez plus de fonctionnalités

  • Caméra : bun add @capacitor/camera
  • Localisation géographique : bun add @capacitor/geolocation
  • Notifications Push : bun add @capacitor/push-notifications
  • Système de fichiers : bun add @capacitor/filesystem

Interface utilisateur et transitions natives

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 de sécurité Tailwind, ajoutez @capgo/tailwind-capacitor:

bun add -D tailwind-capacitor

Voir Utilisation de @capgo/capacitor-native-navigation, Utilisation de @capgo/capacitor-transitions, et le repo tailwind-capacitor pour la configuration spécifique à Next.js. Résolution des problèmes de mise en page iOS (Vueport, zone de sécurité, et débordement horizontal)

Corrections des problèmes de mise en page iOS (Vueport, zone de sécurité, et débordement horizontal)

Si le contenu semble coupé, décalé ou scrollable horizontalement sur iOS, ajouter plus overflow-x: hidden ou ajuster la balise de viewport seul ne résout généralement pas le problème. Passer par ces vérifications dans l'ordre.

Vérifiez que la balise meta de viewport est appliquée correctement

App Router (app/export viewport à partir de app/layout.tsx:

import type { Viewport } from 'next';

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

Pages Router (pages/): placez la balise de viewport dans pages/_app.tsxpas _document.tsx.

Gérez l'espace sûr d'iOS à partir d'un seul wrapper racine

Créez une coquille d'application unique et appliquez-y une mise en forme de l'espace sûr — pas 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 mise en forme de la zone de sécurité redondante dans les en-têtes, les modaux et les enveloppes de mise en page rend souvent l'interface utilisateur coupée ou trop grande.

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

Définissez Capacitor iOS contentInset en premier never Dans

, préférez l'inset natif désactivé et laissez CSS (ou la navigation native) capacitor.config.tsprendre en charge la zone de sécurité : contentInsetMode: 'css'Mélanger les inset de contenu automatique de __CAPGO_KEEP_0__ avec CSS

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-*) le padding est une cause courante de double espace.

Trouvez l'élément qui déborde vraiment

Le coupable habituel est un élément utilisant 100vw, Tailwind w-screen, une largeur de pixels fixe, ou une large min-width.

Dans l'Inspecteur Web de Safari, exécutez :

[...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 Tailwind, remplacez w-screen par w-full lorsque possible. De nombreux problèmes de débordement horizontal proviennent de 100vw / w-screen, de la duplication de la marge de sécurité, ou d'un conteneur à largeur fixe — et non de la balise meta de la vue d'ensemble elle-même.

Mises à jour par voie aérienne

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

bunx @capgo/cli init

Résolution des problèmes

La construction échoue avec « Cannot find module » Exécuter bun install et réessayer.

iOS : « Pas d'identité de signature trouvée » Ouvrez Xcode, allez dans Signing &amp; Capabilities, et sélectionnez votre équipe de développement.

Android : « SDK location not found » 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 — s'inscrire à un compte gratuit aujourd'hui.

Continuez de Build une application mobile Next.js à partir de zéro avec Capacitor 8

Si vous utilisez Build une application mobile Next.js à partir de zéro avec Capacitor 8 pour planifier l'automatisation de CI/CD, connectez-l’avec Capgo CI/CD pour le flux de travail du produit dans Capgo CI/CD, Capgo Builds natifs pour le flux de travail du produit dans Capgo Builds natifs, Capgo Intégrations pour le flux de travail du produit dans Capgo Intégrations, Intégration CI/CD pour le détail d'implémentation dans Intégration CI/CD, et GitHub Actions d'intégration pour les détails d'implémentation dans GitHub Actions d'intégration.

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

Mises à jour en temps réel pour les applications Capgo

Contexte : Page/zone : Site web de marketing Capgo. Rôle : Phrase de copie du site web. Vu dans : composant GetStarted.astro. Préservez les termes de produit/branche et les termes de développeur de Capgo exactement. Clé de message `instant_updates_for_capacitor_apps` (Mises à jour instantanées pour les applications Capacitor).

Commencez dès maintenant

Dernières actualités de notre Blog

Capgo vous offre les meilleures informations nécessaires pour créer une application mobile véritablement professionnelle.