Introduzione
Vuoi costruire un'app mobile con Next.js da zero? Questa guida ti guida attraverso la creazione di un nuovo progetto Next.js 15 configurato per la mobilità fin dal primo giorno, poi pacchettizzandolo come app native iOS e Android utilizzando Capacitor 8.
Alla fine di questo tutorial, avrai un'app mobile funzionante che esegue sui simulatori e che puoi continuare a sviluppare e pubblicare infine sul App Store e Google Play.
Tempo richiesto: ~30 minuti
Ciò che realizzerai:
- Un nuovo progetto Next.js 15 con App Router
- Configurazione di esportazione statica per dispositivi mobili
- Capacitor 8 con plugin essenziali
- Applicazioni native iOS e Android
- Setup di sviluppo con live reload
Hai già un'app Next.js? Ecco Converti la tua app Next.js in mobile altrimenti.
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 Next.js
Inizia creando un progetto Next.js 15 fresco:
bunx create-next-app@latest my-mobile-app
Quando ti viene chiesto, seleziona queste opzioni:
- TipoScript: Sì (consigliato)
- ESLint: Sì
- Tailwind CSS: Sì (consigliato per lo stiling mobile)
src/directory: Sì- App Router: Sì (consigliato)
- Alias di importazione: Predefinito (
@/*)
Naviga al tuo progetto:
cd my-mobile-app
Passo 2: Configura Next.js per l'esportazione statica
Capacitor richiede file HTML/JS/CSS statici. Configura Next.js per l'esportazione statica aggiornando 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;
Perché questi impostazioni?
output: 'export'— Genera HTML statico invece di richiedere un server Node.jsimages: { unoptimized: true }— Disabilita l'ottimizzazione delle immagini di Next.js (richiede un server)trailingSlash: true— Assicura la routing corretta nella WebView nativa
Passo 3: Aggiungi script mobili
Aggiorna il tuo package.json con script di sviluppo 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"
}
}
Testa la build:
bun run build
Devi vedere un out Direttorio con i tuoi file statici.
Passo 4: Installa Capacitor 8
Installare i pacchetti di base di Capacitor:
bun add @capacitor/core
bun add -D @capacitor/cli
Installare 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 dello schermo di benvenuto nativo
- @capacitor/status-bar — Personalizza la barra dello stato del dispositivo
- @capacitor/preferenze — Archiviazione chiave-valore (come localStorage ma nativa)
Passo 5: Inizializza Capacitor
Inizia Capacitor con i dettagli del tuo progetto:
bunx cap init "My Mobile App" com.example.mymobileapp --web-dir out
Sostituisci:
"My Mobile App"con il nome della tua appcom.example.mymobileappcon l'ID dell'app (notazione di dominio inverso)
Ciò crea capacitor.config.tsAggiornalo con la configurazione del 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;
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 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
O 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:
- Aspettare che Gradle finisca di sincronizzare
- Selezionare un emulatore dal menu a discesa dei dispositivi
- Cliccare sul pulsante Esegui o premere
Shift + F10
Passo 8: Configura Live Reload
Per un sviluppo più veloce, abilita il live reload in modo che le modifiche appariscano istantaneamente sul tuo dispositivo.
- Trova l'indirizzo IP locale:
# macOS
ipconfig getifaddr en0
# Windows
ipconfig
- Crea una configurazione di sviluppo Capacitor. Aggiungi a
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;
- 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 Next.js code si ricaricheranno automaticamente sul dispositivo.
Passo 9: Crea la Prima Schermata Mobili
Creiamo una semplice schermata di benvenuto per dispositivi mobili. Aggiorna 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>
);
}
Passo 10: Aggiungi gestione area sicura
Gli dispositivi mobili hanno notch, indicatori di home e barre di stato. Aggiungi la gestione dell'area sicura con Tailwind.
Aggiorna 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;
}
Struttura del progetto
Il tuo progetto dovrebbe ora avere questo aspetto:
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
└── ...
Passaggi successivi
Ora hai un'app mobile Next.js funzionante. Ecco cosa fare successivamente:
Configurazione essenziale
- Icone dell'app: Sostituisci le icone predefinite in
ios/App/App/Assets.xcassetseandroid/app/src/main/res - Schermo di avvio: Personalizza nei progetti nativi o utilizza
@capacitor/splash-screenconfig - Deep Links: Configura i schemi di URL per la tua app
Aggiungi più funzionalità
- Camera:
bun add @capacitor/camera - Geolocalizzazione:
bun add @capacitor/geolocation - Notifiche Push:
bun add @capacitor/push-notifications - Sistema di file:
bun add @capacitor/filesystem
Interfaccia utente nativa e transizioni
Usa i plugin Capgo al posto di Konsta UI per un sentore di mobile nativo:
- @capgo/capacitor-navigazione-nativa — Barra di navigazione Liquida Glass 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 Utilizza @capgo/capacitor-native-navigation, Utilizza @capgo/capacitor-transizioni, e il repo tailwind-capacitor per la configurazione specifica di Next.js.
Risolvere i problemi di layout di iOS (Viewport, Area sicura e sovrapposizione orizzontale)
If il contenuto sembra essere tagliato, spostato o scorrevole orizzontalmente su iOS, aggiungere altro overflow-x: hidden o modificare il tag viewport da solo non risolve di solito il problema. Lavora attraverso questi controlli in ordine.
Assicurati che il tag meta viewport sia applicato correttamente
Router dell'applicazione (app/): esporta viewport da app/layout.tsx:
import type { Viewport } from 'next';
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
};
Router delle pagine (pages/): metti il tag meta viewport in pages/_app.tsxnon _document.tsx.
Gestisci l'area sicura di iOS da un solo wrapper radice
Creati un unico contenitore dell'applicazione e applica l'aggiustamento dell'area sicura lì — non in componenti nidificati multipli:
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);
}
Avvolgi tutto il contenuto della pagina all'interno .app-shell. La sovrapposizione di padding di sicurezza duplicato nelle intestazioni, nei modali e nei wrapper di layout può rendere l'interfaccia utente appiattita o troppo grande.
Con @capgo/tailwind-capacitor, puoi esprimere lo stesso padding con utility come pt-safe pb-safe px-safe su quella singola shell.
Imposta Capacitor iOS contentInset a never primo
In capacitor.config.ts, preferisci l'inserimento nativo disabilitato e lascia che CSS (o la navigazione nativa ' contentInsetMode: 'css'') gestisca l'area sicura:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'out',
ios: {
contentInset: 'never',
},
};
La miscela di Capacitor’s automatico contenuto insetto con CSS env(safe-area-inset-*) la spaziatura è una causa comune di doppia spaziatura.
Trova l'elemento che sta effettivamente sovrapponendo
Il solito colpevole è un elemento che utilizza 100vw, Tailwind w-screen, una larghezza in pixel fisse, o un 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, padding di area sicura duplicato, o un contenitore di larghezza fissa — non dal tag meta viewport stesso.
Aggiornamenti Over-the-Air
Configura Capgo per inviare aggiornamenti senza riconciliazione dell'app store:
bunx @capgo/cli init
Risoluzione dei problemi
L'edizione fallisce con “Non è stato trovato modulo”
Esegui bun install e riprova.
iOS: “Identità di firma non trovata” Apri Xcode, vai a Signing & Capabilità, e seleziona il tuo team di sviluppo.
Android: “SDK” non trovato in locale
Crea android/local.properties con sdk.dir=/path/to/android/sdk
Le modifiche non si visualizzano sul dispositivo
Assicurati di aver eseguito il comando bun run mobile dopo aver effettuato modifiche. Per il live reload, verificare l'indirizzo IP è corretto e il server di sviluppo è in esecuzione.
Risorse
- Capacitor 8 Documentazione
- Next.js 15 Documentazione
- Capgo - Aggiornamenti in tempo reale
- @capgo/capacitor-navigazione nativa
- @capgo/capacitor-transizioni
- @capgo/tailwind-capacitor
Pronto a distribuire la tua app? Scopri come Capgo può aiutarti a consegnare aggiornamenti più velocemente — iscrivi il tuo account gratuito oggi.
Continua da Costruisci un'app mobile Next.js da zero con Capacitor 8
Se stai utilizzando Costruisci un'app mobile Next.js 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 flusso di lavoro del prodotto in Capgo Integrazioni, Integrazione CI/CD per il dettaglio di implementazione in Integrazione CI/CD, e Azioni di integrazione di GitHub per i dettagli di implementazione in Azioni di integrazione di GitHub