Sauter au contenu principal
Tutoriel

Créez une application mobile Nuxt à partir de zéro avec Capacitor 8

Étape par étape pour créer un nouveau projet Nuxt 4 et le convertir en applications mobiles natives iOS et Android à l'aide de Capacitor 8. Parfait pour commencer frais avec un développement Vue mobile-first.

Crédits de l'article

Martin Donadieu

Auteur

Valeria

Relecteur

Jordan

Éditeur

Créez une application mobile Nuxt à partir de zéro avec Capacitor 8

Introduction

Voulez-vous créer une application mobile avec Nuxt à partir de zéro ? Ce guide vous guide à travers la création d'un projet Nuxt 4 neuf, configuré pour les appareils mobiles dès le début, puis l'emballeage sous forme d'applications natives iOS et Android à l'aide de Capacitor 8.

À la fin de ce tutoriel, vous aurez une application mobile fonctionnelle exécutant sur des simulateurs que vous pouvez continuer à développer et publier finalement sur l'App Store et Google Play.

Temps requis : ~30 minutes

Ce que vous construisez :

  • Un nouveau projet Nuxt 4 avec la structure de répertoire la plus récente
  • Configuration de génération 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 Nuxt ? Consultez Convertissez votre application Nuxt en mobile au lieu de cela.

Prerequisites

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 (macOS uniquement, pour le développement iOS)
  • Android Studio (pour le développement Android)

Étape 1 : Créez un nouveau projet Nuxt 4

Créez un nouveau projet Nuxt 4 :

bunx nuxi@latest init my-mobile-app
cd my-mobile-app
bun install

Structure de répertoire de Nuxt 4

Nuxt 4 utilise une nouvelle structure de répertoire avec l'application code dans le app/ directory:

my-mobile-app/
  app/
    assets/
    components/
    composables/
    layouts/
    middleware/
    pages/
    plugins/
    utils/
    app.vue
  public/
  server/
  nuxt.config.ts
  package.json

Cette structure offre une meilleure séparation entre l'application et le serveur code.

Étape 2 : Configurez Nuxt pour la génération statique

Capacitor nécessite des fichiers HTML/JS/CSS statiques. Configurez Nuxt pour la génération statique dans nuxt.config.ts:

export default defineNuxtConfig({
  compatibilityDate: '2025-01-15',
  devtools: { enabled: true },

  // Enable static generation
  ssr: true,
  nitro: {
    preset: 'static',
  },
});

Étape 3 : Ajoutez les scripts mobiles

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

{
  "scripts": {
    "dev": "nuxt dev",
    "build": "nuxt build",
    "generate": "nuxt generate",
    "preview": "nuxt preview",
    "mobile": "bun run generate && bunx cap sync",
    "mobile:ios": "bun run mobile && bunx cap open ios",
    "mobile:android": "bun run mobile && bunx cap open android"
  }
}

Testez la génération statique :

bun run generate

Vous devriez voir un .output/public 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

Install essential plugins that most mobile apps need:

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 d'application (avant-plan/arrière-plan, liens profonds)
  • @capacitor/clavier — Contrôle du comportement du clavier
  • @capacitor/écran de démarrage — Contrôle de l'écran de démarrage natif
  • @capacitor/barre d'état — Personnalisez la barre d'état du dispositif
  • @capacitor/préférences — Stockage de valeurs clés (comme localStorage mais natif)

Étape 5 : Initialisez Capacitor

Initialisez Capacitor avec vos détails de projet :

bunx cap init "My Mobile App" com.example.mymobileapp --web-dir .output/public

Remplacez :

  • "My Mobile App" par le nom d'affichage de votre application
  • com.example.mymobileapp avec votre ID d'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: '.output/public',
  plugins: {
    SplashScreen: {
      launchShowDuration: 2000,
      launchAutoHide: true,
      androidScaleType: 'CENTER_CROP',
      splashFullScreen: true,
      splashImmersive: true,
    },
    Keyboard: {
      resize: 'body',
      resizeOnFullScreen: true,
    },
    StatusBar: {
      style: 'dark',
    },
  },
};

export default config;

Étape 6 : Ajouter 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 les répertoires 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 Android Emulateur :

bun run mobile:android

In Xcode (iOS) :

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

In Android Studio :

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

Étape 8 : Configurez le Live Reload

