Introducción
¿Tienes una web app en Next.js? En esta guía aprenderás a convertirla en apps nativas para iOS y Android usando Capacitor 8 — la última versión con mejor rendimiento y nuevas funciones.
Capacitor envuelve tu web app en un contenedor nativo, dándote acceso a APIs del dispositivo como cámara, filesystem y push notifications sin cambiar tu codebase de React. A diferencia de React Native, no tienes que reescribir nada: tu code de Next.js funciona tal cual.
Lo que aprenderás:
- Configura tu app de Next.js para static export
- Añadir Capacitor 8 con plugins nativos esenciales
- Compilar y probar en simuladores de iOS y Android
- Activar live reload para un desarrollo más rápido
- Corregir problemas comunes de layout en iOS (viewport, safe area, horizontal overflow)
- Añade una UI con sensación nativa con Capgo Native Navigation y Transitions
¿Quieres empezar un proyecto nuevo desde cero? Mira nuestra guía sobre Cómo crear una app móvil con Next.js desde cero.
Ventajas de usar Next.js y Capacitor
- Reutilización de Code: Next.js te permite escribir componentes reutilizables y compartir code entre tus apps web y móviles, ahorrando tiempo y esfuerzo de desarrollo.
- Rendimiento: Next.js ofrece optimizaciones de rendimiento integradas, como server-side rendering y code splitting, garantizando tiempos de carga rápidos y una experiencia de usuario fluida.
- Capacidades nativas: Capacitor da acceso a funciones nativas del dispositivo como la cámara, la geolocalización y más, permitiéndote crear apps móviles muy completas.
- Desarrollo simplificado: Con Capacitor, puedes desarrollar y probar tu app móvil usando tecnologías web que ya conoces, reduciendo la curva de aprendizaje y agilizando el proceso de desarrollo.
Requisitos
Antes de empezar, asegúrate de tener:
- Node.js 18+ instalado
- Un Next.js 15+ aplicación
- Xcode (para desarrollo iOS, solo macOS)
- Android Studio (para desarrollo Android)
Configura tu app de Next.js para móvil
El primer paso es configurar tu app de Next.js para exportación estática. Capacitor necesita archivos HTML/JS/CSS estáticos para empaquetarlos en la app nativa.
Abre tu next.config.js (o next.config.ts) archivo y añade la configuración de exportación:
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
unoptimized: true,
},
};
module.exports = nextConfig;
El output: 'export' este ajuste le indica a Next.js que genere archivos HTML estáticos, y images: { unoptimized: true } evita la optimización de imágenes de Next.js, que requiere un servidor.
Importante: Si usas funciones que requieren un servidor (API routes, server components con data fetching, etc.), deberás refactorizarlas para usar alternativas del lado del cliente o APIs externas.
Añade scripts específicos para móviles a tu package.json:
{
"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"
}
}
Prueba la exportación estática ejecutando:
bun run build
Deberías ver una carpeta out en la raíz de tu proyecto. Esta contiene todos los archivos estáticos que Capacitor empaquetará en tu app nativa.
Añadir Capacitor 8 a tu proyecto
Para empaquetar tu app de Next.js en un contenedor móvil nativo, sigue estos pasos:
- Instala Capacitor core y CLI:
bun add @capacitor/core
bun add -D @capacitor/cli
- Instala los plugins de Capacitor más comunes que probablemente necesites:
bun add @capacitor/app @capacitor/keyboard @capacitor/splash-screen @capacitor/preferences
Estos plugins ofrecen funciones esenciales:
- @capacitor/app: Gestionar eventos del ciclo de vida (foreground/background, URLs)
- @capacitor/keyboard: Controlar el comportamiento del teclado en móviles
- @capacitor/splash-screen: Gestionar la splash screen nativa
- @capacitor/preferences: Almacenar datos clave-valor de forma persistente
- Inicializa Capacitor con los detalles de tu proyecto:
bunx cap init my-app com.example.myapp --web-dir out
Reemplazar my-app con el nombre de tu app y com.example.myapp con el ID de tu app (notación de dominio inverso).
- Crea o actualiza el
capacitor.config.tsarchivo con la configuración adecuada:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'out',
plugins: {
SplashScreen: {
launchShowDuration: 2000,
launchAutoHide: true,
androidScaleType: 'CENTER_CROP',
showSpinner: false,
splashFullScreen: true,
splashImmersive: true,
},
},
};
export default config;
- Instala las plataformas nativas:
bun add @capacitor/ios @capacitor/android
- Añade las carpetas de las plataformas nativas:
bunx cap add ios
bunx cap add android
Capacitor creará ios y android carpetas en la raíz de tu proyecto con los proyectos nativos.
Para compilar el proyecto de Android, necesitas Android Studio. Para iOS, necesitas un Mac con Xcode.
- Haz el build y sincroniza tu proyecto:
bun run mobile
Esto ejecuta tu script personalizado que hace el build del proyecto Next.js y sincroniza los archivos estáticos con las plataformas nativas.
Build y despliegue de apps nativas
Para hacer el build y desplegar tu app móvil nativa, sigue estos pasos: Para desarrollar apps de iOS, necesitas tener Xcode instalado, y para apps de Android, necesitas tener Android Studio instalado. Además, si planeas distribuir tu app en la tienda de apps, debes inscribirte en el Apple Developer Program para iOS y en la Google Play Console para Android.
- Abre los proyectos nativos:
Para iOS:
bun run mobile:ios
Para Android:
bun run mobile:android
O directamente con Capacitor CLI:
bunx cap open ios
bunx cap open android
- Build y ejecuta la app:

