Para publicar una web app en App Store y Google Play, envuelve tu web app compilada en un proyecto nativo con Capacitor, añade algunas funcionalidades nativas, crea cuentas de desarrollador de Apple y Google, firma y compila los binarios de iOS y Android, haz testing con usuarios reales, prepara las fichas de las tiendas y envíalas a revisión. Tu HTML, CSS y JavaScript actuales siguen ejecutándose dentro de un WebView nativo, así que no tienes que reescribir la app.
A continuación tienes los 11 pasos en el orden que evita esperas, con comandos para Capacitor 8 y las normas de las tiendas vigentes en octubre de 2026.
Qué necesitas
- Una web app que compila a archivos estáticos (React, Vue, Angular, Svelte, Next.js static export, Nuxt generate, HTML puro, o una app hecha con un AI builder como Lovable o Bolt).
- Node.js 22 o superior (requisito de Capacitor 8) y Bun u otro gestor de paquetes.
- Android Studio para builds de Android.
- Xcode 26 en macOS para builds de iOS, o un servicio de build en la nube si no tienes un Mac.
- 99 USD al año para Apple y 25 USD una vez para Google.
Plazos realistas
| Fase | Tiempo típico | ¿Se puede ejecutar en paralelo? |
|---|---|---|
| Inscripción de cuenta de desarrollador | Horas (individual) a 2 semanas (organización con D-U-N-S nuevo) | Sí, empieza desde el primer día |
| Capacitor setup and first device run | 1 día | |
| Pulido de la app y funciones nativas | De 3 días a 3 semanas | |
| Firma y primeros builds | 1 día | |
| Prueba cerrada en Google Play (nuevas cuentas personales) | Mínimo 14 días, luego revisión de acceso a producción | Sí, con iOS TestFlight |
| Ficha de la tienda | De 1 a 2 días | Sí |
| Revisión de la app | Apple suele tardar de 1 a 2 días; Google, desde horas hasta varios días |
Paso 1: Empieza hoy el registro de tu cuenta de desarrollador
La verificación de la cuenta es el paso que no puedes acelerar, así que hazla antes de programar.
- Apple Developer Program: 99 USD al año. Los desarrolladores individuales necesitan una Apple Account con autenticación de dos factores y su nombre legal. Las organizaciones también necesitan un número D-U-N-S, un sitio web corporativo y un email de trabajo en ese dominio.
- Google Play Console: 25 USD una vez. Las organizaciones necesitan un número D-U-N-S. Habrá verificación de identidad.
Si te registras en Google Play como individuo, tu cuenta estará sujeta a la regla de pruebas cerradas (Paso 9). Guía completa: cómo crear cuentas de desarrollador en Apple y Google Play.
Paso 2: Prepara la web app para el móvil
Capacitor ejecuta tu app en un WebView. Cosas que en una pestaña del navegador van bien, en una app se sienten raras:
- El output de un build estático. Capacitor carga archivos desde el app bundle. El server-side rendering no se ejecuta en el teléfono. Usa el output estático de tu framework (
next buildconoutput: 'export',nuxt generate, Vitebuild). Las llamadas de API van a tu backend por HTTPS como antes. - Client-side routing que funcione desde un origen de archivo. Usa history routing (Capacitor sirve la app desde
https://localhosten Android ycapacitor://localhosten iOS, así que funciona) y asegúrate de que las deep URLs hagan fallback aindex.html. - CORS. Añade los orígenes de Capacitor a los orígenes permitidos de tu API:
capacitor://localhost(iOS) yhttps://localhost(Android). - Toca, no hover. Elimina los menús que dependen del hover. Haz que los tap targets midan al menos 44 x 44 puntos.
- Áreas seguras. Añadir
viewport-fit=covera la meta tag viewport y añade padding a los headers y barras inferiores conenv(safe-area-inset-top)yenv(safe-area-inset-bottom). - Offline y redes lentas. Muestra un estado adecuado en lugar de una pantalla en blanco. Los revisores prueban con Wi-Fi inestable.
- Sin banners de “descarga nuestra app” y sin enlaces que manden a los usuarios a tu web para hacer tareas clave.
<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover" />
Paso 3: Añadir Capacitor
Desde la raíz de tu proyecto web:
bun add @capacitor/core
bun add -d @capacitor/cli
bunx cap init "My App" com.example.myapp --web-dir dist
bun add @capacitor/ios @capacitor/android
bun run build
bunx cap add ios
bunx cap add android
Usa la carpeta de salida real para --web-dir: dist si usas Vite, out para el export estático de Next.js, .output/public para el generate de Nuxt, build para Create React App, dist/<project>/browser para Angular.
El bundle ID (com.example.myapp) es permanente una vez que la app esté en las tiendas. Usa un dominio inverso que controles.
Tu capacitor.config.ts ahora se ve así:
import type { CapacitorConfig } from '@capacitor/cli';
const config: CapacitorConfig = {
appId: 'com.example.myapp',
appName: 'My App',
webDir: 'dist',
};
export default config;
Capacitor 8 crea el proyecto iOS con Swift Package Manager por defecto, así que no necesitas CocoaPods. Cada vez que cambies el code web:
bun run build
bunx cap sync
Ejecútalo:
bunx cap run ios
bunx cap run android
Haz commit de las ios/ y android/ carpetas. Son code fuente que editarás (permisos, iconos, firma). Para más contexto, consulta lo fácil que es convertir una web app en una app móvil con Capacitor, y si usaste una herramienta de IA, nuestra guía de Lovable a móvil.
Paso 4: Añade funciones nativas que justifiquen una app
La directriz 4.2 de Apple (Funcionalidad mínima) rechaza las apps que son solo un sitio web en un shell. No necesitas decenas de funciones nativas, pero la app debe comportarse como una app. Añadidos comunes y útiles:
| Característica | Plugin |
|---|---|
| Notificaciones push | @capacitor/push-notifications |
| Inicio de sesión nativo de Google, Apple y Facebook | @capgo/capacitor-social-login |
| Desbloqueo con Face ID / huella dactilar | @capgo/capacitor-native-biometric |
| Cámara y fotos | @capacitor/camera |
| Compras in-app y suscripciones | @capgo/capacitor-native-purchases |
| Hoja de compartir nativa | @capacitor/share |
| Hápticos | @capacitor/haptics |
| Barra de estado y splash screen | @capacitor/status-bar, @capacitor/splash-screen |
| Solicitud para calificar la app | @capgo/capacitor-in-app-review |
| Actualizaciones en vivo | @capgo/capacitor-updater |
Ejemplo: mostrar la hoja de compartir nativa en lugar de un botón de «copiar enlace».
import { Share } from '@capacitor/share';
import { Capacitor } from '@capacitor/core';
export async function shareLink(url: string, title: string) {
if (Capacitor.isNativePlatform()) {
await Share.share({ title, url });
} else {
await navigator.clipboard.writeText(url);
}
}
Si vendes contenido digital o suscripciones, planifica los pagos ahora. Apple y Google exigen sus sistemas de compra in-app para bienes digitales en la mayoría de los casos. En la App Store de EE. UU., las aplicaciones también pueden enlazar a un checkout web externo tras la sentencia judicial de 2025; otras regiones tienen sus propias reglas. Los bienes y servicios físicos (entregas, viajes) pueden usar Stripe o cualquier proveedor de pagos. Ver compras in-app con Capacitor.
El catálogo completo de plugins de Capgo está en la página de plugins.
Paso 5: Iconos, splash screen y strings de permisos
Genera todos los tamaños de iconos y splash a partir de dos imágenes:
bun add -d @capacitor/assets
# assets/icon.png 1024x1024, assets/splash.png 2732x2732
bunx capacitor-assets generate
En iOS, cada permiso que uses necesita una descripción de uso en ios/App/App/Info.plist, o la app se bloquea al pedirlo y Apple la rechaza:
<key>NSCameraUsageDescription</key>
<string>Take a photo of your receipt to attach it to an expense.</string>
<key>NSPhotoLibraryUsageDescription</key>
<string>Choose receipt photos from your library.</string>
Escribe razones específicas. “Esta app necesita la cámara” te la rechazan.
En Android, los plugins añaden la mayoría de permisos al manifest por sí mismos. Elimina los que no uses; Google te pedirá justificar los sensibles.
También añade un manifiesto de privacidad (PrivacyInfo.xcprivacy) si tu code usa APIs de motivo requerido. Consulta la guía de privacy manifest para apps de iOS.
Paso 6: Configurar la firma
iOS. Necesitas un certificado de distribución de Apple (con su clave privada, que normalmente se exporta como .p12) y un perfil de aprovisionamiento de App Store Connect para tu bundle ID. Xcode puede crearlos automáticamente, o puedes crearlos tú mismo, incluso sin Mac. Lee Certificados de iOS y perfiles de aprovisionamiento explicados; el generador de certificados iOS gestiona el paso del CSR en el navegador.
Android. Crea un keystore de upload y mantén una copia de seguridad. Google Play usa Play App Signing, así que Google conserva la clave de firma final de la app y tú firmas los uploads con la tuya.
keytool -genkeypair -v -keystore upload-keystore.jks -alias upload \
-keyalg RSA -keysize 2048 -validity 10000
O usa el Generador de keystore para Android.
Paso 7: Compilar los binarios de release
Localmente
iOS (en un Mac con Xcode 26, necesario para subir apps a la App Store desde abril de 2026):
bunx cap open ios- Selecciona el app target, establece la versión y el build number, y elige tu equipo en Signing & Capabilities.
- Elige Cualquier dispositivo iOS (arm64), luego Producto > Archivo.
- En el Organizer, Distribuir App > App Store Connect > Upload.
Android:
bun run build
bunx cap sync android
cd android
./gradlew bundleRelease
El AAB está en android/app/build/outputs/bundle/release/. Configura signingConfigs en android/app/build.gradle con tu keystore, cargando las contraseñas desde variables de entorno.
Asegúrate de que targetSdkVersion es 36. Desde el 31 de agosto de 2026, Google Play exige que las nuevas apps y actualizaciones apunten a Android 16 (API 36), que es el Capacitor 8 predeterminado.
En la nube
Si no tienes un Mac o quieres builds reproducibles desde CI, Build de Capgo compila ambas plataformas en máquinas alojadas y puede subir directamente a TestFlight y Google Play:
bunx @capgo/cli@latest build credentials save --appId com.example.myapp --platform ios
bunx @capgo/cli@latest build credentials save --appId com.example.myapp --platform android
bunx @capgo/cli@latest build request com.example.myapp --platform ios --path .
bunx @capgo/cli@latest build request com.example.myapp --platform android --path .
Las credenciales se usan solo para el build y no se almacenan en los servidores de Capgo. Consulta la Docs de Build de Capgo.
Paso 8: Distribuir a testers
Pon el build en teléfonos reales antes de que Apple o Google lo vean.
- iOS: sube a TestFlight. Los testers internos (hasta 100 miembros del equipo) lo reciben justo después del procesamiento; los externos (hasta 10.000) tras una breve revisión de la app beta.
- Android: crea una release de prueba interna en Play Console y comparte el enlace de opt-in.
Prueba el registro e inicio de sesión, los pagos en sandbox, las notificaciones push, el comportamiento sin conexión, que el teclado cubra los inputs y el comportamiento del botón de atrás en Android. Detalles de cada opción: cómo distribuir apps de iOS y Android a testers.
Paso 9: Ejecutar el test cerrado de Google Play (cuentas personales nuevas)
Si tu cuenta de Play es personal y se creó después del 13 de noviembre de 2023, no puedes publicar en producción hasta haber hecho un test cerrado con al menos 12 testers inscritos durante 14 días consecutivos. Luego solicitas acceso a producción en el dashboard de Play Console, que Google suele revisar en una semana.
Empieza esto en cuanto tengas un build de Android usable. Usa un Google Group como lista de testers para que la gente pueda unirse por su cuenta. Publica actualizaciones durante los 14 días y recopila feedback, ya que Google pregunta qué aprendiste. Las cuentas de organización están exentas.
Paso 10: Preparar las fichas de las tiendas y enviar
Para ambas tiendas necesitas: nombre de la app, descripciones, capturas de pantalla en los tamaños aceptados, icono, URL de la política de privacidad, declaraciones de privacidad (Apple App Privacy y Google Data safety), cuestionario de clasificación por edad, contacto de soporte y una cuenta de demo si la app tiene login. Google también necesita un feature graphic de 1024 x 500. Especificaciones y límites: cómo preparar tu listing en App Store y Google Play.
Envío en iOS: en App Store Connect, crea la versión, selecciona el build de TestFlight, rellena la App Review Information (cuenta de demo, notas) y haz clic en Añadir para revisión, luego Enviar.
Envío en Android: crea un release de producción con el AAB (o promociona el ya probado desde un track de pruebas), completa cada Contenido de la app declaración, selecciona los países y envíalo a revisión.
Los motivos de rechazo más comunes en web apps:
- 4.2 Funcionalidad mínima: la app es solo tu sitio web. Añade valor nativo y elimina la UI tipo navegador.
- Login requerido pero sin cuenta demo, o la cuenta no funciona.
- Sin opción de login enfocada en privacidad al ofrecer login con Google o Facebook en iOS. La directriz 4.8 exige una opción equivalente que limite la recopilación de datos; Sign in with Apple es la opción habitual.
- Sin opción de eliminar cuenta dentro de la app cuando los usuarios pueden crear cuentas.
- Compras digitales a través de Stripe donde se requiere la compra in-app.
- Layout de iPad roto porque el proyecto soporta iPad por defecto.
- Strings de permisos faltantes o vagos.
Nuestro guía para la primera revisión de la app y guía de envío de apps para iOS analizar cada una en detalle.
Paso 11: Publicar updates sin esperar revisión
Tras el lanzamiento, la mayoría de tus cambios seguirán en el web code. En lugar de crear un nuevo build de la tienda para cada corrección, añade live updates. El updater de Capgo descarga nuevos bundles web desde Capgo y los aplica en el siguiente arranque, con rollback automático si el nuevo bundle falla al iniciar.
bun add @capgo/capacitor-updater
bunx cap sync
bunx @capgo/cli@latest init
Llama a notifyAppReady() cuando tu app ha iniciado, para que el updater sepa que el bundle es estable:
import { CapacitorUpdater } from '@capgo/capacitor-updater';
CapacitorUpdater.notifyAppReady();
Entonces, cada release de web code es un solo comando:
bun run build
bunx @capgo/cli@latest bundle upload --channel production
Ambas tiendas lo permiten para code interpretado, siempre que la actualización no cambie el propósito principal de la app ni eluda sus reglas de pago. Los cambios nativos (nuevos plugins, nuevos permisos, upgrades de Capacitor) siguen pasando por las tiendas. Lee más en actualizaciones Live Update de Capgo y la docs del updater.
Añade el plugin antes de tu primer envío a la tienda. Debe estar en el binario que instalan los usuarios; de lo contrario, tu primer live update solo llegará a los usuarios tras una segunda release en la tienda.
Finalmente, automatiza: compila y sube en cada tag desde GitHub Actions o GitLab CI, y publica actualizaciones en vivo en cada merge a main, y reserva las versiones nativas para cambios nativos.
Checklist de prelanzamiento
- Cuentas de Apple y Google aprobadas, acuerdos aceptados
- La app funciona offline o muestra un estado offline claro
- Safe areas, teclado y botón atrás de Android gestionados
- Al menos algunas funciones nativas que una web no puede ofrecer
- Iconos, splash, textos de permisos, privacy manifest
- Certificado de distribución, perfil de App Store y keystore de upload respaldados
- Target SDK 36 en Android, compilado con Xcode 26 en iOS
- TestFlight y pruebas internas de Play realizadas en dispositivos reales
- Prueba cerrada de Google Play finalizada (cuentas personales)
- Fichas completas en ambas tiendas, cuenta demo añadida
- Eliminación de cuenta in-app si los usuarios pueden registrarse
- Plugin de Live Updates incluido en el primer binario
Solución de problemas
Pantalla blanca al iniciar. webDir apunta a la carpeta incorrecta o te olvidaste bunx cap sync después del build. Revisa ios/App/App/public y android/app/src/main/assets/public contienen index.html.
las llamadas a API fallan solo en la app. CORS: permite capacitor://localhost y https://localhost. También verifica que no estés llamando a http:// URLs, que iOS bloquea por defecto.
Las rutas dan 404 tras refresh o deep link. Usa un router con fallback a index.html, o hash routing para configuraciones antiguas.
Errores de firma en Xcode. Consulta la lista de errores en Certificados de iOS y perfiles de aprovisionamiento explicados.
Fallo en el build de Gradle tras actualizar. Capacitor 8 requiere Android Studio Otter (2025.2.1) o superior y JDK 21, como se indica en guía de actualización de Capacitor 8. Para otros errores de Gradle, consulta cómo resolver errores de build de Android en Capacitor.
Subida a Google Play rechazada para el target SDK. Configurar targetSdkVersion = 36 en android/variables.gradle.