Saltare al contenuto principale
Guida pratica

Crea un'app mobile Nuxt da zero con Capacitor 8

Passo dopo passo per creare un nuovo progetto Nuxt 4 e trasformarlo in app mobili native per iOS e Android utilizzando Capacitor 8. Perfetto per iniziare con lo sviluppo mobile-first di Vue.

Crediti dell'articolo

Martin Donadieu

Autore

Valeria

Recensore

Jordan

Curatore

Crea un'app mobile Nuxt da zero con Capacitor 8

Introduzione

Vuoi creare un'app mobile con Nuxt dall'alto in basso? Questa guida ti guida attraverso la creazione di un nuovo progetto Nuxt 4 configurato per la mobilità fin dal primo giorno, quindi pacchettizzalo come app native iOS e Android utilizzando Capacitor 8.

Al termine di questo tutorial, avrai un'app mobile funzionante che esegue su simulatori che puoi continuare a sviluppare e pubblicare infine sullo Store App e Google Play.

Tempo richiesto: ~30 minuti

Cosa costruirai:

  • Un nuovo progetto Nuxt 4 con la struttura di directory più recente
  • Configurazione di generazione statica per la mobilità
  • Capacitor 8 with essential plugins
  • App native iOS e Android
  • Setup di sviluppo con live reload

Hai già un'app Nuxt? Converti la tua app Nuxt in mobile invece.

Prerequisiti

Assicurati di avere installati:

  • Node.js 18+ (controlla con node --version)
  • Bun gestore dei pacchetti (curl -fsSL https://bun.sh/install | bash)
  • Xcode (solo per macOS, per lo sviluppo di iOS)
  • Android Studio (per lo sviluppo di Android)

Passo 1: Crea un nuovo progetto Nuxt 4

Inizia creando un nuovo progetto Nuxt 4:

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

Struttura di directory di Nuxt 4

Nuxt 4 utilizza una nuova struttura di directory con app code nella app/ directory:

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

Questa struttura fornisce una migliore separazione tra app e server code.

Passo 2: Configura Nuxt per la generazione statica

Capacitor richiede file HTML/JS/CSS statici. Configura Nuxt per la generazione statica in nuxt.config.ts:

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

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

Passo 3: Aggiungi script mobili

Aggiorna il tuo package.json con script di sviluppo 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"
  }
}

Verifica la generazione statica:

bun run generate

Dovresti vedere un .output/public directory con i tuoi file statici.

Passo 4: Installa Capacitor 8

Installa i pacchetti core di Capacitor:

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

Installa i plugin essenziali che la maggior parte delle app mobili richiede:

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

Cosa fanno questi plugin:

  • @capacitor/app — Eventi di ciclo di vita dell'app (in primo piano/ in background, collegamenti profondi)
  • @capacitor/keyboard — Controllo del comportamento della tastiera
  • @capacitor/splash-screen — Controllo schermo di avvio nativo
  • @capacitor/status-bar — Stilizza la barra dello stato del dispositivo
  • @capacitor/preferences — Archiviazione chiave-valore (come localStorage ma nativa)

Passo 5: Inizializza Capacitor

Inizializza Capacitor con i dettagli del tuo progetto:

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

Sostituisci:

  • "My Mobile App" con il nome della tua app
  • com.example.mymobileapp con l'ID dell'app (notazione di dominio inverso)

Ciò crea capacitor.config.ts. Aggiornalo con la configurazione del 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;

Passo 6: Aggiungi piattaforme native

Installa i pacchetti delle piattaforme:

bun add @capacitor/ios @capacitor/android

Genera i progetti nativi:

bunx cap add ios
bunx cap add android

Questo crea ios e android directory contenenti i progetti nativi.

Passo 7: Costruisci e Esegui

Costruisci il tuo progetto e sincronizza con le piattaforme native:

bun run mobile

Apre in iOS Simulator:

bun run mobile:ios

O Android Emulator:

bun run mobile:android

In Xcode (iOS):

  1. Scegli un simulatore dal menu a discesa dei dispositivi
  2. Clicca sul pulsante Play o premi Cmd + R

In Android Studio:

  1. Aspetta che Gradle si sincronizzi
  2. Seleziona un emulatore dalla lista dispositivo
  3. Clicca sul pulsante Esegui o premi Shift + F10

Passo 8: Configura Live Reload

Per un sviluppo più veloce, abilita il live reload affinché le modifiche appariscano istantaneamente sul tuo dispositivo.

  1. Trova l'indirizzo IP locale:
# macOS
ipconfig getifaddr en0

# Windows
ipconfig
  1. Create a development Capacitor config. Update 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. Avvia il server di sviluppo e copia la configurazione in nativo:
bun run dev &
NODE_ENV=development bunx cap copy
  1. Riavvia in Xcode/Android Studio

Ora le modifiche al tuo Nuxt code si ricollegheranno automaticamente sul dispositivo.

Step 9: Crea la Prima Schermata Mobile

Crea una schermata di home amichevole per dispositivi mobili. Aggiorna app/app.vue:

<template>
  <NuxtPage />
</template>

Crea 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>

Step 10: Aggiungi Tailwind CSS

Perché il styling funzioni, aggiungi Tailwind CSS al tuo progetto:

bun add tailwindcss @tailwindcss/vite

Crea 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()],
  },
});

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

Step 11: Aggiungi il Plugin di Condivisione

Crea una funzionalità di pulsante di condivisione:

bun add @capacitor/share

Aggiorna per utilizzare il plugin di condivisione: app/pages/index.vue Sincronizza e ricostruisci:

<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>

Aggiorna per utilizzare il plugin di condivisione:

bun run mobile

Struttura del Progetto

