En este tutorial, te guiaremos en el proceso de convertir una web app de Vue en una app móvil nativa usando Capacitor. También puedes añadir Capgo Native Navigation and Transitions para una sensación nativa, y usar tailwind-capacitor para las safe areas.
Acerca de Capacitor
Capacitor es una herramienta revolucionaria que te permite integrarla fácilmente en cualquier proyecto web para convertir tu app en una app móvil nativa. Genera proyectos nativos de Xcode y Android Studio y te da acceso a funciones nativas del dispositivo, como la cámara, mediante un bridge de JavaScript.
Preparando tu app de Vue
Primero, crea una nueva app de Vue ejecutando el siguiente comando:
vue create my-app
cd my-app
npm install
Para preparar tu app de Vue para el despliegue móvil nativo, deberás exportar tu proyecto. Añade un script en tu package.json para buildear y copiar el proyecto de Vue:
{
"scripts": {
// ...
"build": "vue-cli-service build"
}
}
Tras ejecutar el build comando, deberías ver una nueva dist carpeta en el directorio raíz de tu proyecto. Esta carpeta será usada por Capacitor más adelante.
Añadir Capacitor a tu app de Vue
Para convertir tu web app de Vue en un contenedor móvil nativo, sigue estos pasos:
-
Instala el Capacitor CLI como dependencia de desarrollo y configúralo en tu proyecto. Acepta los valores por defecto para el nombre y el bundle ID durante el setup.
-
Instala el paquete core y los paquetes necesarios para las plataformas iOS y Android.
-
Añade las plataformas y Capacitor creará las carpetas de cada plataforma en la raíz de tu proyecto:
# Install the Capacitor CLI locally
npm install -D @capacitor/cli
# Initialize Capacitor in your Vue project
npx cap init
# Install the required packages
npm install @capacitor/core @capacitor/ios @capacitor/android
# Add the native platforms
npx cap add ios
npx cap add android
Ahora deberías ver nuevas iOS y Android carpetas en tu proyecto Vue.
Actualiza el capacitor.config.json para apuntar el webDir al resultado de tu comando de build:
{
"appId": "com.example.app",
"appName": "my-app",
"webDir": "dist"
}
Ahora puedes hacer el build de tu proyecto Vue y sincronizarlo con Capacitor:
npm run build
npx cap sync
Compila y despliega apps nativas
Para desarrollar apps de iOS, necesitas tener instalado Xcode, y para Android, Android Studio. Además, debes registrarte en el Apple Developer Program para iOS y en Google Play Console para Android para distribuir tu app en las tiendas.
Usa Capacitor CLI para abrir ambos proyectos nativos:
npx cap open ios
npx cap open android
Despliega tu app en un dispositivo conectado usando Android Studio o Xcode.
Live Reload con Capacitor
Activa el live reload en tu dispositivo móvil haciendo que la app Capacitor cargue el contenido desde una URL específica de tu red.
Busca tu dirección IP local y actualiza el capacitor.config.ts archivo con la IP y el puerto correctos:
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: 'dist',
bundledWebRuntime: false,
server: {
url: 'http://192.168.x.xx:8080',
cleartext: true
}
};
export default config;
Aplica estos cambios copiándolos en tu proyecto nativo:
npx cap copy
Ahora, tu app se recargará automáticamente y mostrará los cambios cuando actualices tu app de Vue.
Uso de plugins de Capacitor
Instala un plugin de Capacitor, como el plugin Share, y úsalo en tu app de Vue:
npm i @capacitor/share
Importa el paquete y llama al share() función en tu app:
<template>
<div>
<h1>Welcome to Vue and Capacitor!</h1>
<button @click="share">Share now!</button>
</div>
</template>
<script setup lang="ts">
import { Share } from '@capacitor/share';
async function share() {
await Share.share({
title: 'Open Youtube',
text: 'Check new video on youtube',
url: 'https://www.youtube.com',
dialogTitle: 'Share with friends'
});
}
</script>
Tras instalar nuevos plugins, ejecuta el sync comando y vuelve a desplegar la app en tu dispositivo:
npx cap sync
Después, puedes hacer que la app se sienta más nativa en iOS y Android con la navegación y transiciones de Capgo, y solucionar problemas comunes de layout en iOS que causan desbordamiento horizontal o áreas seguras recortadas.
UI con sensación nativa gracias a Capgo Native Navigation and Transitions
He trabajado durante años con Ionic para crear apps multiplataforma, pero integrarlo con Vue es complejo y rara vez vale la pena si ya tienes Tailwind CSS.
Para una sensación nativa en una app de Vue + Capacitor, usa plugins de Capgo en lugar de UI kits web como Konsta UI:
- @capgo/capacitor-native-navigation — navbar nativa, Liquid Glass tab bar en iOS y un estilo de tab bar con desenfoque en Android. Tu Vue router gestiona el estado de las rutas; el plugin controla el chrome nativo.
- @capgo/capacitor-transitions — Transiciones de página estilo Ionic y gesto de retroceso en iOS en la capa WebView, sin necesidad de usar Ionic UI.
Instala ambos:
bun add @capgo/capacitor-native-navigation @capgo/capacitor-transitions
bunx cap sync
Configura la navegación nativa con CSS inset mode para que el contenido web respete las barras nativas:
import { NativeNavigation } from '@capgo/capacitor-native-navigation';
await NativeNavigation.configure({
contentInsetMode: 'css',
animationDuration: 360,
glass: {
effect: 'liquidGlass',
},
});
Renderiza una tab bar Liquid Glass (iOS usa renderizado del sistema; Android usa un fondo WebView desenfocado):
await NativeNavigation.setTabbar({
selectedId: 'home',
labelVisibilityMode: 'labeled',
icons: true,
colors: { dynamic: true },
tabs: [
{ id: 'home', title: 'Home', icon: { svg: '...' } },
{ id: 'settings', title: 'Settings', icon: { svg: '...' } },
],
});
await NativeNavigation.addListener('tabSelect', ({ id }) => {
router.push(`/${id}`);
});
Añade transiciones de página nativas en tu app shell:
<script setup>
import { ref, onMounted } from 'vue';
import { useRouter } from 'vue-router';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions/vue';
initTransitions({ platform: 'auto' });
const router = useRouter();
const outletRef = ref(null);
onMounted(() => {
if (outletRef.value) {
setupRouterOutlet(outletRef.value, { platform: 'auto', swipeGesture: 'auto' });
}
});
const openSettings = () => {
setDirection('forward');
router.push('/settings');
};
</script>
<template>
<cap-router-outlet ref="outletRef">
<router-view />
</cap-router-outlet>
</template>
Envuelve las páginas enrutadas en cap-router-outlet, cap-page, y cap-content, y llama a setDirection('forward') o setDirection('back') antes de navegar. No dupliques headers o footers web si la navegación nativa ya gestiona esas áreas.
Consulta las guías completas: Usando @capgo/capacitor-native-navigation y Usando @capgo/capacitor-transitions.
Safe areas con Tailwind
Para las safe areas en Tailwind CSS, usa @capgo/tailwind-capacitor (publicado como tailwind-capacitor en npm). Proporciona safe-areas utilidades y otros plugins de Tailwind compatibles con Capacitor:
bun add -D tailwind-capacitor
En src/assets/main.css:
@import 'tailwindcss';
@plugin "@capgo/tailwind-capacitor/platform";
@plugin "@capgo/tailwind-capacitor/safe-areas";
Usa utilidades como pt-safe, pb-safe, y px-safe en lugar de añadir env(safe-area-inset-*) manualmente. El proyecto se desarrolla activamente; si falta algo para tu configuración de Vue, abre un PR en GitHub.
Cómo solucionar problemas de layout en iOS (Viewport, Safe Area y desbordamiento horizontal)
Si el contenido se ve recortado, desplazado o con scroll horizontal en iOS, añadir más overflow-x: hidden o ajustar solo la etiqueta viewport no suele solucionarlo. Revisa estas comprobaciones en orden.
Asegúrate de que la etiqueta meta viewport esté aplicada correctamente
Añade el meta tag del viewport en index.html dentro de <head>:
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
Gestiona el safe area de iOS desde un único wrapper raíz
Crea un app shell único y aplica el padding del safe area ahí, no en múltiples componentes anidados:
html,
body,
#app {
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-shell. El padding de safe-area duplicado en headers, modales y wrappers de layout suele hacer que la UI parezca recortada o demasiado grande.
Con @capgo/tailwind-capacitor, puedes aplicar el mismo padding con utilidades como pt-safe pb-safe px-safe en ese único shell.
Configura Capacitor iOS contentInset a never primero
En capacitor.config.ts, prefiere desactivar el inset nativo y dejar que CSS (o la navegación nativa) contentInsetMode: 'css') se encarga del safe area:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'dist',
ios: {
contentInset: 'never',
},
};
Mezclar el content inset automático de Capacitor con CSS env(safe-area-inset-*) padding suele causar espacios dobles.
Encuentra el elemento real que desborda
El culpable habitual es un elemento que usa 100vw, Tailwind w-screen, un ancho fijo en píxeles, o un min-width.
En Safari Web Inspector, ejecuta:
[...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 siempre que puedas. Muchos problemas de desbordamiento horizontal vienen de 100vw / w-screen, padding de safe-area duplicado, o un contenedor de ancho fijo —no del propio meta tag del viewport.
Conclusión
Capacitor es una excelente opción para crear aplicaciones nativas a partir de un proyecto web existente. Con la incorporación de Capgo, es aún más fácil añadir actualizaciones en vivo a tu app, lo que garantiza que tus usuarios siempre tengan acceso a las últimas funciones y correcciones de errores.
Aprende cómo Capgo te ayuda a crear mejores apps más rápido, regístrate para obtener una cuenta gratis hoy mismo.
Continuación de: Cómo crear apps móviles con Vue y Capacitor
Si estás usando Cómo crear apps móviles con Vue y Capacitor para planificar el comportamiento de los medios y la interfaz nativos, conéctalo con Uso de @capgo/capacitor-live-activities para la capacidad nativa en Uso de @capgo/capacitor-live-activities, @capgo/capacitor-live-activities para los detalles de implementación en @capgo/capacitor-live-activities, Uso de @capgo/capacitor-video-player para la capacidad nativa al usar @capgo/capacitor-video-player, @capgo/capacitor-video-player para el detalle de implementación en @capgo/capacitor-video-player, y Usando @capgo/capacitor-native-navigation para la capacidad nativa al usar @capgo/capacitor-native-navigation.