-
En Android Studio, espera a que el proyecto esté listo y haz clic en el botón “Run” para desplegar la app en un dispositivo conectado o emulador.

-
En Xcode, configura tu cuenta de signing para desplegar la app en un dispositivo real. Si es la primera vez, Xcode te guiará en el proceso (ten en cuenta que debes estar inscrito en el Apple Developer Program). Una vez configurado, haz clic en el botón “Play” para ejecutar la app en tu dispositivo.
¡Felicidades! Has desplegado con éxito tu web app de Next.js en un dispositivo móvil.
Live Reload con Capacitor
Durante el desarrollo, puedes aprovechar el live reloading para ver los cambios al instante en tu móvil. Para activar esta función, sigue estos pasos:
- Busca tu dirección IP local:
-
En macOS, ejecuta el siguiente comando en la terminal:
ipconfig getifaddr en0 -
En Windows, ejecuta:
ipconfigBusca la dirección IPv4 en la salida.
- Actualiza tu
capacitor.config.tspara apuntar a tu servidor de desarrollo:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: 'out',
server: {
url: 'http://YOUR_IP_ADDRESS:3000',
cleartext: true,
},
};
export default config;
Reemplazar YOUR_IP_ADDRESS con tu dirección IP local (ej. 192.168.1.100).
- Aplica los cambios a tu proyecto nativo:
bunx cap copy
El copy el comando copia la carpeta web y los cambios de configuración al proyecto nativo sin actualizar todo el proyecto.
- Reconstruye y ejecuta la app en tu dispositivo usando Android Studio o Xcode.
Ahora, cada vez que hagas cambios en tu app de Next.js, la app móvil se recargará automáticamente para reflejarlos.
Nota: Si instalas nuevos plugins o modificas archivos nativos, tendrás que reconstruir el proyecto nativo, ya que el live reloading solo aplica a cambios en code web.
Uso de Capacitor Plugins
Los plugins de Capacitor te permiten acceder a funciones nativas del dispositivo desde tu app de Next.js. Veamos cómo usar el plugin Share como ejemplo:
- Instala el plugin Share:
bun add @capacitor/share
- Actualiza el
pages/index.jsarchivo para usar el plugin Share:
import Head from 'next/head';
import styles from '../styles/Home.module.css';
import { Share } from '@capacitor/share';
export default function Home() {
const share = async () => {
await Share.share({
title: 'Open Youtube',
text: 'Check new video on youtube',
url: 'https://www.youtube.com',
dialogTitle: 'Share with friends',
});
};
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<h1 className={styles.title}>
Welcome to <a href="https://nextjs.org">Capgo!</a>
</h1>
<p className={styles.description}>
<h2>Cool channel</h2>
<button onClick={() => share()}>Share now!</button>
</p>
</main>
</div>
);
}
- Sincroniza los cambios con el proyecto nativo:
Como mencionamos antes, al instalar nuevos plugins, debemos hacer un sync y luego volver a desplegar la app en nuestro dispositivo. Para ello, ejecuta el siguiente comando:
bun run mobile
O simplemente sincroniza sin reconstruir:
bunx cap sync
- Reconstruye y ejecuta la app en tu dispositivo.
Ahora, al hacer clic en el botón “Share now!”, aparecerá el diálogo nativo de compartir, permitiéndote enviar el contenido a otras apps.
He trabajado durante años con Ionic para crear aplicaciones multiplataforma, pero integrarlo con Next.js es complejo y rara vez vale la pena si ya tienes Tailwind CSS 4.
Para lograr una sensación nativa en una app de Next.js + Capacitor, usa plugins de Capgo en lugar de UI kits solo 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 router de Next.js mantiene el estado de la ruta; el plugin gestiona el chrome nativo.
- @capgo/capacitor-transitions — transiciones de página estilo Ionic y swipe-back desde el borde en iOS en la capa WebView, sin adoptar 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 con desenfoque):
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:
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions/react';
initTransitions({ platform: 'auto' });
Envuelve las páginas enrutadas en cap-router-outlet, cap-page, y cap-content, y llama a setDirection('forward') o setDirection('back') antes router.push() o router.back(). No dupliques los headers o footers web si la navegación nativa ya gestiona esas áreas.
Consulta las guías completas: Uso de @capgo/capacitor-native-navigation y Uso de @capgo/capacitor-transitions.
Safe areas con Tailwind
Para las safe areas del dispositivo 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 styles/globals.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-*) a mano. El proyecto se desarrolla activamente; si falta algo para tu configuración de Next.js, abre un PR en GitHub.
Cómo solucionar problemas de layout en iOS (viewport, safe area y overflow 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 meta tag viewport esté bien aplicada
App Router (app/): export viewport de los app/layout.tsx:
import type { Viewport } from 'next';
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
};
Pages Router (pages/): coloca el meta tag de viewport en pages/_app.tsx, no _document.tsx (Es posible que Next.js no aplique las etiquetas de _document.tsx la forma esperada para el comportamiento del viewport).
Gestiona el safe area de iOS desde un único wrapper raíz
Crea un único app shell y aplica el padding de safe area ahí, no en múltiples componentes anidados:
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);
}
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 usando 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 encargue del safe area:
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'out',
ios: {
contentInset: 'never',
},
};
Combinar el content inset automático de Capacitor con CSS env(safe-area-inset-*) es una causa común de espaciado doble.
Encuentra el elemento que realmente 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 sea posible. 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.
Optimización del rendimiento
Para asegurar el rendimiento óptimo de tu app con Next.js y Capacitor, considera estas buenas prácticas:
- Minimiza el tamaño de la app eliminando assets y dependencias que no uses.
- Optimiza imágenes y otros archivos multimedia para reducir los tiempos de carga.
- Implementa lazy loading en componentes y páginas para mejorar la carga inicial.
- Usa server-side rendering (SSR) con Next.js para mejorar la velocidad de carga y el SEO.
- Aprovecha las optimizaciones nativas de Capacitor, como el caching de la web view y el app bundling.
Conclusión
Has convertido con éxito tu web app de Next.js en apps nativas de iOS y Android usando Capacitor 8. Tu codebase ahora corre de forma nativa en móviles con acceso a las APIs del dispositivo.
Lo que lograste:
- Configuración de Next.js para exportación estática
- Añadido Capacitor 8 con plugins esenciales
- Build y despliegue en simuladores iOS y Android
- Live reload habilitado para desarrollo
- Corrección de errores de layout en iOS (viewport, safe area, overflow)
- UI con sensación nativa con Capgo Native Navigation and Transitions
Próximos pasos:
- Configura Capgo para actualizaciones OTA sin reenviar a la App Store
- Añadir más plugins nativos como Camera, Geolocation o Push Notifications
- Configura los iconos y splash screens para producción
- Prepara tu app para enviarla a App Store y Google Play
¿Empiezas un proyecto desde cero? Echa un vistazo a Cómo crear una app móvil con Next.js desde cero para un tutorial paso a paso.
Recursos
- Documentación de Next.js
- @capgo/capacitor-native-navigation — Barra de pestañas Liquid Glass y chrome nativo
- Documentación de Capacitor 8
- @capgo/capacitor-transitions — transiciones de página con estilo nativo
- @capgo/tailwind-capacitor — Utilidades safe-area de Tailwind para Capacitor
- Capgo - Live Updates para apps de Capacitor
Descubre cómo Capgo puede ayudarte a crear mejores apps más rápido: crea una cuenta gratis hoy.
Continúa desde Convertir tu app de Next.js a iOS y Android con Capacitor 8
Si estás usando Convierte tu app de Next.js a iOS y Android con Capacitor 8 para planificar el trabajo con plugins nativos, conéctalo con Directorio de plugins de Capgo para el flujo de trabajo del producto en Capgo Plugin Directory, Plugins de Capacitor por Capgo para el detalle de implementación en los Plugins de Capacitor por Capgo, Añadir o actualizar plugins para el detalle de implementación en Agregar o actualizar plugins, Alternativas a plugins de Ionic Enterprise para el flujo de trabajo en Alternativas a plugins de Ionic Enterprise, y Native Builds de Capgo para el flujo de trabajo del producto en Capgo Native Builds.