Saltar al contenido principal
Tutoriales

Crea una aplicación móvil de Nuxt desde cero con Capacitor 8

Guía paso a paso para crear un nuevo proyecto de Nuxt 4 y convertirlo en aplicaciones móviles nativas de iOS y Android utilizando Capacitor 8. Ideal para empezar de cero con el desarrollo de Vue móvil.

Martin Donadieu

Martin Donadieu

Gerente de contenido

Crea una aplicación móvil de Nuxt desde cero con Capacitor 8

Introducción

¿Quieres crear una aplicación móvil con Nuxt desde cero? Este manual te guía a través de la creación de un proyecto de Nuxt 4 completamente nuevo configurado para móviles desde el principio, luego empaquetándolo como aplicaciones nativas de iOS y Android Capacitor 8.

Al finalizar este tutorial, tendrás una aplicación móvil en funcionamiento en simuladores que podrás seguir desarrollando y eventualmente publicar en la Tienda de App y Google Play.

Tiempo requerido: ~30 minutos

Lo que construirás:

  • Un nuevo proyecto de Nuxt 4 con la estructura de directorios más reciente
  • Configuración de generación estática para móviles
  • Capacitor 8 con plugins esenciales
  • Aplicaciones nativas de iOS y Android
  • Configuración de desarrollo con reloj de vida

Ya tienes una aplicación de Nuxt? Revisa Convierte tu aplicación de Nuxt a móvil en su lugar.

Requisitos previos

Asegúrate de que tengas instalados:

  • Node.js 18+ (verifica con node --version)
  • Bun administrador de paquetes (curl -fsSL https://bun.sh/install | bash)
  • Xcode (solo para macOS, para desarrollo de iOS)
  • Android Studio (para el desarrollo de Android)

Paso 1: Crear un Nuevo Proyecto Nuxt 4

Comience creando un proyecto Nuxt 4 fresco:

bunx nuxi@latest init my-mobile-app
cd my-mobile-app
bun install

Estructura de Directorio de Nuxt 4

Nuxt 4 utiliza una nueva estructura de directorio con app code en el app/ directorio:

my-mobile-app/
  app/
    assets/
    components/
    composables/
    layouts/
    middleware/
    pages/
    plugins/
    utils/
    app.vue
  public/
  server/
  nuxt.config.ts
  package.json

Esta estructura proporciona una mejor separación entre la aplicación y el servidor code.

Paso 2: Configurar Nuxt para Generación Estática

Capacitor requiere archivos HTML/JS/CSS estáticos. Configure Nuxt para la generación estática en nuxt.config.ts:

export default defineNuxtConfig({
  compatibilityDate: '2025-01-15',
  devtools: { enabled: true },

  // Enable static generation
  ssr: true,
  nitro: {
    preset: 'static',
  },
});

Paso 3: Agregar Scripts Móviles

Actualice su package.json con scripts de desarrollo móvil:

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

Prueba la generación estática:

bun run generate

Deberías ver un .output/public directorio con tus archivos estáticos.

Paso 4: Instala Capacitor 8

Instala los paquetes de core de Capacitor:

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

Instala plugins esenciales que la mayoría de las aplicaciones móviles necesitan:

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

¿Qué hacen estos plugins?

  • @capacitor/app — Eventos de ciclo de vida de la aplicación (anterior/fondo, enlaces profundos)
  • @capacitor/keyboard — Controla el comportamiento del teclado
  • @capacitor/splash-screen — Control de pantalla de arranque nativa
  • @capacitor/barra_de_estado — Estiliza la barra de estado del dispositivo
  • @capacitor/preferencias — Almacenamiento de valores clave (como localStorage pero nativo)

Paso 5: Inicializa Capacitor

Inicializa Capacitor con los detalles de tu proyecto:

bunx cap init "My Mobile App" com.example.mymobileapp --web-dir .output/public

Sustituye:

  • "My Mobile App" por el nombre de tu aplicación
  • com.example.mymobileapp por el ID de tu aplicación (notación de dominio inverso)

Esto crea capacitor.config.ts. Actualiza con la configuración del plugin:

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;

Step 6: Agregar Plataformas Nativas

Instale los paquetes de plataforma:

bun add @capacitor/ios @capacitor/android

Genere los proyectos nativos:

bunx cap add ios
bunx cap add android

Esto crea ios y android directorios que contienen los proyectos nativos.

Step 7: Compilar y Ejecutar

Compile su proyecto y sincronice con las plataformas nativas:

bun run mobile

Abrir en iOS Simulator:

bun run mobile:ios

O Emulador de Android:

bun run mobile:android

En Xcode (iOS):

  1. Seleccione un simulador desde el menú de dispositivos
  2. Haga clic en el botón de reproducción o presione Cmd + R

En Android Studio:

  1. Espera a que Gradle termine sincronizando
  2. Seleccione un emulador desde el menú desplegable de dispositivos
  3. Haga clic en el botón de ejecución o presione Shift + F10

Paso 8: Configura la recarga en vivo

Para un desarrollo más rápido, habilite la recarga en vivo para que los cambios aparezcan instantáneamente en tu dispositivo.

  1. Encuentra tu dirección IP local:
# macOS
ipconfig getifaddr en0

# Windows
ipconfig
  1. Crea una configuración de desarrollo Capacitor. Actualiza 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;
  1. Inicia el servidor de desarrollo y copia la configuración a nativo:
bun run dev &
NODE_ENV=development bunx cap copy
  1. Reconstruye en Xcode/Android Studio

Ahora los cambios en tu Nuxt code se recargarán automáticamente en el dispositivo.

Paso 9: Crea tu primera pantalla móvil

Vamos a crear una pantalla de inicio amigable con dispositivos móviles. Actualiza app/app.vue:

<template>
  <NuxtPage />
</template>

Crear 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>

Paso 10: Agrega Tailwind CSS

Para que el estilo funcione, agrega Tailwind CSS a tu proyecto:

bun add tailwindcss @tailwindcss/vite

Actualiza 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()],
  },
});

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

