Introduzione
Vuoi costruire un'app mobile con Nuxt da zero? Questa guida ti guida attraverso la creazione di un nuovo progetto Nuxt 4 configurato per la mobilità fin dal primo giorno, poi lo pacchetta come app native per iOS e Android utilizzando Capacitor 8.
Alla fine di questo tutorial, avrai un'app mobile funzionante che esegue su simulatori e 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 dispositivi mobili
- Capacitor 8 con plugin essenziali
- Applicazioni nativi iOS e Android
- Impostazione di sviluppo con live reload
Hai già un'app Nuxt? Ecco cosa fare: Converti la tua app Nuxt in mobile invece.
Requisiti preliminari
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 progetto Nuxt 4 fresco:
bunx nuxi@latest init my-mobile-app
cd my-mobile-app
bun install
Struttura di directory di Nuxt 4
Utilizza Nuxt 4 una nuova struttura di directory con app code in il 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 separazione migliore 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 per lo Sviluppo Mobile
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"
}
}
Testa la generazione statica:
bun run generate
Devi vedere un .output/public directory con i tuoi file statici.
Passo 4: Installa Capacitor 8
Installa i pacchetti di base Capacitor:
bun add @capacitor/core
bun add -D @capacitor/cli
Installa i plugin essenziali che la maggior parte degli 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 dello schermo di benvenuto nativo
- @capacitor/status-bar — Stilizzazione della barra di stato del dispositivo
- @capacitor/preferences — Archiviazione chiave-valore (come localStorage ma nativa)
Step 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 visualizzato dell'appcom.example.mymobileappcon 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;
Step 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
Ciò crea ios e i directory contenenti i progetti nativi. android Step 7: Costruisci e Esegui
Costruisci il tuo progetto e sincronizza con le piattaforme native:
Apre in iOS Simulator:
bun run mobile
O Android Emulator:
bun run mobile:ios
In Xcode (iOS):
bun run mobile:android
Seleziona un simulatore dal menu a discesa dei dispositivi
- Clicca sul pulsante Play o premi
- In Android Studio:
Cmd + R
Aspetta che Gradle finisca di sincronizzare
- Seleziona un emulatore dal menu a discesa dei dispositivi
- In Xcode (iOS): Seleziona un simulatore dal menu a discesa dei dispositivi. Clicca sul pulsante Play o premi Command + R. In Android Studio: Aspetta che Gradle finisca di sincronizzare. Seleziona un emulatore dal menu a discesa dei dispositivi.
- Premi il pulsante Esegui o premi
Shift + F10
Passo 8: Configura il Live Reload
Per una maggiore velocità di sviluppo, abilita il live reload in modo che le modifiche appariscano istantaneamente sul tuo dispositivo.
- Cerca l'indirizzo IP locale:
# macOS
ipconfig getifaddr en0
# Windows
ipconfig
- Crea una configurazione di sviluppo locale 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 su nativo:
bun run dev &
NODE_ENV=development bunx cap copy
- Riavvia in Xcode/Android Studio
Ora le modifiche al tuo Nuxt code si ricaricheranno automaticamente sul dispositivo.
Passo 9: Crea la Prima Schermata Mobili
Creiamo una schermata home adatta 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>
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
└── ...
Passaggi Successivi
Ora hai un'app mobile Nuxt funzionante. Ecco cosa fare di seguito:
Impostazione Fondamentale
- Icone dell'App: Sostituisci le icone predefinite in
ios/App/App/Assets.xcassetseandroid/app/src/main/res - Schermo di Avvio: Personalizza in progetti nativi o utilizza
@capacitor/splash-screenconfig - Collegamenti Profondi: 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-firebase-messaging 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 aspetto mobile nativo:
- @capgo/capacitor-native-navigation — Liquid Glass barra delle schede e navbar nativa
- @capgo/capacitor-transitions — transizioni di pagina con un aspetto 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 Utilizza @capgo/capacitor-native-navigation, Utilizza @capgo/capacitor-transizioni, e il repo tailwind-capacitor per la configurazione specifica di Nuxt.
Risolvere i Problemi di Layout iOS (Viewport, Area di Sicurezza e Scoramento Orizzontale)
Se il contenuto sembra essere tagliato, spostato o scorrevole orizzontalmente su iOS, aggiungere ulteriori overflow-x: hidden o modificare il tag viewport da solo non risolve di solito il problema. Esegui questi controlli in ordine.
Assicurati che il meta tag viewport sia applicato correttamente
In nuxt.config.tsimposta la vista portata app.head:
export default defineNuxtConfig({
app: {
head: {
meta: [
{
name: 'viewport',
content: 'width=device-width, initial-scale=1, viewport-fit=cover',
},
],
},
},
});
gestisci l'area sicura di iOS da un unico wrapper radice
Creare un unico contenitore dell'applicazione e applicare il padding dell'area sicura lì — non nei 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);
}
Avvolgi tutta il contenuto della pagina all'interno di .app-shellDuplicare il padding dell'area sicura nei titoli, nei modali e nei wrapper di layout spesso fa sembrare l'interfaccia utente tagliata o troppo grande.
Con @capgo/tailwind-capacitor, puoi esprimere lo stesso padding con utilità come pt-safe pb-safe px-safe su quel singolo contenitore.
Imposta Capacitor iOS contentInset a never primo
In capacitor.config.tspreferisci un inset nativo disabilitato e lascia che CSS (o la navigazione nativa) gestisca l'area sicura: contentInsetMode: 'css'Mescolare l'insetto di contenuto automatico di __CAPGO_KEEP_0__ con il padding CSS è una causa comune di doppia spaziatura.
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-*) L'elemento solito colpevole è un elemento che utilizza
, Tailwind
, una larghezza in pixel fissata o molto grande: 100vwIn Safari Web Inspector, esegui: w-screenCon Tailwind, sostituisci min-width.
con
[...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,
}));
With Tailwind, replace w-screen with w-full When possibile, molti problemi di sovrapposizione orizzontale derivano da 100vw / w-screen, duplicati padding di area sicura, o da un contenitore di larghezza fissata — non dal tag meta del viewport stesso.
Aggiornamenti Over-the-Air
Configura Capgo per inviare aggiornamenti senza dover riconfermare l'app sullo store:
bunx @capgo/cli init
Risoluzione dei problemi
Errore di compilazione con ‘Cannot find module’
Esegui bun install e riprova.
iOS: ‘Non trovato identità di firma’ Apre Xcode, va 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 vengono visualizzate sul dispositivo
Assicurati di aver eseguito bun run mobile dopo aver apportato modifiche. Per il live reload, verificare che l'indirizzo IP sia corretto e 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
- Documentazione Nuxt 4
- Capgo - Aggiornamenti in tempo reale
- @capgo/@capacitor-navigazione nativa
- @capgo/@capacitor-transizioni
- @capgo/tailwind-capacitor
Siete pronti a distribuire la vostra app? Imparate come Capgo possa aiutarvi a consegnare gli aggiornamenti più velocemente — iscrivetevi ad un account gratuito oggi.
Continuate a lavorare da Costruire un'app mobile Nuxt da zero con Capacitor 8
Se state utilizzando Costruire un'app mobile Nuxt da zero con Capacitor 8 per pianificare l'automazione CI/CD, connettetelo 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 flusso di lavoro del prodotto in Capgo Integrazioni, Integrazione CI/CD per il dettaglio di implementazione in Integrazione CI/CD, e GitHub Integrazione delle azioni per il dettaglio di implementazione in GitHub Integrazione delle azioni.