Introduzione
Vuoi creare 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, quindi pacchettizzato come app native iOS e Android utilizzando Capacitor 8.
Al termine di questo tutorial, avrai un'app mobile funzionante che esegue su simulatori e che potrai continuare a sviluppare e pubblicare infine sullo Store App e su Google Play.
Tempo richiesto: ~30 minuti
Cosa costruirai:
- Un nuovo progetto Next.js 15 con App Router
- Configurazione di esportazione statica per la mobilità
- Capacitor 8 with essential plugins
- App 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 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 Next.js
Inizia creando un progetto Next.js 15 fresco:
bunx create-next-app@latest my-mobile-app
Quando viene richiesto, seleziona queste opzioni:
- TypeScript: Sì (consigliato)
- ESLint: Sì
- Tailwind CSS: Sì (consigliato per la stilizzazione mobile)
src/directory: Sì- Router dell'applicazione: Sì (consigliato)
- Alias di importazione: Predefinito (
@/*)
Vai 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 una routing corretta nella WebView nativa
Passo 3: Aggiungi script mobili
Aggiorna il tuo package.json con gli 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 costruzione:
bun run build
Devi vedere un out directory con i tuoi file statici.
Passo 4: Installa Capacitor 8
Installa i pacchetti di base 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
Di cosa fanno questi plugin:
- @capacitor/app – Eventi di ciclo di vita dell'applicazione (in primo piano/ in background, collegamenti profondi)
- @capacitor/keyboard — Controllo del comportamento della tastiera
- @capacitor/schermo di benvenuto — Controllo dello schermo di benvenuto nativo
- @capacitor/barra dello stato — Stilizzazione della barra dello stato del dispositivo
- @capacitor/preferenze — Archiviazione dei valori chiave (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 out
Sostituisci:
"My Mobile App"con il nome visualizzato dell'appcom.example.mymobileappcon l'ID dell'app (notazione di dominio inverso)
Questo 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 directory che contengono 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):
- Scegli un simulatore dalla lista dispositivi
- Clicca sul pulsante di riproduzione o premi
Cmd + R
In Android Studio:
- Aspetta che Gradle finisca di sincronizzare
- Scegli un emulatore dalla lista dispositivi
- Clicca sul pulsante di esecuzione o premi
Shift + F10
Passo 8: Configura Live Reload
Per un'esperienza di sviluppo più veloce, abilita live reload per visualizzare i cambiamenti istantaneamente sul tuo dispositivo.
- Cerca l'indirizzo IP locale:
# macOS
ipconfig getifaddr en0
# Windows
ipconfig
- Crea una configurazione di sviluppo locale 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;
- Inizia 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 Next.js code si ricaricheranno automaticamente sul dispositivo.
Passo 9: Crea la Prima Schermata Mobile
Creiamo una semplice schermata di benvenuto adatta a 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
I 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
La tua struttura del progetto dovrebbe ora assomigliare a questo:
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
└── ...
Passi Successivi
Ora hai un'app mobile Next.js funzionante. Ecco cosa fare di seguito:
Configurazione Essenziale
- Icône dell'applicazione: 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 più funzionalità
- Camera:
bun add @capacitor/camera - Posizionamento geografico:
bun add @capacitor/geolocation - Notifiche push:
bun add @capacitor/push-notifications - Sistema di file:
bun add @capacitor/filesystem
Interfaccia nativa e transizioni
Utilizza i plugin Capgo al posto di Konsta UI per un'esperienza mobile nativa:
- @capgo/capacitor-navigazione-nativa — barra dei pulsanti Liquido 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-navigazione-nativa, Utilizza @capgo/capacitor-transizioni, e il repo tailwind-capacitor per la configurazione specifica di Next.js.
Risolvere i Problemi di Layout iOS (Viewport, Area di Sicurezza e Sovraffollamento Orizzontale)
Se il contenuto sembra essere tagliato, spostato o scorrevole orizzontalmente su iOS, aggiungere o modificare il tag viewport da solo non risolve di solito il problema. Esegui questi controlli in ordine. overflow-x: hidden Assicurati che il tag meta viewport sia applicato correttamente
App Router
): esporta (app/da viewport Pages Router app/layout.tsx:
import type { Viewport } from 'next';
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
};
): metti il tag meta viewport in (pages/protectedTokens pages/_app.tsxe non _document.tsx.
Configura l'area di sicurezza iOS da un wrapper radice solo
Creare un unico contenitore dell'applicazione e applicare il padding dell'area di sicurezza lì — non nei 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);
}
Avvolgere tutto il contenuto della pagina all'interno .app-shell di. Il padding dell'area di sicurezza duplicato 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 su never context: Pagina/area: Pagina di prodotti in tempo reale. Ruolo: Etichetta di navigazione breve o elemento di navigazione. Chiave di messaggio `live_update_dynamic_label_to` (Etichetta dinamica di aggiornamento in tempo reale per).
In capacitor.config.ts, prefer native inset disabled and let CSS (o la navigazione nativa) contentInsetMode: 'css') own the safe area:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'out',
ios: {
contentInset: 'never',
},
};
Mischia Capacitor’s automatic content inset con CSS env(safe-area-inset-*) è una causa comune di doppia spaziatura.
Trova l'elemento che sta veramente sovrascrivendo
Il solito colpevole è un elemento che utilizza 100vw, Tailwind w-screen, una larghezza in pixel fissata, o una larghezza 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-screenpadding di area sicura duplicato, o da un contenitore di larghezza fissata — non dal tag meta 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
Costruisci fallisce con “Non è stato trovato modulo”
Esegui bun install e riprova.
iOS: “Non è stato trovato identità di firma” Apre Xcode, vai a Signing & Capabilità, 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, verificare che l'indirizzo IP sia corretto e che il server di sviluppo sia in esecuzione.
Risorse
- Capacitor 8 Documentazione
- Documentazione Next.js 15
- Capgo - Aggiornamenti in tempo reale
- @capgo/capacitor-navigazione nativa
- @capgo/capacitor-transizioni
- @capgo/tailwind-capacitor
Siete pronti a spedire il vostro app? Imparate come Capgo può aiutarvi a consegnare aggiornamenti più velocemente — iscrivetevi a un account gratuito oggi.
Continuate da Costruire un'app mobile Next.js da zero con Capacitor 8
Se state utilizzando Costruire un'app mobile Next.js 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 Build nativi per il flusso di lavoro del prodotto in Capgo Build nativi, Capgo Integrazioni per il flusso di lavoro del prodotto in Capgo Integrazioni Integrazione CI/CD per i dettagli di implementazione in Integrazione CI/CD, e GitHub Azioni Integrazione per i dettagli di implementazione in GitHub Azioni Integrazione.