Paso 11: Agrega el plugin de Compartir

Vamos a implementar la funcionalidad del botón de compartir:

bun add @capacitor/share

Actualiza para usar el plugin de Compartir: app/pages/index.vue Sincroniza y reconstruye:

<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>

Sincroniza y reconstruye:

bun run mobile

Estructura del Proyecto

Su proyecto debería verse ahora así:

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

Pasos Siguientes

Ahora tiene una aplicación móvil de Nuxt funcionando. Aquí hay lo que debe hacer a continuación:

Configuración Esencial

  • Íconos de la Aplicación: Sustituya los íconos predeterminados en ios/App/App/Assets.xcassets y android/app/src/main/res
  • Pantalla de Inicio: Personalice en proyectos nativos o utilice @capacitor/splash-screen config
  • Enlaces Profundos: Configura esquemas de URL para tu aplicación

Agregar más características

  • Cámara: bun add @capacitor/camera
  • Ubicación: bun add @capacitor/geolocation
  • Notificaciones de push: bun add @capacitor/push-notifications o @capgo/capacitor-firebase-messaging para Firebase Cloud Messaging en iOS y Android
  • Sistema de archivos: bun add @capacitor/filesystem

Interfaz de usuario nativa y transiciones

Utiliza plugins de Capgo en lugar de Konsta UI para un sentir móvil nativo:

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

Para áreas seguras de Tailwind, agrega @capgo/tailwind-capacitor:

bun add -D tailwind-capacitor

Ver Usando @capgo/capacitor-navegación nativa, Usando @capgo/capacitor-transiciones, y el repo tailwind-capacitor para la configuración específica de Nuxt.

Solucionando problemas de diseño de iOS (Vista previa, área segura y rebosamiento horizontal)

If el contenido parece recortado, desplazado o desplazable horizontalmente en iOS, agregar más overflow-x: hidden o ajustar la etiqueta de viewport en sí solo no suele solucionar el problema. Trabaja a través de estas comprobaciones en orden.

