Saltare al contenuto principale
Guida pratica

Crea un'app mobile Next.js da zero con Capacitor 8

Passo dopo passo, creiamo un nuovo progetto Next.js 15 e lo trasformiamo in app mobili native per iOS e Android utilizzando Capacitor 8. Perfetto per iniziare con lo sviluppo mobile-first.

Martin Donadieu

Martin Donadieu

Content Marketer

Crea un'app mobile Next.js da zero con Capacitor 8

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 dall'inizio, poi lo pacchettiamo come app native per iOS e Android utilizzando Capacitor 8.

Con la fine di questa guida, avrai un'app mobile funzionante che esegue su simulatori e puoi continuare a svilupparla e pubblicarla infine su App Store e Google Play.

Tempo richiesto: ~30 minuti

Cosa costruirai:

  • 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
  • Impostazione di sviluppo con reload live

Hai già un'app Next.js? Consulta invece Converti la tua app Next.js in mobile prerequisiti

Requisiti

Assicurati di avere installati:

  • Node.js 18+ (controlla con node --version)
  • Bun gestore di 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:

  • TypeScript: Sì (consigliato)
  • ESLint:
  • Tailwind CSS: Sì (consigliato per la stilizzazione mobile)
  • src/ directory:
  • 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.js
  • images: { 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 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

Dovresti vedere un out directory 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 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 — Stile la barra di stato del dispositivo
  • @capacitor/preference — 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 out

Sostituisci:

  • "My Mobile App" con il nome visualizzato dell'applicazione
  • com.example.mymobileapp con l'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: '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 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):

  1. Seleziona un simulatore dalla dropdown dispositivi
  2. Clicca sul pulsante Play o premi Cmd + R

In Android Studio:

  1. Attendere che Gradle completi la sincronizzazione
  2. Scegli un emulatore dal menu a discesa dei dispositivi
  3. Clicca sul pulsante Esegui o premi Shift + F10

Passo 8: Configura Live Reload

Per un sviluppo più veloce, abilita live reload in modo che le modifiche appariscano istantaneamente sul tuo dispositivo.

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

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

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

Passo 9: Crea la Prima Schermata Mobile

Creiamo una semplice schermata di benvenuto mobile-friendly. 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>
  );
}

Step 10: Aggiungi Gestione Area Sicura

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

Page/Area: Capgo Builder / prodotto di costruzione nativa cloud. Ruolo: Etichetta di navigazione breve o elemento UI. Messaggio chiave `native_build_builder_credit_next` (Crediti del costruttore di costruzione nativa).

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

  • Configurazione Essenziale Iconografie dell'App: ios/App/App/Assets.xcassets Sostituisci gli iconi predefiniti in android/app/src/main/res
  • E il messaggio chiave `and` (E). Page/Area: Sito web di marketing Capgo. Ruolo: Etichetta di navigazione breve o elemento UI. Visualizzato in: pagina trust.astro. Messaggio chiave `and` (E). Personalizza in progetti nativi o utilizza @capacitor/splash-screen config
  • Deep Links: Configura schemi di URL per la tua app

Aggiungi Funzionalità

  • Camera: bun add @capacitor/camera
  • Geolocalizzazione: bun add @capacitor/geolocation
  • Push Notifications: bun add @capacitor/push-notifications
  • Sistema di File: bun add @capacitor/filesystem

Interfaccia utente nativa e transizioni

Utilizza plugin Capgo al posto di Konsta UI per un aspetto mobile 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 Utilizzare @capgo/capacitor-navigazione nativa, Utilizzare @capgo/capacitor-transizioni, e il repo tailwind-capacitor per la configurazione specifica di Next.js.

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

Se il contenuto sembra essere tagliato, spostato o scorrevole orizzontalmente su iOS, aggiungere più overflow-x: hidden o regolare la riga di taglio di viewport da solo non risolve di solito il problema. Lavora attraverso questi controlli in ordine.

Assicurati che la meta tag di viewport sia applicata correttamente

App Router (app/): esporta viewport da app/layout.tsx:

import type { Viewport } from 'next';

export const viewport: Viewport = {
  width: 'device-width',
  initialScale: 1,
  viewportFit: 'cover',
};

Pages Router (pages/): metti la meta tag di viewport in pages/_app.tsxnon _document.tsx.

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

Crea un unico guscio di applicazione e applica il padding 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. Aggiungi padding di area sicura duplicato nelle intestazioni, nei modali e nei wrapper di layout, il che spesso fa sì che l'interfaccia utente sembri tagliata o troppo grande.

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

Imposta Capacitor iOS contentInset su never primo

In capacitor.config.ts, preferisci l'inserzione nativa disabilitata 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',
  },
};

Mischia Capacitor's automatico contenuto inset con CSS env(safe-area-inset-*) La spaziatura è una causa comune di doppia spaziatura.

Trova l'elemento che sta effettivamente sovrapponendosi.

L'elemento colpevole è spesso un elemento che utilizza 100vw, Tailwind w-screen, una larghezza in pixel fissata, o un contenitore di grandi dimensioni 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 fissata — non dal tag meta viewport stesso.

Aggiornamenti Over-the-Air

Configura Capgo per aggiornare senza riconferma dell'app store:

bunx @capgo/cli init

Troubleshooting

Costruzione fallita con “Non è possibile trovare modulo” Esegui bun install e riprova.

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

Android: “SDK” non trovato 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 l'indirizzo IP è corretto e il server di sviluppo è in esecuzione.

Risorse

Pronto a spedire la tua app? Scopri come Capgo può aiutarti a consegnare aggiornamenti più velocemente — iscriversi a un account gratuito oggi.

Continua con Build a Next.js Mobile App from Scratch con Capacitor 8

Se stai utilizzando Build a Next.js Mobile App from Scratch 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 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 del layer web è attivo, invia la correzione attraverso Capgo invece di aspettare giorni per l'approvazione della store. Gli utenti ricevono l'aggiornamento in background mentre le modifiche native rimangono nel normale percorso di revisione.

Supporto umano da Martin

Avvia Ora

Ultimi articoli dal nostro Blog

Capgo vi offre le migliori informazioni che avete bisogno per creare un'app mobile davvero professionale.