La tua progetto dovrebbe ora avere questo aspetto:

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

Passaggi Successivi

Ora hai un'app mobile Nuxt funzionante. Ecco cosa fare successivamente:

Configurazione Essenziale

  • Icône dell'App: Sostituisci le icône predefinite in ios/App/App/Assets.xcassets E android/app/src/main/res
  • Schermo di Avvio: Personalizza in progetti nativi o utilizza @capacitor/splash-screen config
  • Collegamenti Profondi: Configura i schemi di URL per la tua app

Aggiungi più funzionalità

  • Camera: bun add @capacitor/camera
  • Geolocalizzazione: bun add @capacitor/geolocation
  • Push Notifications: bun add @capacitor/push-notifications o @capgo/capacitor-firebase-messaging Perché scegliere tra le alternative?
  • Perché scegliere tra le alternative? bun add @capacitor/filesystem

Perché scegliere tra le alternative?

Use Capgo plugins instead of Konsta UI for a native mobile feel:

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

Per aree sicure di Tailwind, aggiungi @capgo/tailwind-capacitor:

bun add -D tailwind-capacitor

Vedi Utilizzo di @capgo/capacitor-navigazione nativa, Utilizzo di @capgo/capacitor-transizionie il repo tailwind-capacitor per la configurazione specifica di Nuxt.

Risolvere gli issue di layout iOS (Viewport, Area sicura e sovrapposizione orizzontale)

If il contenuto sembra essere tagliato, spostato o scorrevole orizzontalmente su iOS, aggiungere più overflow-x: hidden o regolare la tag di viewport da solo non risolve spesso il problema. Esegui questi controlli in ordine.

Assicurati che la tag meta viewport sia applicata correttamente

In nuxt.config.ts, impostare il viewport tramite app.head:

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

Gestisci l'area di sicurezza di iOS da un wrapper radice solo

Crea un unico contenitore dell'applicazione e applica il padding dell'area di sicurezza lì — non in più componenti nidificati:

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

Avvolgi tutto il contenuto della pagina all'interno di .app-shellAggiungere padding dell'area di sicurezza duplicato nei moduli, nelle finestre di dialogo e nei wrapper di layout spesso fa sembrare l'interfaccia utente tagliata o troppo grande.

Con @capgo/tailwind-capacitorpuoi esprimere lo stesso padding con utilità come pt-safe pb-safe px-safe su quella singola shell.

Imposta Capacitor iOS contentInset a never primo

In capacitor.config.ts, preferisci l'ingombro nativo disabilitato e lascia che CSS (o la navigazione nativa) si occupi dell'area sicura: contentInsetMode: 'css'Il mixaggio dell'ingombro automatico di contenuto di __CAPGO_KEEP_0__ con CSS

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

Mixing Capacitor’s automatic content inset with CSS env(safe-area-inset-*) Trova l'elemento che sta effettivamente sovrapprendendo

Il solito colpevole è un elemento che utilizza

, Tailwind 100vwpreferisci l'ingombro nativo disabilitato e lascia che CSS (o la navigazione nativa) si occupi dell'area sicura: w-screenuna larghezza di pixel fissi, o una grande min-width.

In Safari Web Inspector, esegui:

[...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,
  }));

Sostituisci con w-screen con w-full quando possibile. Molti problemi di sovrapposizione orizzontale derivano da 100vw / w-screenduplicati padding di area sicura, o da un contenitore di larghezza fissata — non dal tag meta viewport stesso.

Aggiornamenti Over-the-Air

Configura Capgo per inviare aggiornamenti senza la riconvalidazione dell'app store:

bunx @capgo/cli init

Risoluzione dei problemi

Costruzione fallita con “Cannot find module” Avvia bun install e riprova.

iOS: “Non è stato trovato alcun identità di firma” Apri Xcode, vai a Signing & Capabilities e seleziona il tuo team di sviluppo.

Android: “SDK location not found” Crea android/local.properties con sdk.dir=/path/to/android/sdk

Le modifiche non si visualizzano sul dispositivo Assicurati di aver eseguito bun run mobile dopo aver apportato modifiche. Per il live reload, verifica che l'indirizzo IP sia corretto e che il server di sviluppo sia in esecuzione.

La cartella .output/public è vuota o mancante Assicurati di aver configurato nitro: { preset: 'static' } su nuxt.config.ts e esegui bun run generate.

Risorse

Siete pronti a spedire la vostra app? Scoprite come Capgo possa aiutarvi a consegnare aggiornamenti più velocemente — iscrivetevi a un account gratuito oggi.

Continua da Costruisci un'app mobile Nuxt da zero con Capacitor 8

Se stai utilizzando Costruisci un'app mobile Nuxt da zero con Capacitor 8 per pianificare l'automazione CI/CD, connettilo con Capgo Automazione CI/CD per il flusso di lavoro del prodotto in Capgo Automazione CI/CD, Capgo Costruzioni native per il flusso di lavoro del prodotto in Capgo Costruzioni native, Capgo Integrazioni per il flusso di lavoro del prodotto in Capgo Integrazioni, Integrazione CI/CD per il dettaglio di implementazione in Integrazione CI/CD, e GitHub Azioni di integrazione per i dettagli di implementazione in GitHub Azioni di integrazione.

Aggiornamenti in tempo reale per le app Capacitor

Quando un bug nel layer web è attivo, invia la correzione attraverso Capgo invece di attendere giorni per l'approvazione della store. Gli utenti ricevono l'aggiornamento in background mentre le modifiche native rimangono nel normale percorso di revisione.

Sostegno umano da Martin

Inizia subito

Dai ultimi nostri articoli

Capgo ti offre le migliori informazioni che ti servono per creare un'app mobile davvero professionale.