Zum Hauptinhalt springen
Tutorials

Next.js Mobile App von Grund auf bauen mit Capacitor 8

Schritt-für-Schritt-Anleitung: Erstelle ein neues Next.js 15 Projekt und verwandle es mit Capacitor in native iOS- und Android-Apps. Ideal für den Neustart mit Mobile-First-Development.

Mit Capacitor eine Next.js Mobile App von Grund auf bauen 8 Capgo

Einführung

Möchtest du eine mobile App mit Next.js von Grund auf neu entwickeln? Dieser Guide zeigt dir, wie du ein Next.js 15 Projekt direkt für Mobile konfigurierst und es anschließend als native iOS- und Android-Apps verpackst mit Capacitor 8.

Am Ende dieses Tutorials hast du eine funktionierende mobile App auf Simulatoren laufen, die du weiterentwickeln und schließlich im App Store und Google Play veröffentlichen kannst.

Zeitaufwand: ~30 Minuten

Das baust du:

  • Ein neues Next.js-15-Projekt mit App Router
  • Static-Export-Konfiguration für Mobile
  • Capacitor 8 mit essenziellen Plugins
  • Native iOS- und Android-Apps
  • Live-Reload-Setup für die Entwicklung

Schon eine Next.js App? Dann schau dir das an: Konvertiere deine Next.js App in eine Mobile App stattdessen.

Voraussetzungen

