Introduzione
Vuoi costruire 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 pacchettizzarlo come app native iOS e Android utilizzando Capacitor 8.
Al termine di questo tutorial, avrai un'app mobile funzionante che esegue i 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 con plugin essenziali
- Applicazioni native iOS e Android
- Setup di sviluppo con reload live
Se già hai un'app Nuxt, consulta 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)
Step 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
Inizia creando un nuovo progetto Nuxt 4:
Nuxt 4 utilizza una nuova struttura di directory con l'app code nel app/ directory:
my-mobile-app/
app/
assets/
components/
composables/
layouts/
middleware/
pages/
plugins/
utils/
app.vue
public/
server/
nuxt.config.ts
package.json
This structure provides better separation between app and 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 Testa la generazione statica:
{
"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"
}
}
Prova la generazione statica:
bun run generate
directory con i tuoi file statici. .output/public Passo 4: Installa __CAPGO_KEEP_0__ 8
Installa i pacchetti di base di Capacitor:
Installa i pacchetti core Capacitor:
bun add @capacitor/core
bun add -D @capacitor/cli
Installare i plugin essenziali necessari a molti app mobili:
bun add @capacitor/app @capacitor/keyboard @capacitor/splash-screen @capacitor/status-bar @capacitor/preferences
@__CAPGO_KEEP_0__/app
- @capacitor/app Eventi di ciclo di vita dell'app (in primo piano/trasparenza, link profondi)
- @capacitor/keyboard — Gestione del comportamento del tastierino
- @capacitor/splash-screen — Controllo della schermata di avvio nativa
- @capacitor/status-bar — Stilella barra dello stato del dispositivo
- @capacitor/preferences — Archiviazione chiave-valore (come localStorage ma nativa)
Step 5: Initialize 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 appcom.example.mymobileappcon il tuo ID dell'applicazione (notazione di dominio inverso)
Questo 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
Installare 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 i directory contenenti i progetti nativi.
Passo 7: Costruisci e Esegui
Costruisci il tuo progetto e sincronizza con le piattaforme native:
bun run mobile
Apri in iOS Simulator:
bun run mobile:ios
Ora Android Emulator:
bun run mobile:android
In Xcode (iOS):
- Seleziona un simulatore dal menu a discesa dei dispositivi
- Clicca sul pulsante Play o premi
Cmd + R
In Android Studio:
- Aspetta che Gradle finisca di sincronizzare
- Seleziona un emulatore dal menu a discesa dei dispositivi
- Clicca sul pulsante Run o premi
Shift + F10
Passo 8: Configura Live Reload
Per un sviluppo più veloce, abilita il reload in tempo reale per visualizzare i cambiamenti istantaneamente sul tuo dispositivo.
- Trova l'indirizzo IP locale:
# macOS
ipconfig getifaddr en0
# Windows
ipconfig
- Crea una configurazione di sviluppo Capacitor. Aggiorna
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;
- Avvia il server di sviluppo e copia la configurazione nativa:
bun run dev &
NODE_ENV=development bunx cap copy
- Riavvia in Xcode/Android Studio
Ora le modifiche al tuo Nuxt code si ricollegheranno automaticamente sul dispositivo.
Passo 9: Crea la tua prima schermata mobile
Creiamo una schermata home adatta ai 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>
Passo 10: Aggiungi Tailwind CSS
Perché il styling funzioni, aggiungi Tailwind CSS al tuo progetto:
bun add tailwindcss @tailwindcss/vite
Aggiorna 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;
}
Passo 11: Aggiungi il Plugin di Condivisione
Implementiamo la funzionalità del pulsante di condivisione:
bun add @capacitor/share
Aggiorna app/pages/index.vue per utilizzare il plugin di condivisione:
<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>
Sincronizza e ricostruisci:
bun run mobile
Struttura del Progetto
Il tuo 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
└── ...
Next Steps
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.xcassetsEandroid/app/src/main/res - Pantalla di avvio: Personalizza nei progetti nativi o utilizza
@capacitor/splash-screenconfig - Deep Links: Configura i schemi di URL per la tua app
Aggiungi Funzionalità
- Camera:
bun add @capacitor/camera - Geolocalizzazione:
bun add @capacitor/geolocation - Notifiche Push:
bun add @capacitor/push-notificationso @capgo/capacitor-messaging-firebase per Firebase Cloud Messaging su iOS e Android - Sistema di File:
bun add @capacitor/filesystem
Interfaccia nativa e transizioni
Usa i plugin Capgo al posto di Konsta UI per un'esperienza mobile nativa:
- @capgo/capacitor-navigazione-nativa — Liquid Glass barra delle schede e navbar nativa
- @capgo/capacitor-transizioni transizioni di pagina con un sentimento nativo
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 Usare @capgo/capacitor-navigazione-nativa, Usare @capgo/capacitor-transizioni, e repository tailwind-capacitor per la configurazione specifica di Nuxt.
Risolvere i problemi di layout iOS (Viewport, Area di sicurezza e sovrapposizione orizzontale)
Se il contenuto sembra tagliato, spostato o scorrevole orizzontalmente su iOS, aggiungere più overflow-x: hidden Raramente risolvere il problema modificando solo la tag viewport risolve il problema. Esegui questi controlli in ordine.
Assicurati che il tag meta viewport sia applicato correttamente
In nuxt.config.tsImposta il viewport attraverso app.head:
export default defineNuxtConfig({
app: {
head: {
meta: [
{
name: 'viewport',
content: 'width=device-width, initial-scale=1, viewport-fit=cover',
},
],
},
},
});
Utilizza l'area di sicurezza iOS da un wrapper radice solo
Crea un guscio di app singolo e applica il padding di area sicura lì — non in componenti nidificati multipli:
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);
}
Wrappa tutto il contenuto della pagina all'interno .app-shellRisolvere i problemi di layout iOS (Viewport, Area di sicurezza e sovrapposizione orizzontale)
With @capgo/tailwind-capacitor, puoi esprimere la stessa spaziatura con utilità come pt-safe pb-safe px-safe on che singola shell.
Imposta Capacitor iOS contentInset su never first
primo capacitor.config.tsprefer l'interfaccia nativa disabilitata e lasciare che CSS (o la navigazione nativa) contentInsetMode: 'css'Possiedi l'area di sicurezza
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: '.output/public',
ios: {
contentInset: 'never',
},
};
Mixing Capacitor’s automatic content inset con CSS env(safe-area-inset-*) Mescolare __CAPGO_KEEP_0__’s automatico contenuto insetto con CSS
Trova l'elemento che si sta sovrapponendo
Il colpevole più comune è un elemento che utilizza 100vw, Tailwind w-screenuna larghezza fissa di pixel, 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,
}));
Con Tailwind, sostituisci w-screen con w-full quando possibile. Molti problemi di sovrapposizione orizzontale derivano da 100vw / w-screen, la duplicazione di padding di area sicura o un contenitore di larghezza fissa — non dal tag meta viewport stesso.
Aggiornamenti Over-the-Air
Configura Capgo per far aggiornare senza riconvalidazione dell'app store:
bunx @capgo/cli init
Risolvere i problemi
Costruzione fallita con “Cannot find module”
Esegui bun install Costruzione fallita con “Cannot find module”
iOS: "Identità di firma non trovata" Apri Xcode, vai a Signing & Capabilità, e seleziona il tuo team di sviluppo.
Android: “SDK non trovato”
Create android/local.properties with sdk.dir=/path/to/android/sdk
Modifiche non visibili sul dispositivo
Esegui il controllo per assicurarti bun run mobile Dopo aver effettuato modifiche. Verifica l'indirizzo IP per il live reload e assicurati che il server di sviluppo sia in esecuzione.
.output/public è vuoto o mancante
Assicurati di aver configurato nitro: { preset: 'static' } in nuxt.config.ts e esegui bun run generate.
Risorse
- Capacitor 8 Documentazione
- Nuxt 4 Documentazione
- Documentazione Capgo 8
- @capgo/capacitor-navigazione nativa
- @capgo/capacitor-transizioni
- @capgo/tailwind-capacitor
Pronto a distribuire il tuo app? Scopri come Capgo può aiutarti a consegnare aggiornamenti più velocemente — iscrivi 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 CI/CD per il flusso di lavoro del prodotto in Capgo CI/CD, Capgo Costruzioni native per il flusso di lavoro del prodotto in Capgo Costruzioni native, Capgo Integrazioni per il workflow del prodotto in Integrazioni Capgo Integrazione CI/CD per i dettagli di implementazione nella integrazione CI/CD, e GitHub Actions Integration per i dettagli di implementazione in GitHub Integrazione delle azioni.