En este tutorial aprenderás a crear una app móvil usando React y Capacitor. Al terminar, sabrás cómo transformar una web app de React.js en una app móvil nativa con Capacitor, y cómo darle un toque nativo con Capgo Native Navigation and Transitions.
Capacitor permite transformar fácilmente tu web app de React.js en una app móvil nativa, sin necesidad de cambios sustanciales ni de aprender nuevas estrategias como React Native.
El proceso consta de unos pocos pasos sencillos y, antes de que te des cuenta, tu app de React.js será una aplicación móvil totalmente funcional. Quédate con nosotros mientras te guiamos en este proceso.
Resumen de Capacitor
CapacitorJS cambia las reglas del juego. Se integra sin problemas con cualquier proyecto web y envuelve tu app en una webview nativa mientras genera los proyectos de Xcode y Android Studio. Además, mediante sus plugins, puedes acceder a funciones nativas del dispositivo, como la cámara, a través de un bridge de JS.
Capacitor ofrece una forma directa de crear una aplicación móvil nativa sin complicaciones ni curvas de aprendizaje pronunciadas. Su API sencillo y su funcionalidad optimizada facilitan su incorporación a tu proyecto.
Configuración de tu app de React.js
Vamos a usar el método más simple para iniciar una aplicación React. Usaremos el gestor de paquetes npm para crear una nueva app de React:
npx create-react-app my-app
Para transformar nuestro proyecto en una app móvil nativa, se requiere un export de nuestra app es necesario.
Volveremos a esto en un momento. Primero, entendamos cómo integrar Capacitor en nuestra app de React.
Integración de Capacitor en tu app React.js
Los pasos de configuración inicial pueden ser algo detallados, pero después de eso, actualizar el wrapper nativo de tu app será tan simple como ejecutar un sync comando.
Primero, instalaremos el CLI de Capacitor como una dependencia de desarrollo y lo configuraremos en nuestro proyecto. Durante la configuración, acepta los valores por defecto para el nombre y el bundle ID pulsando "enter".
A continuación, instalaremos el paquete core y los paquetes necesarios para iOS y Android.
Por último, añadiremos las plataformas y Capacitor creará las carpetas de cada una en la raíz del proyecto:
# Install the Capacitor CLI locally
npm install -D @capacitor/cli
# Initialize Capacitor in your React 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
El ios y Android los directorios ya están presentes en tu proyecto de React.js.
Para acceder al proyecto de Android más tarde, instala Android Studio. Para iOS, necesitas un Mac y deberías instalar Xcode.
Luego, actualiza el webDir en tu capacitor.config.json archivo como se muestra abajo:
{
"appId": "com.example.app",
"appName": "my-app",
"webDir": "build",
"bundledWebRuntime": false
}
Ejecuta el comando de build y sincroniza tu proyecto con Capacitor:
npm run build
npx cap sync
El npm run build el comando compilará tu proyecto de React.js, mientras que npx cap sync alineará el code web en los lugares correctos de las plataformas nativas para que se ejecuten en una app.
¡Ahora, con un poco de suerte y sin errores, tu app de React.js debería estar lista para lanzarse en un dispositivo!
Build y despliegue de tus apps nativas
Desarrollar apps para iOS requiere Xcode, y las apps de Android requieren Android Studio. Si planeas distribuir tu app en las tiendas, debes inscribirte en el Apple Developer Program para iOS y en Google Play Console para Android.
El Capacitor CLI simplifica el proceso de abrir ambos proyectos nativos:
npx cap open ios
npx cap open android
Una vez configurados tus proyectos nativos, desplegar tu app en un dispositivo conectado es un proceso sencillo.
En Android Studio, espera a que todo cargue y luego despliega tu app en un dispositivo conectado.
En Xcode, configura tu cuenta de signing para desplegar la app en un dispositivo real en lugar de usar solo el simulador. Tras esto, solo dale a play para ejecutar la app en el dispositivo conectado que elijas arriba.
Si todo ha salido bien, ¡habrás convertido tu web app de React.js en una aplicación móvil nativa!
Live Reload con Capacitor
Los frameworks de desarrollo modernos suelen incluir hot reload, y por suerte, puedes tener lo mismo con Capacitor pero en tu dispositivo móvil!
Puedes hacer que tu aplicación local sea accesible mediante live reload en tu red, haciendo que la app Capacitor cargue el contenido desde una URL específica.
Primero, determina tu dirección IP local. En un Mac, puedes hacerlo ejecutando ipconfig getifaddr en0 en la terminal. En Windows, ejecuta ipconfig y busca la dirección IPv4.
Después, indica a Capacitor que cargue la app directamente desde el servidor añadiendo otro parámetro a tu capacitor.config.ts archivo:
import { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.app',
appName: 'my-app',
webDir: 'build',
bundledWebRuntime: false,
server: {
url: 'http://192.168.x.xx:3000',
cleartext: true
}
};
export default config;
Asegúrate de usar la IP y el puerto correctos. Ejecuta npx cap copy para aplicar estos cambios a nuestro proyecto nativo.
¡Al desplegar tu app una vez más mediante Android Studio o Xcode, cualquier cambio en tu app de React se recargará y se mostrará automáticamente en tu app!
Ten en cuenta que si instalas nuevos plugins, como la cámara, será necesario hacer un rebuild de tu proyecto nativo. Esto se debe a que los archivos nativos habrán cambiado y no pueden actualizarse sobre la marcha.
Uso de plugins de Capacitor
Echemos un vistazo rápido a cómo usar un plugin de Capacitor. Instalemos uno sencillo, el Plugin de compartir, lo que abre el diálogo nativo de compartir:
npm i @capacitor/share
Para usarlo, importa el paquete y llama a la share() función de nuestra app. Considera el App.js:
import { Share } from '@capacitor/share';
function ShareButton() {
const share = async () => {
await Share.share({
title: 'React App',
text: 'Visit this React App',
url: 'http://localhost:3000',
dialogTitle: 'Share with...'
});
};
return (
<button onClick={share}>
Share
</button>
);
}
export default ShareButton;
Tras instalar un nuevo plugin, recuerda sincronizar tu proyecto React de nuevo usando 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 React es complejo y rara vez vale la pena si ya tienes Tailwind CSS.
Para una sensación nativa en una app de React + 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 React router mantiene el estado de la ruta; el plugin gestiona 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 }) => {
navigate(`/${id}`);
});
Añade transiciones de página nativas en tu app shell:
import { useEffect, useRef } from 'react';
import { useNavigate } from 'react-router-dom';
import '@capgo/capacitor-transitions';
import { initTransitions, setDirection, setupRouterOutlet } from '@capgo/capacitor-transitions/react';
initTransitions({ platform: 'auto' });
export function AppShell() {
const navigate = useNavigate();
const outletRef = useRef<HTMLElement>(null);
useEffect(() => {
if (outletRef.current) {
setupRouterOutlet(outletRef.current, { platform: 'auto', swipeGesture: 'auto' });
}
}, []);
const openSettings = () => {
setDirection('forward');
navigate('/settings');
};
return <cap-router-outlet ref={outletRef}>{/* routes */}</cap-router-outlet>;
}
Envuelve las páginas enrutadas en cap-router-outlet, cap-page, y cap-content, y llama setDirection('forward') o setDirection('back') antes de navegar. No dupliques los headers o footers web cuando la navegación nativa ya gestione esas superficies.
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/index.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 está en desarrollo activo; si falta algo para tu setup de React, 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 la etiqueta meta 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,
#root {
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: 'build',
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 ofrece una forma fluida de crear apps nativas basadas en un proyecto web existente, permitiendo compartir code y mantener una UI consistente.
Gracias a tecnologías como Capacitor, crear apps móviles desde web apps en React.js nunca ha sido tan fácil. Lleva tus habilidades de desarrollo web al siguiente nivel creando apps nativas impresionantes. ¡A programar!
Para saber más sobre cómo acelerar tu proceso de desarrollo de apps, regístrate para obtener una cuenta gratis hoy mismo.
Continúa desde Crear apps móviles con React.js puro y Capacitor
Si estás usando Crear apps móviles con React.js puro 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 el detalle de implementación en @capgo/capacitor-live-activities, Uso de @capgo/capacitor-video-player para la funcionalidad nativa en el uso de @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.