Saltar al contenido principal
Tutoría

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

Pasos 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 nuevo con desarrollo de Vue móvil.

Créditos del artículo

Martín Donadieu

Escritor

Valeria

Revisor

Jordan

Editor

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

Introducción

¿Quieres construir una aplicación móvil con Nuxt desde cero? Este tutorial 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, y luego empaquetarlo como aplicaciones nativas de iOS y Android utilizando Capacitor 8.

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

Tiempo requerido: ~30 minutos

¿Qué 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 iOS y Android
  • Configuración de desarrollo con recarga en vivo

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

Requisitos previos

Asegúrate de tener instalados estos:

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

Step 1: Crea un Nuevo Proyecto de Nuxt 4

Comience creando un proyecto de Nuxt 4 fresco:

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

Estructura de directorios de Nuxt 4

Nuxt 4 utiliza una nueva estructura de directorios con la aplicación code en el app/ directory:

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: Configura 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',
  },
});

Step 3: Agrega scripts móviles

actualice package.json Prueba la generación estática:

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

carpeta con tus archivos estáticos. .output/public Step 4: Instala __CAPGO_KEEP_0__ 8

Instala los paquetes de núcleo de Capacitor:

Instale los paquetes de núcleo Capacitor.

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

Install essential plugins that most mobile apps need:

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

@__CAPGO_KEEP_0__/app

  • @capacitor/app — Eventos de ciclo de aplicación (anterior/plano, enlaces profundos)
  • @capacitor/teclado — Controlar el comportamiento del teclado
  • @capacitor/pantalla-de-inicio — Control de pantalla de inicio nativa
  • @capacitor/barra-de-estado — Estilizar la barra de estado del dispositivo
  • @capacitor/preferencias — Almacenamiento de valores clave (como localStorage pero nativo)

Paso 5: Inicializar Capacitor

Inicialice Capacitor con los detalles de su proyecto:

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

Sustituya:

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

Esto crea capacitor.config.ts. Actualice 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

Generar los proyectos nativos:

bunx cap add ios
bunx cap add android

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

Step 7: Compilar y Ejecutar

Compilar su proyecto y sincronice con las plataformas nativas:

bun run mobile

Abrir en Simulador de iOS:

bun run mobile:ios

O Android Emulador:

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 de sincronizar
  2. Seleccione un emulador desde el menú de dispositivos
  3. Haga clic en el botón de ejecución o presione Shift + F10

Paso 8: Configuración de Live Reload

Para un desarrollo más rápido, habilite la recarga en vivo para que los cambios se reflejen de inmediato en su dispositivo.

  1. Encuentre su dirección IP local:
# macOS
ipconfig getifaddr en0

# Windows
ipconfig
  1. Cree un archivo de configuración de desarrollo Capacitor. Actualice 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. Arranque el servidor de desarrollo y copie la configuración a nativo:
bun run dev &
NODE_ENV=development bunx cap copy
  1. Reconstruya en Xcode/Android Studio

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

Paso 9: Crea tu primera pantalla móvil

Crea 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

Actualizar 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

Actualización app/pages/index.vue a utilizar el plugin de Compartir:

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

Sincronice y reconstruye:

bun run mobile

Estructura del Proyecto

Tu proyecto debería verse 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 tienes una aplicación móvil de Nuxt funcionando. Aquí tienes qué hacer a continuación:

Configuración básica

  • App Icons: Sustituye los iconos predeterminados en ios/App/App/Assets.xcassets y android/app/src/main/res
  • Pantalla de bienvenida: Personalizar en proyectos nativos o usar @capacitor/splash-screen config
  • Enlaces Profundos: Configurar 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 Push: bun add @capacitor/push-notifications o @capgo/capacitor-messaging-de-firebase Para Firebase Cloud Messaging en iOS y Android
  • Sistema de Archivos: bun add @capacitor/filesystem

Interfaz nativa y transiciones

Utilice plugins 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, agregue @capgo/tailwind-capacitor:

bun add -D tailwind-capacitor

Consulte Usando @capgo/capacitor-navegación-nativa, Usando @capgo/capacitor-transicionesy repo de tailwind-capacitor para la configuración específica de Nuxt.

Corrección de problemas de diseño en iOS (Vista previa, Área segura y desbordamiento horizontal)

Si el contenido parece recortado, desplazado o desplazable horizontalmente en iOS, agregar más overflow-x: hidden o ajustar la etiqueta de vista previa sola no suele solucionar el problema. Pase por estos controles en orden.

Asegúrese de que la etiqueta meta de vista previa se aplique correctamente

En nuxt.config.ts, establezca 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',
        },
      ],
    },
  },
});

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

Crear un solo contenedor de aplicación y aplicar allí el relleno del á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);
}

Wrap all page content inside __CAPGO_KEEP_0__. .app-shellEl relleno de seguridad duplicado en encabezados, modales y wrappers de layout a menudo hace que la interfaz de usuario se vea recortada o demasiado grande.

With @capgo/tailwind-capacitor, puedes expresar el mismo relleno con utilidades como pt-safe pb-safe px-safe en esa sola caja.

Establece Capacitor iOS contentInset a never primero

En capacitor.config.ts, prefiera el diseño nativo deshabilitado y deja que CSS (o la navegación nativa) contentInsetMode: 'css') se encargue del área segura:

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

Mezclar el relleno de área automático de Capacitor con CSS env(safe-area-inset-*) es una causa común de doble espaciado.

Encuentre el elemento que desborda realmente

El culpable habitual es un elemento que utiliza 100vw, Tailwind w-screenuna anchura de píxel fija, o una gran min-width.

In Safari Web Inspector, ejecutar:

[...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 desbordamiento horizontal provienen de 100vw / w-screen, duplicado relleno de zona segura, o un contenedor de ancho fijo — no del meta de etiqueta de viewport en sí mismo.

Actualizaciones en Línea

Configuración Capgo Sin necesidad de reenviar la aplicación a la tienda.

bunx @capgo/cli init

Troubleshooting

El compilado falla con “No se encuentra el módulo” Ejecutar bun install y volver a intentarlo.

iOS: “No se encontró ninguna identidad de firma” Abra Xcode, vaya a Signing &amp; Capabilities, y seleccione su equipo de desarrollo.

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

Los cambios no se muestran en el dispositivo Asegúrese de haber ejecutado bun run mobile después de hacer cambios. Verifique la dirección IP es correcta y el servidor de desarrollo está en ejecución.

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

Recursos

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

Sigue adelante desde Construye una aplicación móvil de Nuxt desde cero con Capacitor 8

Si estás utilizando Construye una aplicación móvil de Nuxt desde cero con Capacitor 8 a planificar la automatización de CI/CD, conecta con Capgo CI/CD para el flujo de trabajo del producto en Capgo CI/CD, Capgo Builds Nativos para el flujo de trabajo del producto en Capgo Builds Nativos, Capgo Integraciones para el flujo de trabajo del producto en Capgo Integraciones, Integración CI/CD para los detalles de implementación en la Integración CI/CD, y GitHub Integración de Acciones para los detalles de implementación en GitHub Integración de Acciones.

Actualizaciones en vivo para aplicaciones Capacitor

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

Apoyo humano de Martin

Inicia ahora

Últimas noticias de nuestro Blog

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