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 les appareils mobiles dès le départ, puis dans l'emballage de celui-ci sous forme d'applications natives iOS et Android à l'aide 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 les appareils mobiles
- Capacitor 8 with essential plugins
- Applications natives iOS et Android
- Configuration de développement avec rechargement en direct
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éer 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 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.jsimages: { unoptimized: true }— Désactive l'optimisation des images 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 de l'appareil
- @capacitor/préférences — Stockage de valeurs clé-valeur (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 applicationcom.example.mymobileapppar 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 dossiers contenant les projets natifs.
Étape 7 : Construire et Exécuter
Construire votre projet et synchronisez-l’avec les plateformes natives :
bun run mobile
Ouvrez dans l'émulateur iOS :
bun run mobile:ios
Ou l'émulateur Android :
bun run mobile:android
Dans Xcode (iOS) :
- Sélectionnez un simulateur dans le menu déroulant des appareils
- Cliquez sur le bouton Démarrer ou appuyez sur
Cmd + R
Dans Android Studio :
- Attendez que Gradle termine de synchroniser
- Sélectionnez un émulateur dans le menu déroulant des appareils
- Cliquez sur le bouton Exécuter ou appuyez sur
Shift + F10
Étape 8 : Configurer la reprise de vie
Pour un développement plus rapide, activez la reprise de vie pour que les modifications apparaissent instantanément sur votre appareil.
- Trouvez votre adresse IP locale :
# macOS
ipconfig getifaddr en0
# Windows
ipconfig
- 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;
- Démarrer le serveur de développement et copiez la configuration vers natif :
bun run dev &
NODE_ENV=development bunx cap copy
- Reconstruire dans Xcode/Android Studio
Maintenant, les modifications apportées à votre Next.js code se reflètent 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 : Ajoutez un traitement de zone de sécurité
Les appareils mobiles disposent de notches, d'indicateurs d'accueil et de barres de statut. Ajoutez un traitement de 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.xcassetsetandroid/app/src/main/res - Écran d'accueil : Personnalisez dans les projets natifs ou utilisez
@capacitor/splash-screenconfig - Liens profonds : Configurez les schémas de URL pour votre application
Ajoutez plus de fonctionnalités
- Caméra :
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 Capgo plugins au lieu de Konsta UI pour un sentiment de mobile natif :
- @capgo/capacitor-navigation-native — Barre d'onglets Liquid Glass et navbar native
- @capgo/capacitor-transitions — transitions de page ressentant un sentiment 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 repo de tailwind-capacitor pour la configuration spécifique à Next.js.
Résoudre les problèmes de mise en page 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 de vueport seul ne suffit généralement pas. Travaillez à travers ces vérifications dans l'ordre. overflow-x: hidden Assurez-vous que le tag meta de 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',
};
): mettre le tag meta de vueport dans (pages/protectedTokens pages/_app.tsx, pas _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 la mise en forme de l'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 mise en forme de l'espace sûr dupliquée 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-capacitorvous pouvez exprimer la même mise en forme 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 en direct dynamique à).
Dans capacitor.config.ts, préférez l'insérer natif désactivé et laissez CSS (ou la navigation native) contentInsetMode: 'css') posséder l'aire de sécurité :
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'out',
ios: {
contentInset: 'never',
},
};
Mélanger les Capacitor automatiques de contenu de l'insérer avec CSS env(safe-area-inset-*) la marge est une cause courante de double espace.
Trouvez l'élément réellement débordant
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 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-screendes marge de sécurité dupliquée, ou d'un conteneur à 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
Aide au dépannage
context : Page/zone : Support / 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 l'aide au dépannage de la politique de support).
Échec de la construction avec « Impossible de trouver le module » bun install Exécuter
et réessayer. iOS : « Aucune identité de signature trouvée » : Ouvrez Xcode, allez dans Signature et capacités, et sélectionnez votre équipe de développement.
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
- Capacitor 8 Documentation
- Documentation de Next.js 15
- Capgo - Mises à jour en direct
- @capgo/capacitor-navigation-native
- @capgo/capacitor-transitions
- @capgo/tailwind-capacitor
Prêt à envoyer votre application ? Apprenez comment Capgo peut vous aider à livrer des mises à jour plus rapidement — Inscrivez-vous pour 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 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 Intégration d'Actions pour le détail d'implémentation dans GitHub Intégration d'Actions