For faster development, enable live reload so changes appear instantly on your device.

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

# Windows
ipconfig
  1. Créez une configuration de développement Capacitor. Mettez à jour capacitor.config.ts:
import type { CapacitorConfig } from '@capacitor/cli';

const devConfig: CapacitorConfig = {
  appId: 'com.example.mymobileapp',
  appName: 'My Mobile App',
  webDir: '.output/public',
  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: '.output/public',
  plugins: {
    // ... same plugin config
  },
};

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

export default config;
  1. Start the dev server and copy config to native:
bun run dev &
NODE_ENV=development bunx cap copy
  1. Reconstruire dans Xcode/Android Studio

Now edits to your Nuxt code will hot-reload on the device.

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

Créons une page d'accueil mobile améliorée. Mettre à jour app/app.vue:

<template>
  <NuxtPage />
</template>

Créer app/pages/index.vue:

<template>
  <main
    class="min-h-screen bg-linear-to-b from-green-500 to-green-700 flex flex-col items-center justify-center p-6 text-white"
  >
    <h1 class="text-4xl font-bold mb-4">My Mobile App</h1>
    <p class="text-xl mb-8 text-center opacity-90">
      Built with Nuxt 4 + Capacitor 8
    </p>

    <div v-if="appInfo" class="bg-white/20 rounded-lg p-4 backdrop-blur-sm mb-8">
      <p class="text-sm">
        {{ appInfo.name }} v{{ appInfo.version }}
      </p>
    </div>

    <div class="space-y-4 w-full max-w-sm">
      <button
        class="w-full py-4 px-6 bg-white text-green-600 rounded-xl font-semibold text-lg shadow-lg active:scale-95 transition-transform"
        @click="handleGetStarted"
      >
        Get Started
      </button>
      <button
        class="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"
        @click="handleShare"
      >
        Share App
      </button>
    </div>
  </main>
</template>

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { App } from '@capacitor/app';

const appInfo = ref<{ name: string; version: string } | null>(null);

let backButtonListener: { remove: () => void } | null = null;

onMounted(async () => {
  // Get app info
  try {
    appInfo.value = await App.getInfo();
  } catch (e) {
    // Web fallback
    appInfo.value = { name: 'My Mobile App', version: '1.0.0' };
  }

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

onUnmounted(() => {
  backButtonListener?.remove();
});

function handleGetStarted() {
  // Navigate to onboarding or main app
  console.log('Get started clicked');
}

async function handleShare() {
  // We'll implement this with the Share plugin later
  console.log('Share clicked');
}
</script>

Étape 10 : Ajouter Tailwind CSS

Pour que la mise en forme fonctionne, ajoutez Tailwind CSS à votre projet :

bun add tailwindcss @tailwindcss/vite

Mettre à jour nuxt.config.ts:

import tailwindcss from '@tailwindcss/vite';

export default defineNuxtConfig({
  compatibilityDate: '2025-01-15',
  devtools: { enabled: true },

  ssr: true,
  nitro: {
    preset: 'static',
  },

  css: ['~/assets/css/main.css'],

  vite: {
    plugins: [tailwindcss()],
  },
});

Créer app/assets/css/main.css:

@import 'tailwindcss';

: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;
}

Étape 11 : Ajouter le plugin de partage

Implémentons la fonctionnalité du bouton de partage :

bun add @capacitor/share

Mettre à jour app/pages/index.vue pour utiliser le plugin de partage :

<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { App } from '@capacitor/app';
import { Share } from '@capacitor/share';

// ... existing code ...

async function handleShare() {
  try {
    await Share.share({
      title: 'Check out this app!',
      text: 'Built with Nuxt 4 and Capacitor 8',
      url: 'https://capacitorjs.com',
      dialogTitle: 'Share with friends',
    });
  } catch (e) {
    console.log('Share cancelled or failed:', e);
  }
}
</script>

Mettre à jour et reconstruire :

bun run mobile

Structure du projet

Votre projet devrait ressembler à ceci :

my-mobile-app/
├── android/                  # Android native project
├── ios/                      # iOS native project
├── .output/
│   └── public/              # Static build output
├── app/
│   ├── assets/
│   │   └── css/
│   │       └── main.css
│   ├── pages/
│   │   └── index.vue
│   └── app.vue
├── capacitor.config.ts       # Capacitor configuration
├── nuxt.config.ts            # Nuxt configuration
├── package.json
└── ...

Étapes suivantes

Vous avez maintenant une application mobile Nuxt fonctionnelle. Voici ce que faire ensuite.

Configuration essentielle

  • App Icons: Remplacer les icônes par défaut dans ios/App/App/Assets.xcassets et android/app/src/main/res
  • Écran d'accueil : Personnalisez dans des projets natifs ou utilisez @capacitor/splash-screen config
  • Lien Profond : Configurez les schémas d'URL pour votre application

Ajouter des fonctionnalités

  • Caméra : bun add @capacitor/camera
  • Localisation : bun add @capacitor/geolocation
  • Notifications de Push : bun add @capacitor/push-notifications ou @capgo/capacitor-messaging-firebase pour Firebase Cloud Messaging sur iOS et Android
  • Système de fichiers : bun add @capacitor/filesystem

Interface utilisateur natif et transitions

Utilisez les plugins Capgo au lieu de Konsta UI pour un sentiment de 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 les repo de Tailwind-capacitor pour la configuration spécifique à Nuxt.

Résoudre les problèmes de disposition sur iOS (Vueport, zone de sécurité et débordement horizontal)

Si le contenu semble coupé, décalé ou déroulable horizontalement sur iOS, ajouter plus overflow-x: hidden ou ajuster seul le tag de vueport ne résout généralement pas le problème. Travaillez à travers ces vérifications dans l'ordre.

Assurez-vous que le tag de métadonnées de vueport est appliqué correctement

In nuxt.config.ts, définissez la vueport par app.head:

export default defineNuxtConfig({
  app: {
    head: {
      meta: [
        {
          name: 'viewport',
          content: 'width=device-width, initial-scale=1, viewport-fit=cover',
        },
      ],
    },
  },
});

Gérer la zone de sécurité iOS à partir d'un seul enveloppe racine

Créez un noyau d'application unique et appliquez-y un padding de zone de sécurité là, et non dans plusieurs composants imbriqués.

html,
body,
#__nuxt {
  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);
}

