Einführung
Möchtest du eine mobile App mit Nuxt von Grund auf neu bauen? Dieser Guide zeigt dir, wie du ein brandneues Nuxt 4 Projekt erstellst, das von Tag eins an für Mobile konfiguriert ist, und es dann 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 Nuxt 4 Projekt mit der neuesten Verzeichnisstruktur
- Konfiguration der statischen Generierung für Mobile
- Capacitor 8 mit essenziellen Plugins
- Native iOS- und Android-Apps
- Live-Reload-Setup für die Entwicklung
Schon eine Nuxt App? Schau dir an: Deine Nuxt App für Mobile konvertieren 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 Nuxt 4 Projekt erstellen
Erstelle zuerst ein frisches Nuxt 4 Projekt:
bunx nuxi@latest init my-mobile-app
cd my-mobile-app
bun install
Nuxt 4 Verzeichnisstruktur
Nuxt 4 nutzt eine neue Verzeichnisstruktur mit der App code in der app/ Verzeichnis:
my-mobile-app/
app/
assets/
components/
composables/
layouts/
middleware/
pages/
plugins/
utils/
app.vue
public/
server/
nuxt.config.ts
package.json
Diese Struktur sorgt für eine bessere Trennung zwischen App- und Server-code.
Schritt 2: Nuxt für Static Generation konfigurieren
Capacitor benötigt statische HTML/JS/CSS-Dateien. Konfiguriere Nuxt für Static Generation in nuxt.config.ts:
export default defineNuxtConfig({
compatibilityDate: '2025-01-15',
devtools: { enabled: true },
// Enable static generation
ssr: true,
nitro: {
preset: 'static',
},
});
Schritt 3: Mobile Scripts hinzufügen
Aktualisiere dein package.json mit Scripts für die mobile Entwicklung:
{
"scripts": {
"dev": "nuxt dev",
"build": "nuxt build",
"generate": "nuxt generate",
"preview": "nuxt preview",
"mobile": "bun run generate && bunx cap sync",
"mobile:ios": "bun run mobile && bunx cap open ios",
"mobile:android": "bun run mobile && bunx cap open android"
}
}
Static Generation testen:
bun run generate
Du solltest einen .output/public 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 des Geräts
- @capacitor/preferences — Key-Value-Speicherung (wie localStorage, aber nativ)
Schritt 5: Capacitor initialisieren
Initialisiere Capacitor mit deinen Projektdaten:
bunx cap init "My Mobile App" com.example.mymobileapp --web-dir .output/public
Ersetze:
"My Mobile App"durch den Anzeigenamen deiner Appcom.example.mymobileappdurch deine App-ID (Reverse-Domain-Notation)
Dadurch entstehen capacitor.config.ts. Aktualisiere es mit der Plugin-Konfiguration:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.mymobileapp',
appName: 'My Mobile App',
webDir: '.output/public',
plugins: {
SplashScreen: {
launchShowDuration: 2000,
launchAutoHide: true,
androidScaleType: 'CENTER_CROP',
splashFullScreen: true,
splashImmersive: true,
},
Keyboard: {
resize: 'body',
resizeOnFullScreen: true,
},
StatusBar: {
style: 'dark',
},
},
};
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):
- Wähle einen Simulator aus dem Geräte-Dropdown
- Klicke auf den Play-Button oder drücke
Cmd + R
In Android Studio:
- Warten, bis Gradle das Syncing beendet hat
- Wähle einen Emulator aus dem Device-Dropdown
- Klicke auf den Run-Button oder drücke
Shift + F10
Schritt 8: Live Reload einrichten
Aktiviere Live Reload für eine schnellere Entwicklung, damit Änderungen sofort auf deinem Gerät erscheinen.
- Ermitteln Sie Ihre lokale IP-Adresse:
# macOS
ipconfig getifaddr en0
# Windows
ipconfig
- Erstelle eine Capacitor Dev-Config. Aktualisieren
capacitor.config.ts:
import type { CapacitorConfig } from '@capacitor/cli';
const devConfig: CapacitorConfig = {
appId: 'com.example.mymobileapp',
appName: 'My Mobile App',
webDir: '.output/public',
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: '.output/public',
plugins: {
// ... same plugin config
},
};
const config = process.env.NODE_ENV === 'development' ? devConfig : prodConfig;
export default config;
- Starte den Dev-Server und kopiere die Config in den nativen Teil:
bun run dev &
NODE_ENV=development bunx cap copy
- In Xcode/Android Studio neu bauen
Änderungen an deinem Nuxt code werden nun per Hot-Reload auf dem Gerät angezeigt.
Schritt 9: Erstelle deinen ersten Mobile Screen
Lass uns einen mobil-optimierten Home Screen erstellen. Aktualisieren app/app.vue:
<template>
<NuxtPage />
</template>
Erstellen app/pages/index.vue:
<template>
<main
class="min-h-screen bg-linear-to-b from-green-500 to-green-700 flex flex-col items-center justify-center p-6 text-white"
>
<h1 class="text-4xl font-bold mb-4">My Mobile App</h1>
<p class="text-xl mb-8 text-center opacity-90">
Built with Nuxt 4 + Capacitor 8
</p>
<div v-if="appInfo" class="bg-white/20 rounded-lg p-4 backdrop-blur-sm mb-8">
<p class="text-sm">
{{ appInfo.name }} v{{ appInfo.version }}
</p>
</div>
<div class="space-y-4 w-full max-w-sm">
<button
class="w-full py-4 px-6 bg-white text-green-600 rounded-xl font-semibold text-lg shadow-lg active:scale-95 transition-transform"
@click="handleGetStarted"
>
Get Started
</button>
<button
class="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"
@click="handleShare"
>
Share App
</button>
</div>
</main>
</template>
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { App } from '@capacitor/app';
const appInfo = ref<{ name: string; version: string } | null>(null);
let backButtonListener: { remove: () => void } | null = null;
onMounted(async () => {
// Get app info
try {
appInfo.value = await App.getInfo();
} catch (e) {
// Web fallback
appInfo.value = { name: 'My Mobile App', version: '1.0.0' };
}
// Handle Android back button
backButtonListener = await App.addListener('backButton', ({ canGoBack }) => {
if (!canGoBack) {
App.exitApp();
} else {
window.history.back();
}
});
});
onUnmounted(() => {
backButtonListener?.remove();
});
function handleGetStarted() {
// Navigate to onboarding or main app
console.log('Get started clicked');
}
async function handleShare() {
// We'll implement this with the Share plugin later
console.log('Share clicked');
}
</script>
Schritt 10: Tailwind CSS hinzufügen
Damit das Styling funktioniert, füge Tailwind CSS zu deinem Projekt hinzu:
bun add tailwindcss @tailwindcss/vite
Update nuxt.config.ts:
import tailwindcss from '@tailwindcss/vite';
export default defineNuxtConfig({
compatibilityDate: '2025-01-15',
devtools: { enabled: true },
ssr: true,
nitro: {
preset: 'static',
},
css: ['~/assets/css/main.css'],
vite: {
plugins: [tailwindcss()],
},
});
Erstellen app/assets/css/main.css:
@import 'tailwindcss';
: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;
}
Schritt 11: Das Share Plugin hinzufügen
Implementieren wir die Share-Button-Funktionalität:
bun add @capacitor/share
Update app/pages/index.vue um das Share Plugin zu nutzen:
<script setup lang="ts">
import { ref, onMounted, onUnmounted } from 'vue';
import { App } from '@capacitor/app';
import { Share } from '@capacitor/share';
// ... existing code ...
async function handleShare() {
try {
await Share.share({
title: 'Check out this app!',
text: 'Built with Nuxt 4 and Capacitor 8',
url: 'https://capacitorjs.com',
dialogTitle: 'Share with friends',
});
} catch (e) {
console.log('Share cancelled or failed:', e);
}
}
</script>
Sync und Rebuild:
bun run mobile
Projektstruktur
Dein Projekt sollte nun so aussehen:
my-mobile-app/
├── android/ # Android native project
├── ios/ # iOS native project
├── .output/
│ └── public/ # Static build output
├── app/
│ ├── assets/
│ │ └── css/
│ │ └── main.css
│ ├── pages/
│ │ └── index.vue
│ └── app.vue
├── capacitor.config.ts # Capacitor configuration
├── nuxt.config.ts # Nuxt configuration
├── package.json
└── ...
Nächste Schritte
Deine Nuxt Mobile App läuft jetzt. Das sind die nächsten Schritte:
Grundlegendes Setup
- App-Icons: Ersetze die Standard-Icons in
ios/App/App/Assets.xcassetsundandroid/app/src/main/res - Splash Screen: In nativen Projekten anpassen oder nutzen:
@capacitor/splash-screenKonfiguration - 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-notificationsoder @capgo/capacitor-firebase-messaging für Firebase Cloud Messaging auf iOS und Android - Dateisystem:
bun add @capacitor/filesystem
Native UI und Übergänge
Nutze Capgo Plugins statt Konsta UI für ein natives Mobile-Feeling:
- @capgo/capacitor-native-navigation — Liquid Glass Tab-Bar und native Navbar
- @capgo/capacitor-transitions — Page Transitions, die sich nativ anfühlen
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 Nuxt-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
Unter nuxt.config.ts, setze den Viewport über app.head:
export default defineNuxtConfig({
app: {
head: {
meta: [
{
name: 'viewport',
content: 'width=device-width, initial-scale=1, viewport-fit=cover',
},
],
},
},
});
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,
#__nuxt {
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: '.output/public',
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 nach den Änderungen. Für Live Reload prüfe, ob die IP-Adresse stimmt und der Dev-Server läuft.
.output/public ist leer oder fehlt
Make sure you configured nitro: { preset: 'static' } in nuxt.config.ts und führe aus: bun run generate.
Ressourcen
- Capacitor 8 Dokumentation
- Nuxt 4 Dokumentation
- Capgo - Live Updates
- @capgo/capacitor-native-navigation
- @capgo/capacitor-transitions
- @capgo/tailwind-capacitor
Bereit für den App-Release? Erfahre, wie Capgo dir hilft, Updates schneller auszuliefern — Registrieren Sie sich für ein kostenloses Konto noch heute.
Weiterlesen: Nuxt Mobile App von Grund auf mit Capacitor bauen 8
Wenn du es nutzt Nuxt 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.