Stelle sicher, dass Folgendes installiert ist:

  • Node.js 18+ (prüfen mit node --version)
  • Bun Package Manager (curl -fsSL https://bun.sh/install | bash)
  • Xcode (nur macOS, für iOS-Entwicklung)
  • Android Studio (für Android-Entwicklung)

Schritt 1: Neues Next.js-Projekt erstellen

Erstelle zuerst ein neues Next.js 15 Projekt:

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

Wähle bei den Prompts diese Optionen:

  • TypeScript: Ja (empfohlen)
  • ESLint: Ja
  • Tailwind CSS: Ja (empfohlen für mobiles Styling)
  • src/ Verzeichnis: Ja
  • App Router: Ja (empfohlen)
  • Import-Alias: Standard (@/*)

Navigiere zu deinem Projekt:

cd my-mobile-app

Schritt 2: Next.js für den Static Export konfigurieren

Capacitor benötigt statische HTML/JS/CSS-Dateien. Konfiguriere Next.js für den Static Export, indem du 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;

Warum diese Einstellungen?

  • output: 'export' — Erzeugt statisches HTML und braucht keinen Node.js-Server
  • images: { unoptimized: true } — Deaktiviert die Next.js Image Optimization (benötigt einen Server)
  • trailingSlash: true — Sorgt für korrektes Routing im nativen WebView

Schritt 3: Mobile Scripts hinzufügen

Aktualisiere dein package.json mit Scripts für die mobile Entwicklung:

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

Teste den Build:

bun run build

Du solltest einen out Verzeichnis mit deinen statischen Dateien.

Schritt 4: Capacitor 8 installieren

Installiere die Capacitor Core-Packages:

bun add @capacitor/core
bun add -D @capacitor/cli

Installiere die wichtigsten Plugins für mobile Apps:

bun add @capacitor/app @capacitor/keyboard @capacitor/splash-screen @capacitor/status-bar @capacitor/preferences

Was diese Plugins machen:

  • @capacitor/app — App-Lifecycle-Events (Foreground/Background, Deep Links)
  • @capacitor/keyboard — Tastaturverhalten steuern
  • @capacitor/splash-screen — Native Splash-Screen steuern
  • @capacitor/status-bar — Styling der Statusleiste
  • @capacitor/preferences — Key-Value-Storage (wie localStorage, aber nativ)

Schritt 5: Capacitor initialisieren

Initialisiere Capacitor mit deinen Projektdaten:

bunx cap init "My Mobile App" com.example.mymobileapp --web-dir out

Ersetze:

  • "My Mobile App" durch den Anzeigenamen deiner App
  • com.example.mymobileapp durch deine App-ID (Reverse-Domain-Notation)

Dadurch entstehen capacitor.config.ts. Aktualisiere sie mit der Plugin-Konfiguration:

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;

Schritt 6: Native Plattformen hinzufügen

Installiere die Plattform-Packages:

bun add @capacitor/ios @capacitor/android

Native Projekte generieren:

bunx cap add ios
bunx cap add android

Dadurch entstehen ios und android Verzeichnisse mit den nativen Projekten.

Schritt 7: Build und Run

Baue dein Projekt und synchronisiere es mit den nativen Plattformen:

bun run mobile

Im iOS Simulator öffnen:

bun run mobile:ios

Oder Android Emulator:

bun run mobile:android

In Xcode (iOS):

  1. Wähle einen Simulator aus dem Geräte-Dropdown
  2. Klicke auf den Play-Button oder drücke Cmd + R

In Android Studio:

  1. Warten, bis Gradle das Syncing beendet hat
  2. Wähle einen Emulator aus dem Device-Dropdown
  3. Klicke auf Run oder drücke Shift + F10

Schritt 8: Live Reload einrichten

Aktiviere Live Reload für schnelleres Entwickeln, damit Änderungen sofort auf deinem Device erscheinen.

  1. Ermitteln Sie Ihre lokale IP-Adresse:
# macOS
ipconfig getifaddr en0

# Windows
ipconfig
  1. Erstelle eine Capacitor Dev-Config. Füge sie zu 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. Starte den Dev-Server und kopiere die Config zum Native-Projekt:
bun run dev &
NODE_ENV=development bunx cap copy
  1. In Xcode/Android Studio neu builden

Änderungen an deinem Next.js code werden nun per Hot-Reload auf dem Device angezeigt.

Schritt 9: Deinen ersten mobilen Screen erstellen

Erstellen wir einen einfachen, mobile-optimierten Home-Screen. Update 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>
  );
}

Schritt 10: Safe Area Handling hinzufügen

Mobile Geräte haben Notches, Home-Indikatoren und Statusleisten. Füge Safe Area Handling mit Tailwind hinzu.

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

Projektstruktur

Dein Projekt sollte nun so aussehen:

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
└── ...

Nächste Schritte

Du hast jetzt eine funktionierende Next.js-Mobile-App. Das sind die nächsten Schritte:

Grundlegendes Setup

  • App-Icons: Ersetze die Standard-Icons in ios/App/App/Assets.xcassets und android/app/src/main/res
  • Splash Screen: In nativen Projekten anpassen oder nutzen: @capacitor/splash-screen Konfiguration
  • Deep Links: URL-Schemes für deine App konfigurieren

Mehr Features hinzufügen

  • Kamera: bun add @capacitor/camera
  • Geolocation: bun add @capacitor/geolocation
  • Push-Benachrichtigungen: bun add @capacitor/push-notifications
  • Dateisystem: bun add @capacitor/filesystem

Native UI und Übergänge

Nutze Capgo Plugins statt Konsta UI für ein natives Mobile-Feeling:

bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync

Für Tailwind Safe Areas füge hinzu @capgo/tailwind-capacitor:

bun add -D tailwind-capacitor

Siehe Verwendung von @capgo/capacitor-native-navigation, Verwendung von @capgo/capacitor-transitions, und die tailwind-capacitor Repo für das Next.js-spezifische Setup.

iOS-Layoutprobleme beheben (Viewport, Safe Area und horizontaler Overflow)

Wenn Inhalte auf iOS abgeschnitten, verschoben oder horizontal scrollbar wirken, hilft es meist nicht, mehr overflow-x: hidden hinzuzufügen oder nur das Viewport-Tag zu ändern. Gehe diese Checks der Reihe nach durch.

Stelle sicher, dass das Viewport-Meta-Tag korrekt angewendet wird

App Router (app/): export viewport von app/layout.tsx:

import type { Viewport } from 'next';

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

Pages Router (pages/): füge das Viewport-Meta-Tag in pages/_app.tsx, nicht _document.tsx.

iOS Safe Area nur von einem Root-Wrapper aus handhaben

Erstelle eine einzige App-Shell und wende dort das Safe-Area-Padding an – nicht in mehreren verschachtelten Komponenten:

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

Umschließe den gesamten Seiteninhalt mit .app-shellDoppeltes Safe-Area-Padding in Headern, Modals und Layout-Wrappern lässt das UI oft abgeschnitten oder zu groß wirken.

Mit @capgo/tailwind-capacitor, kannst du dasselbe Padding mit Utilities wie pt-safe pb-safe px-safe in dieser einen Shell ausdrücken.

Setze Capacitor iOS contentInset zu never zuerst

Unter capacitor.config.ts, deaktiviere lieber native Insets und überlasse CSS (oder der Native Navigation contentInsetMode: 'css') die Safe Area:

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

Kombination von Capacitor’s automatischen Content Insets mit CSS env(safe-area-inset-*) Padding ist eine häufige Ursache für doppelte Abstände.

Das tatsächlich überlaufende Element finden

Der übliche Übeltäter ist ein Element mit 100vw, Tailwind w-screen, einer festen Pixelbreite oder einem großen min-width.

Im Safari Web Inspector ausführen:

[...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,
  }));

Mit Tailwind ersetzen w-screen mit w-full wann immer möglich. Viele Probleme mit horizontalem Overflow entstehen durch 100vw / w-screen, doppeltes Safe-Area-Padding oder einen Container mit fester Breite – nicht durch das Viewport-Meta-Tag selbst.

Over-the-Air Updates

Einrichten Capgo um Updates ohne erneute Einreichung im App Store zu pushen:

bunx @capgo/cli init

Fehlerbehebung

Build schlägt fehl: „Cannot find module“ Ausführen bun install und versuche es erneut.

iOS: „No signing identity found“ Öffne Xcode, gehe zu Signing & Capabilities und wähle dein Development Team aus.

Android: „SDK location not found“ Erstellen android/local.properties mit sdk.dir=/path/to/android/sdk

Änderungen werden nicht auf dem Gerät angezeigt Stelle sicher, dass du ausgeführt hast bun run mobile nachdem du Änderungen vorgenommen hast. Für Live Reload prüfe, ob die IP-Adresse korrekt ist und der Dev-Server läuft.

Ressourcen

Bereit für den App-Release? Erfahre, wie Capgo dir hilft, Updates schneller auszuliefern — Registrieren Sie sich für ein kostenloses Konto noch heute.

Weiter mit: Eine Next.js Mobile App von Grund auf mit Capacitor bauen 8

Wenn du es nutzt Next.js Mobile App von Grund auf bauen mit Capacitor 8 um CI/CD-Automatisierung zu planen, verbinde es mit Capgo CI/CD für den Produkt-Workflow in Capgo CI/CD, Capgo Native Builds optimieren für den Produkt-Workflow in Capgo Native Builds, Capgo Integrationen für den Produkt-Workflow in Capgo Integrations, CI/CD-Integration für die Implementierungsdetails in der CI/CD-Integration und GitHub Actions-Integration für die Implementierungsdetails in der GitHub Actions-Integration.

Live-Updates für Capacitor-Apps

Wenn ein Bug im Web-Layer live ist, liefere den Fix über Capgo aus, statt Tage auf die App-Store-Freigabe zu warten. Nutzer bekommen das Update im Hintergrund, während native Änderungen im normalen Review-Prozess bleiben.

Neues aus unserem Blog

Capgo gibt dir die besten Insights, um eine wirklich professionelle Mobile App zu erstellen.