Saltare al contenuto principale
Tutorial

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

Guida passo dopo passo per creare un nuovo progetto Next.js 15 e trasformarlo 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 dall'alto in basso? Questa guida ti guida attraverso la creazione di un nuovo progetto Next.js 15 configurato per la mobilità fin dal primo giorno, quindi lo imballa 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 eventualmente sul App Store e Google Play.

Tempo richiesto: ~30 minuti

Cosa costruisci:

  • Un nuovo progetto Next.js 15 con App Router
  • Configurazione di esportazione statica per la mobilità
  • Capacitor 8 con plugin essenziali
  • App native iOS e Android
  • Setup di sviluppo con live reload

Già hai un'app Next.js? Ecco cosa fare Converti la tua app Next.js in mobile invece.

Requisiti

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 nuovo progetto Next.js 15:

bunx create-next-app@latest my-mobile-app

Quando viene richiesto, seleziona queste opzioni:

  • TypeScript: Sì (consigliato)
  • ESLint:
  • Tailwind CSS: Sì (consigliato per lo styling mobile)
  • src/ directory:
  • Router dell'applicazione: Sì (consigliato)
  • Importa alias: Predefinito (@/*)

Naviga al tuo progetto:

cd my-mobile-app

Passaggio 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 la routing corretta nella WebView nativa

Passaggio 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"
  }
}

Sviluppa l'installazione:

bun run build

Devi vedere un out directory con i tuoi file statici.

Passo 4: Installare 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'applicazione (in primo piano/ in background, collegamenti profondi)
  • @capacitor/keyboard — Control il comportamento della tastiera
  • @capacitor/splash-screen — Controllo dello schermo di benvenuto nativo
  • @capacitor/status-bar — Personalizza la barra dello stato del dispositivo
  • @capacitor/preferences — Archiviazione dei valori chiave (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 visualizzato dell'app
  • com.example.mymobileapp con l'ID dell'app (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 native:

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. Scegli un simulatore dalla lista dispositivi
  2. Clicca sul pulsante di riproduzione o premi Cmd + R

In Android Studio:

  1. Aspetta che Gradle si sincronizzi
  2. Scegli un emulatore dalla lista dispositivi
  3. Clicca sul pulsante di esecuzione o premi Shift + F10

Passo 8: Configura Live Reload

Per una maggiore velocità di sviluppo, abilita live reload per visualizzare i cambiamenti 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 nativa:
bun run dev &
NODE_ENV=development bunx cap copy
  1. Riavvia in Xcode/Android Studio

Ora le modifiche al tuo Next.js code verranno ricaricate in tempo reale sul dispositivo.

Passo 9: Crea la Prima Schermata Mobile

Crea 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

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

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 di seguito:

Configurazione Fondamentale

  • Icone dell'app: Sostituisci gli iconi predefiniti in ios/App/App/Assets.xcassets e android/app/src/main/res
  • Schermo di benvenuto: Personalizza in progetti nativi o utilizza @capacitor/splash-screen config
  • Collegamenti profondi: Configura i schemi di URL per il tuo app

Aggiungi più funzionalità

  • Camera: bun add @capacitor/camera
  • Geolocalizzazione: bun add @capacitor/geolocation
  • Notifiche push: bun add @capacitor/push-notifications
  • File System: bun add @capacitor/filesystem

Interfaccia nativa e transizioni

Usa i plugin Capgo al posto di Konsta UI per un'esperienza mobile nativa:

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-transizioniEcco il repo tailwind-__CAPGO_KEEP_0__ per la configurazione specifica di Next.js. tailwind-capacitor repo Se il contenuto sembra essere tagliato, spostato o scorrevole orizzontalmente su iOS, aggiungere o modificare il tag viewport da solo non risolve il problema. Esegui questi controlli in ordine.

Assicurati che il meta tag viewport sia applicato correttamente.

Router di App overflow-x: hidden : esporta

da

: Router delle Pagine (app/: inserisci il meta tag viewport viewport tailwind-__CAPGO_KEEP_0__ repo per la configurazione specifica di Next.js. app/layout.tsx:

import type { Viewport } from 'next';

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

Per risolvere i problemi di layout su iOS (Viewport, Area di sicurezza e sovrapposizione orizzontale), (pages/Se il contenuto sembra essere tagliato, spostato o scorrevole orizzontalmente su iOS, aggiungere o modificare il tag viewport da solo non risolve il problema. Esegui questi controlli in ordine. Assicurati che il meta tag viewport sia applicato correttamente. App Router,): esporta da Pages Router,): inserisci il meta tag viewport pages/_app.tsxNon gestire l'area sicura di iOS da un unico wrapper radice _document.tsx.

Creare un unico guscio di app e applicare il padding dell'area sicura lì — non nei componenti nidificati multipli:

Avvolgere tutta il contenuto della pagina all'interno

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);
}

La duplicazione del padding dell'area sicura nei titoli, nei modali e nei wrapper di layout spesso fa sembrare l'interfaccia utente tagliata o troppo grande. .app-shellCon

@__CAPGO_KEEP_0__/tailwind-__CAPGO_KEEP_1__ @capgo/tailwind-capacitorsu quel guscio unico. pt-safe pb-safe px-safe Imposta __CAPGO_KEEP_0__ iOS

Set Capacitor iOS contentInset primo never Non

In capacitor.config.ts, prefer native inset disabled e lascia che CSS (o la navigazione nativa) gestisca l'area sicura: contentInsetMode: 'css'Mixing __CAPGO_KEEP_0__’s automatic content inset con CSS

const config: CapacitorConfig = {
  appId: 'com.example.myapp',
  appName: 'my-app',
  webDir: 'out',
  ios: {
    contentInset: 'never',
  },
};

Mixing Capacitor’s automatic content inset with CSS env(safe-area-inset-*) Trova l'elemento che sta veramente sovrapponendosi

L'elemento colpevole è spesso un elemento che utilizza

, Tailwind 100vw, una larghezza in pixel fissata, o un valore molto w-screenIn Safari Web Inspector, esegui: min-width.

Con Tailwind, sostituisci

[...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 w-screen with w-full quando possibile. Molti problemi di sovrapposizione orizzontale derivano da 100vw / w-screen, sovrapposizione di padding di area sicura duplicata, o da un contenitore di larghezza fissata — non dal tag meta viewport stesso.

Aggiornamenti Over-the-Air

Configura Capgo per inviare aggiornamenti senza dover ricondividere 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” Apri Xcode, vai a Signing &amp; Capabilità, e seleziona il tuo team di sviluppo.

Android: “SDK location not found” Crea android/local.properties con sdk.dir=/path/to/android/sdk

I cambiamenti non vengono visualizzati sul dispositivo Assicurati di aver eseguito bun run mobile dopo aver fatto le modifiche. Per il live reload, verificare l'indirizzo IP è corretto e il server di sviluppo è in esecuzione.

Risorse

Pronto a spedire la tua app? Impara come Capgo può aiutarti a consegnare aggiornamenti più velocemente — iscriversi a un 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, Integrazioni Capgo per il workflow del prodotto in Integrazioni Capgo Integrazione CI/CD per il dettaglio di implementazione in Integrazione CI/CD Integrazione GitHub Actions per il dettaglio di implementazione in Integrazione GitHub Actions.

Aggiornamenti in tempo reale per le app Capacitor

Quando un bug del layer web è attivo, invia la correzione attraverso Capgo invece di attendere giorni per l'approvazione della store. Gli utenti ricevono l'aggiornamento in background mentre le modifiche native rimangono nel normale percorso di revisione.

Inizia subito

Ultimi articoli dal nostro Blog

Capgo ti offre le migliori informazioni che ti servono per creare un'app mobile veramente professionale.