Entourer tout le contenu de la page .app-shellLes marges de sécurité dupliquées dans les en-têtes, les modaux et les enveloppes de mise en page rendent souvent l'interface utilisateur coupée ou trop grande.

With @capgo/tailwind-capacitor, vous pouvez exprimer le même écartement avec des utilitaires comme pt-safe pb-safe px-safe on ce seul shell.

Configurez Capacitor iOS contentInset à never first

premier capacitor.config.tsPréférez l'interface native désactivée et laissez CSS (ou la navigation native) contentInsetMode: 'css'Propriétaire de la zone de sécurité :

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

Mélanger les Capacitor automatiques d'encadré de contenu avec CSS env(safe-area-inset-*) l'écartement est une cause fréquente de double espace.

Trouvez l'élément débordant réel

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 avec w-full lorsque possible. De nombreux problèmes de débordement horizontal proviennent de 100vw / w-screenPas de padding de zone de sécurité dupliquée ou d'un conteneur à largeur fixe — pas de la balise meta viewport elle-même.

Mises à jour hors ligne

Configurez Capgo pour envoyer des mises à jour sans résubmission de l'App Store :

bunx @capgo/cli init

Troubleshooting

Échec de construction avec « Cannot find module » Exécuter bun install et tenter à nouveau.

iOS : « No signing identity found » Ouvrez Xcode, allez à 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 les modifications. Vérifiez l'adresse IP est correcte et le serveur de développement est en cours d'exécution.

.output/public est vide ou manquant Assurez-vous que vous avez configuré nitro: { preset: 'static' } dans nuxt.config.ts et exécutez bun run generate.

Ressources

Ready to ship your app? Learn how Capgo can help you deliver updates faster — Inscrivez-vous à un compte gratuit Aujourd'hui.

Continuez à partir de Construire une application mobile Nuxt à partir de zéro avec Capacitor 8

Si vous utilisez Construire une application mobile Nuxt à partir de zéro 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 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 les détails 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.

Mises à jour instantanées pour les applications Capacitor

When a web-layer bug is live, ship the fix through Capgo instead of waiting days for app store approval. Users get the update in the background while native changes stay in the normal review path.

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.