Introducción
¿Quieres crear una aplicación móvil con Next.js desde cero? Este guía te guía a través de la creación de un proyecto de Next.js 15 completamente nuevo configurado para móviles desde el primer día, luego empaquetándolo como aplicaciones nativas de iOS y Android Capacitor 8.
Al finalizar esta tutoría, tendrás una aplicación móvil funcionando 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 Next.js 15 con App Router
- Configuración de exportación estática para móviles
- Capacitor 8 con plugins esenciales
- Aplicaciones nativas de iOS y Android
- Configuración de desarrollo con live reload
Ya tienes una aplicación de Next.js? Revisa Convierte tu aplicación de Next.js a móvil en su lugar.
Requisitos previos
Asegúrate de tener 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 de Next.js
Comience creando un proyecto de Next.js 15 fresco:
bunx create-next-app@latest my-mobile-app
Cuando se le solicite, seleccione estas opciones:
- TypeScript: Sí (recomendado)
- ESLint: Sí
- Tailwind CSS: Sí (recomendado para el estilo móvil)
src/carpeta: Sí- Ruta de la aplicación: Sí (recomendado)
- Importar alias: Predeterminado (
@/*)
Navegue a su proyecto:
cd my-mobile-app
Paso 2: Configure Next.js para exportación estática
Capacitor requiere archivos HTML/JS/CSS estáticos. Configure Next.js para exportación estática actualizando next.config.ts:
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
output: 'export',
images: {
unoptimized: true,
},
// Ensure trailing slashes for proper routing in Capacitor
trailingSlash: true,
};
export default nextConfig;
¿Por qué estos ajustes?
output: 'export'— Genera HTML estático en lugar de requerir un servidor Node.jsimages: { unoptimized: true }— Desactiva la Optimización de imágenes de Next.js (requiere un servidor)trailingSlash: true— Asegura la ruta correcta en la vista previa nativa
Paso 3: Agregar scripts móviles
Actualice su package.json con scripts de desarrollo móvil:
{
"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"
}
}
Pruebe la compilación:
bun run build
Debería ver un out directorio con sus archivos estáticos.
Paso 4: Instale Capacitor 8
Instale los paquetes de core de Capacitor:
bun add @capacitor/core
bun add -D @capacitor/cli
Instale 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 — Control el comportamiento del teclado
- @capacitor/pantalla-de-bienvenida — Control de pantalla de bienvenida 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 out
Sustituye:
"My Mobile App"por el nombre de pantalla de tu aplicacióncom.example.mymobileapppor el ID de tu aplicación (notación de dominio inverso)
Esto crea capacitor.config.ts. Actualice la configuración del plugin:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.mymobileapp',
appName: 'My Mobile App',
webDir: 'out',
plugins: {
SplashScreen: {
launchShowDuration: 2000,
launchAutoHide: true,
androidScaleType: 'CENTER_CROP',
splashFullScreen: true,
splashImmersive: true,
},
Keyboard: {
resize: 'body',
resizeOnFullScreen: true,
},
StatusBar: {
style: 'light',
},
},
};
export default config;
Paso 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.
Paso 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):
- Seleccione un simulador desde el menú de dispositivos
- Haga clic en el botón de reproducción o presione
Cmd + R
En Android Studio:
- Espere a que Gradle termine de sincronizar
- Seleccione un emulador desde el menú de dispositivos
- 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 reproducción en vivo para que los cambios aparezcan instantáneamente en su dispositivo.
- Encuentre su dirección IP local:
# macOS
ipconfig getifaddr en0
# Windows
ipconfig
- Cree una configuración de desarrollo Capacitor. Agregue a
capacitor.config.ts:
import type { CapacitorConfig } from '@capacitor/cli';
const devConfig: CapacitorConfig = {
appId: 'com.example.mymobileapp',
appName: 'My Mobile App',
webDir: 'out',
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: 'out',
plugins: {
// ... same plugin config
},
};
const config = process.env.NODE_ENV === 'development' ? devConfig : prodConfig;
export default config;
- Inicie el servidor de desarrollo y copie la configuración a nativo:
bun run dev &
NODE_ENV=development bunx cap copy
- Reconstruye en Xcode/Android Studio
Ahora los cambios en tu Next.js code se recargarán automáticamente en el dispositivo.
Paso 9: Crea tu primera pantalla móvil
Vamos a crear una pantalla de inicio simple y amigable para móviles. Actualiza src/app/page.tsx:
'use client';
import { useEffect, useState } from 'react';
import { App } from '@capacitor/app';
import { Keyboard } from '@capacitor/keyboard';
export default function Home() {
const [appInfo, setAppInfo] = useState<{ name: string; version: string } | null>(null);
useEffect(() => {
// Get app info on mount
App.getInfo().then(setAppInfo).catch(console.error);
// Handle back button on Android
const backHandler = App.addListener('backButton', ({ canGoBack }) => {
if (!canGoBack) {
App.exitApp();
} else {
window.history.back();
}
});
// Hide keyboard when tapping outside inputs
const keyboardHandler = Keyboard.addListener('keyboardWillShow', () => {
document.body.classList.add('keyboard-open');
});
return () => {
backHandler.then(h => h.remove());
keyboardHandler.then(h => h.remove());
};
}, []);
return (
<main className="min-h-screen bg-linear-to-b from-blue-500 to-blue-700 flex flex-col items-center justify-center p-6 text-white">
<h1 className="text-4xl font-bold mb-4">My Mobile App</h1>
<p className="text-xl mb-8 text-center opacity-90">
Built with Next.js 15 + Capacitor 8
</p>
{appInfo && (
<div className="bg-white/20 rounded-lg p-4 backdrop-blur-sm">
<p className="text-sm">
{appInfo.name} v{appInfo.version}
</p>
</div>
)}
<div className="mt-12 space-y-4 w-full max-w-sm">
<button className="w-full py-4 px-6 bg-white text-blue-600 rounded-xl font-semibold text-lg shadow-lg active:scale-95 transition-transform">
Get Started
</button>
<button className="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">
Learn More
</button>
</div>
</main>
);
}
Paso 10: Agrega manejo de área segura
Los dispositivos móviles tienen notificaciones, indicadores de inicio y barras de estado. Agrega manejo de área segura con Tailwind. Actualiza
Estructura del Proyecto src/app/globals.css:
@tailwind base;
@tailwind components;
@tailwind utilities;
: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;
}
/* Keyboard handling */
.keyboard-open {
--sab: 0px;
}
Tu proyecto debería verse así:
Pasos siguientes
my-mobile-app/
├── android/ # Android native project
├── ios/ # iOS native project
├── out/ # Static build output
├── src/
│ ├── app/
│ │ ├── globals.css
│ │ ├── layout.tsx
│ │ └── page.tsx
│ └── ...
├── capacitor.config.ts # Capacitor configuration
├── next.config.ts # Next.js configuration
├── package.json
└── ...
Ahora tienes una aplicación móvil de Next.js funcionando. Aquí te decimos qué hacer a continuación:
Configuración básica
Configuración básica
- Íconos de la Aplicación: Sustituye los íconos predeterminados en
ios/App/App/Assets.xcassetsyandroid/app/src/main/res - Pantalla de Inicio: Personaliza en proyectos nativos o utiliza
@capacitor/splash-screenconfig - 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 Push:
bun add @capacitor/push-notifications - Sistema de archivos:
bun add @capacitor/filesystem
Interfaz de usuario nativa y transiciones
Utilice los plugins Capgo en lugar de Konsta UI para un sentir móvil nativo:
- @capgo/capacitor-navegación-nativa — Barra de pestañas de vidrio líquido y barra de navegación nativa
- @capgo/capacitor-transiciones — Transiciones de página con un sentir 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
Ver Usando @capgo/capacitor-navegación-nativa, Usando @capgo/capacitor-transiciones, y el repo de tailwind-capacitor para la configuración específica de Next.js.
Solucionar Problemas de Diseño en iOS (Viewport, Á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 viewport sola no suele solucionar el problema. Pase por estos controles en orden.
Asegúrese de que la etiqueta meta de viewport se aplique correctamente
App Router (app/exportar viewport desde app/layout.tsx:
import type { Viewport } from 'next';
export const viewport: Viewport = {
width: 'device-width',
initialScale: 1,
viewportFit: 'cover',
};
Pages Router (pages/ponga la etiqueta meta de viewport en pages/_app.tsx, no _document.tsx.
Gestione el área segura de iOS desde un solo envoltorio raíz
Cree un concha de aplicación única y aplique allí el relleno de área segura — 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);
}
Envuelva todo el contenido de la página dentro de .app-shellEl relleno de área segura duplicado en encabezados, modales y envoltorios de diseño a menudo hace que la interfaz de usuario se vea recortada o demasiado grande.
Con @capgo/tailwind-capacitor, puede expresar el mismo relleno con utilidades como pt-safe pb-safe px-safe en esa concha única.
Establezca Capacitor iOS contentInset a never primero
En capacitor.config.ts, prefiera el área de inserción nativa deshabilitada y deja que CSS (o la navegación nativa) tenga el área de seguridad: contentInsetMode: 'css'Mezclar el área de inserción automática de __CAPGO_KEEP_0__ con CSS
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'my-app',
webDir: 'out',
ios: {
contentInset: 'never',
},
};
Mixing Capacitor’s automatic content inset with CSS env(safe-area-inset-*) Encuentra el elemento que está desbordando en realidad
El culpable usual es un elemento que utiliza
, Tailwind 100vw, una anchura de píxeles fija o un ancho muy grande w-screenEn Safari Web Inspector, ejecuta: min-width.
Con Tailwind, reemplaza
[...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 w-screen Con w-full cuando sea posible. Muchos problemas de rebosamiento horizontal provienen de 100vw / w-screenduplicado relleno de zona segura, o un contenedor de ancho fijo — no del meta etiqueta de viewport en sí.
Actualizaciones por Vía Aérea
Configuración Capgo para enviar actualizaciones sin la 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”
Ejecutar bun install y vuelve a intentarlo.
iOS: “No se encontró identidad de firma” Abre Xcode, ve a Signing & Capabilities, y selecciona tu equipo de desarrollo.
Android: “SDK ubicación no encontrada”
Crear android/local.properties con sdk.dir=/path/to/android/sdk
Los cambios no aparecen en el dispositivo
Asegúrese de haber ejecutado bun run mobile después de hacer cambios. Para el recarga en vivo, verifique que la dirección IP es correcta y el servidor de desarrollo está en ejecución.
Recursos
- Capacitor 8 Documentación
- Documentación de Next.js 15
- Capgo - Actualizaciones en vivo
- @capgo/capacitor-navegación nativa
- @capgo/capacitor-transiciones
- @capgo/tailwind-capacitor
¿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 Construye una aplicación móvil de Next.js desde cero con Capacitor 8
Si estás utilizando Construye una aplicación móvil de Next.js 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 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 el detalle de implementación en Integración CI/CD, y GitHub Acciones de Integración para el detalle de implementación en GitHub Acciones de Integración.