Asegúrate de que la etiqueta meta de viewport se aplique correctamente

In nuxt.config.ts, establece la vista previa a través de app.head:

export default defineNuxtConfig({
  app: {
    head: {
      meta: [
        {
          name: 'viewport',
          content: 'width=device-width, initial-scale=1, viewport-fit=cover',
        },
      ],
    },
  },
});

Gestiona el área segura de iOS desde un solo contenedor raíz

Crea una caja de aplicación única y aplica allí el relleno de área segura — no en múltiples componentes anidados:

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

Envuelve todo el contenido de la página dentro de .app-shellEl relleno de área segura duplicado en encabezados, modales y contenedores de diseño a menudo hace que la interfaz de usuario parezca recortada o demasiado grande.

Con @capgo/tailwind-capacitor, puedes expresar el mismo relleno con utilidades como pt-safe pb-safe px-safe en ese solo shell.

Establezca Capacitor iOS contentInset a never primero

En capacitor.config.ts, prefiera el área de seguridad deshabilitada y deja que CSS (o la navegación nativa) se encargue de ella: contentInsetMode: 'css'Mezclar el área de contenido automática de __CAPGO_KEEP_0__ con CSS

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

Mixing Capacitor’s automatic content inset with CSS env(safe-area-inset-*) Encuentre el elemento que está desbordando en realidad

El culpable usual es un elemento que utiliza

, Tailwind 100vwes una causa común de doble espaciado. w-screeno ancho de píxel fijo, o un gran min-width.

In Safari Web Inspector, run:

[...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, reemplaza w-screen con w-full cuando sea posible. Muchos problemas de rebosamiento horizontal provienen de 100vw / w-screen, relleno de área segura duplicado, o un contenedor de ancho fijo — no del meta de viewport en sí.

Actualizaciones en Línea

Configura Capgo para enviar actualizaciones sin necesidad de volver a subir la aplicación a la tienda:

bunx @capgo/cli init

Solución de Problemas

La compilación falla con “No se puede encontrar el módulo” Ejecuta bun install y vuelve a intentarlo.

iOS: “No se encontró identidad de firma” Abre Xcode, ve a Signing &amp; Capabilities, y selecciona tu equipo de desarrollo.

Android: “SDK no se encontró en la ubicación” Crear android/local.properties con sdk.dir=/path/to/android/sdk

No se están mostrando los cambios Asegúrate de que ejecutaste bun run mobile después de hacer cambios. Para el recarga en vivo, verifica que la dirección IP es correcta y que el servidor de desarrollo está en ejecución.

.output/public está vacío o faltante Asegúrate de que configuraste nitro: { preset: 'static' } in nuxt.config.ts y ejecutar bun run generate.

Recursos

¿Estás listo para enviar tu aplicación? Aprende cómo Capgo puede ayudarte a entregar actualizaciones más rápido — regístrate para una cuenta gratuita hoy.

Sigue adelante desde Crea una Aplicación Móvil de Nuxt desde Cero con Capacitor 8

Si estás utilizando Crea una Aplicación Móvil de Nuxt desde Cero con Capacitor 8 para planificar la automatización de CI/CD, conecta con Capgo CI/CD para el flujo de trabajo del producto en Capgo CI/CD, Capgo Compilaciones Nativas para el flujo de trabajo del producto en Capgo Compilaciones Nativas, Capgo Integraciones para el flujo de trabajo del producto en Capgo Integraciones, Integración de CI/CD para el detalle de implementación en Integración de CI/CD, y Acciones de GitHub Integración para el detalle de implementación en Acciones de GitHub Integración.

Actualizaciones en vivo para aplicaciones Capacitor

Cuando un error en la capa web está activo, envíe la corrección a través de Capgo en lugar de esperar días para la aprobación de la tienda de aplicaciones. Los usuarios reciben la actualización en segundo plano mientras los cambios nativos siguen en el camino de revisión normal.

Comienza Ahora

Últimas noticias de nuestro Blog

Capgo le da las mejores perspectivas que necesita para crear una aplicación móvil verdaderamente profesional.