Saltar al contenido
WebViewGold Del vibe coding a la App Store
Español
Consigue WebViewGold

Claude Code + push

Añade notificaciones push de OneSignal a una app web de Claude Code con WebViewGold

El push es la función nativa que los revisores notan primero y la que los usuarios realmente mantienen activada. Con WebViewGold, OneSignal se ejecuta dentro del envoltorio nativo; tu app web solo decide cuándo pedir permiso, a qué usuario pertenece un dispositivo y qué pantalla abre una notificación. Claude Code puede escribir todo eso en una sola sesión, y esta guía te da el prompt, el código del servidor y el plan de pruebas.

Desde $109 de pago único por plataforma, o deja que nuestro equipo lo haga todo desde $698.

  • Garantía de aprobación – o te devolvemos el dinero en 14 días
  • Sin programar
  • Pago único, actualizaciones gratuitas
  • Soporte humano 24/7
  • Hecho en Alemania desde 2014 · ISO 27001

Qué estás conectando y por qué les importa a los revisores

WebViewGold incluye el SDK de OneSignal en los dos proyectos nativos. En cuanto lo activas, la app recibe notificaciones push incluso cuando está cerrada. Tu app web sigue a cargo de tres decisiones: cuándo aparece el diálogo de permiso del sistema, a qué usuario pertenece un dispositivo y qué URL abre una notificación. Cada una de ellas es un esquema de URL o una variable de JavaScript inyectada, documentados en la documentación de push para iOS y en la documentación de push para Android.

A los revisores les importa por dos motivos. La directriz 4.2 espera que una app basada en web haga más que un sitio web, y un opt-in de push que funcione suele ser la primera capacidad nativa que ven. La directriz 4.5.4 marca los límites: la app debe funcionar sin push, las notificaciones no pueden contener datos personales sensibles y los push promocionales necesitan un opt-in explícito en tu interfaz y una forma de darse de baja. Android 13 y posteriores añaden un permiso en tiempo de ejecución (POST_NOTIFICATIONS), así que el momento en que pides permiso importa en ambas plataformas.

El flujo con el que terminarás: después del onboarding, la app web navega a registerpush://; cuando el usuario acepta, lee onesignalplayerid y lo guarda en el usuario; tu servidor envía un push a ese ID de suscripción con una url en los datos adicionales, y WebViewGold abre esa URL cuando se toca la notificación. Para ver el panorama completo de las funciones nativas, consulta el hub de notificaciones push.

Qué hace Claude Code y qué haces tú

ÁreaClaude CodeTú
Panel de OneSignalNada; no tiene acceso a tu panelCrear la app, añadir las credenciales de APNs (iOS) y de Firebase (Android), copiar el App ID y crear una clave de la REST API
Proyectos de WebViewGoldPuede definir kPushEnabled, oneSignalID, PUSH_ENABLED y el ID en build.gradle si los proyectos están en el repositorio; tú revisas el diffCapabilities en el portal de Apple Developer, el bundle ID de la extensión de OneSignal, firma y compilaciones
App webHelper de push, pantalla de opt-in, fila en ajustes, ruta de registro, helper de envío, migración de la base de datos, reglas en CLAUDE.mdAprobar el plan, definir las variables de entorno, desplegar
PruebasUn plan de pruebas por escrito y, si lo pides, una página de depuración oculta que muestra el estado del push y el ID de suscripciónUn iPhone real y un teléfono Android real, TestFlight y pruebas internas

Activa OneSignal y deja que Claude Code haga la parte web

Calcula alrededor de una hora, casi toda en las consolas de Apple y Firebase.

  1. Crea una sola app de OneSignal para ambas plataformas

    Añade iOS con tus credenciales de APNs (OneSignal recomienda una clave de autenticación .p8; un certificado push también sirve) y Android con el JSON de la cuenta de servicio de Firebase que pide OneSignal. Copia el App ID de OneSignal y crea una clave de la REST API para tu servidor.

  2. iOS: Config.swift y capabilities

    Pon kPushEnabled en true, pega el App ID en oneSignalID y pon askforpushpermissionatfirstrun en false para que seas tú quien decida cuándo aparece el diálogo. En el portal de Apple Developer, activa Push Notifications y App Groups para el App ID. El target de la extensión de OneSignal necesita tu bundle ID más .OneSignalNotificationServiceExtension.

  3. Android: Config.java y build.gradle

    Pon PUSH_ENABLED en true, pega el App ID en ONE_SIGNAL_APP_ID en build.gradle (Module: app) y pon requirePush en false. Sustituye ic_stat_onesignal_default.png por tu propio icono monocromo; si no, los usuarios ven una campana genérica.

  4. Marca la app en el user agent

    Define useragent_iphone y useragent_ipad (iOS) y USER_AGENT (Android) como un user agent móvil normal seguido de WebViewGoldApp, para que isNativeApp() pueda distinguir la app de Safari o Chrome. La plantilla de CLAUDE.md explica la convención.

  5. Ejecuta el prompt en modo plan

    Pulsa Shift+Tab hasta que Claude Code muestre el modo plan (o inícialo con claude --permission-mode plan), pega el prompt de abajo y aprueba el plan solo cuando enumere los archivos y la tabla que esperas. Después deja que lo implemente, lee el diff y despliega.

  6. Compila e instala

    Archiva la app de iOS para TestFlight y sube el bundle de Android a pruebas internas. Si prefieres no instalar Xcode ni Android Studio para esto, el Cloud Builder compila ambas apps en el navegador y las sube por ti.

¡Una forma estupenda de convertir tu web app en una app nativa! Entrega rápida y una manera genial de llevar tus apps a las tiendas sin tener que desarrollar una app nativa completa.

Kevin Joling · FlightConnections & TrainConnections · Trustpilot

El prompt para Claude Code

Adapta el nombre de la tabla, las rutas y las notificaciones de ejemplo a tu app. El prompt le dice al agente dónde están los nombres oficiales de los esquemas para que no se invente ninguno.

Pégalo en Claude Code (primero en modo plan)
Nuestra app web también se ejecuta dentro de apps nativas de iOS y Android creadas con WebViewGold. El push de OneSignal está activado en los proyectos nativos. La app web tiene que pedir permiso en el momento adecuado y comunicar el ID de suscripción del dispositivo a nuestro servidor, y el servidor envía notificaciones dirigidas. Antes de escribir código, lee las secciones Push Notifications para iOS y Android en https://www.webviewgold.com/llms-full.txt y usa solo los esquemas de URL y las variables que estén documentados allí. Empieza con un plan y espera mi aprobación.

Implementa:
1. src/lib/native.ts (reutilízalo si ya existe): isNativeApp() comprueba si navigator.userAgent contiene el token WebViewGoldApp; callNative(url) asigna window.location.href solo dentro de la app; readInjected(name, timeoutMs) consulta window[name] cada 100 ms y rechaza la promesa cuando se agota el tiempo.
2. src/lib/push.ts: askForPush() navega a registerpush://. getPushStatus() navega a checkNativePushPermissions:// y resuelve window.nativePushEnabled (true o false). syncPushId() navega a getonesignalplayerid://, lee window.onesignalplayerid y lo envía por POST junto con la plataforma (ios o android, según el user agent) a /api/push/register. Nunca dispares dos esquemas en la misma ejecución del script: en iOS no funcionan varias llamadas a window.location.href en un mismo script, así que escalónalas con una pausa de alrededor de un segundo.
3. Una pantalla de opt-in que se muestra una vez después del onboarding, nunca en la primera pantalla y solo cuando isNativeApp() es true: una frase sobre lo que enviamos (novedades de pedidos y respuestas), un botón "Activar notificaciones" (askForPush y, 3 segundos después, syncPushId) y un enlace "Ahora no" que oculta la pantalla durante 14 días mediante localStorage.
4. Ajustes: una fila "Notificaciones" que muestra el estado devuelto por getPushStatus(). Si están desactivadas, muestra "Abrir ajustes", que navega a settingsapp://. Añade un interruptor aparte, "Novedades del producto", desactivado por defecto y guardado en el perfil del usuario; solo los usuarios que lo hayan activado pueden recibir push promocionales (directriz 4.5.4 de Apple).
5. En cada inicio de la app de un usuario con sesión iniciada dentro de la app, llama una vez a syncPushId(), porque el ID de suscripción puede cambiar tras una reinstalación.
6. Servidor: POST /api/push/register (autenticado; hace upsert de user_id, subscription_id, platform y last_seen_at en una tabla push_devices; añade la migración) y un helper exclusivo del servidor sendPushToUser(userId, title, message, path) que llama a la REST API de OneSignal con include_subscription_ids y pone la URL https completa de la pantalla de destino en data.url. Lee ONESIGNAL_APP_ID y ONESIGNAL_REST_API_KEY solo desde variables de entorno del servidor.
7. Llama a sendPushToUser allí donde se cree una respuesta nueva o un cambio de estado de un pedido. Nada de datos personales o sensibles en el texto de la notificación.
8. Añade las reglas de push anteriores a CLAUDE.md.

Informa de los archivos que cambiaste, la migración, las variables de entorno que debo definir y todo lo que no hayas podido verificar.

La ruta de registro y el helper de envío

Next.js App Router con TypeScript; pide al agente que lo adapte a Express, a una Supabase Edge Function o a una Cloud Function si ese es tu stack. El valor data.url es lo que WebViewGold abre cuando se toca la notificación; el campo Launch URL de OneSignal no es el que debes usar.

typescript
// app/api/push/register/route.ts  (lo llama la app web dentro del envoltorio nativo)
import { NextResponse } from "next/server";
import { getUser, db } from "@/lib/server"; // tus helpers de autenticación y base de datos

export async function POST(req: Request) {
  const user = await getUser(req);
  if (!user) return NextResponse.json({ error: "unauthorized" }, { status: 401 });

  const { subscriptionId, platform } = await req.json();
  if (typeof subscriptionId !== "string" || subscriptionId.length < 10) {
    return NextResponse.json({ error: "invalid subscription id" }, { status: 400 });
  }
  await db.pushDevices.upsert({ userId: user.id, subscriptionId, platform, lastSeenAt: new Date() });
  return NextResponse.json({ ok: true });
}

// lib/push-server.ts  (solo servidor, nunca lo importes desde componentes de cliente)
export async function sendPushToUser(userId: string, title: string, message: string, path: string) {
  const devices = await db.pushDevices.findMany({ userId });
  if (devices.length === 0) return { sent: 0 };

  const res = await fetch("https://api.onesignal.com/notifications?c=push", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
      Authorization: "Key " + process.env.ONESIGNAL_REST_API_KEY,
    },
    body: JSON.stringify({
      app_id: process.env.ONESIGNAL_APP_ID,
      include_subscription_ids: devices.map((d) => d.subscriptionId),
      headings: { en: title },
      contents: { en: message },
      data: { url: "https://app.example.com" + path }, // WebViewGold lo abre al tocar la notificación
    }),
  });
  if (!res.ok) throw new Error("OneSignal " + res.status + ": " + (await res.text()));
  return { sent: devices.length };
}

Checklist de verificación en teléfonos reales

Ni los simuladores ni los navegadores de escritorio pueden demostrar nada de esto. Usa la compilación de TestFlight en un iPhone y la de pruebas internas en un teléfono con Android 13 o posterior, ambas recién instaladas.

  • Primer inicio: no aparece ningún diálogo del sistema, porque askforpushpermissionatfirstrun y requirePush están en false.
  • Después del onboarding aparece tu pantalla de opt-in; "Activar notificaciones" muestra el diálogo del sistema; "Ahora no" oculta la pantalla y sigue oculta en el siguiente inicio.
  • Tras aceptar, aparece una fila en push_devices y el dispositivo se muestra en OneSignal en Audience → Subscriptions.
  • Envía una prueba desde el panel de OneSignal con url en Additional data apuntando a una página interna como /orders/42. Tócala en tres situaciones: con la app cerrada, en segundo plano y en primer plano. Cada toque abre esa página en la app.
  • Provoca un evento real (una respuesta al usuario de prueba) y confirma que solo los dispositivos de ese usuario reciben el push.
  • En un segundo dispositivo, deniega el permiso: Ajustes muestra que las notificaciones están desactivadas y "Abrir ajustes" salta a la pantalla del sistema mediante settingsapp://. Vuelve a activarlas allí, regresa y el estado se actualiza.
  • Borra y reinstala la app e inicia sesión: se registra un ID de suscripción nuevo.

Errores frecuentes

  • Dos esquemas en la misma ejecución de un script en iOS. Asignar varios esquemas a window.location.href en el mismo script no funciona en iOS (Android sí lo gestiona). Escalona las llamadas con una pausa o usa el esquema documentado multiapicall://getonesignalplayerid,getappversion para las consultas de datos compatibles (documentación de MultiAPICall).
  • Launch URL en lugar de datos adicionales. WebViewGold lee el campo url de los datos adicionales. Deja kPushOpenDeeplinkInBrowser (iOS) y OPEN_NOTIFICATION_URLS_IN_SYSTEM_BROWSER (Android) en false si los enlaces deben abrirse dentro de la app.
  • Leer el ID demasiado pronto. onesignalplayerid se inyecta de forma asíncrona y puede no existir hasta que el SDK se haya registrado. Consulta con un tiempo límite y vuelve a intentarlo en el siguiente inicio de la app en lugar de fallar en silencio.
  • Depender del parámetro de URL. Con kPushEnhanceUrl o PUSH_ENHANCE_WEBVIEW_URL, solo la primera petición recibe ?onesignal_push_id=…; un router del lado del cliente lo pierde. Guárdalo enseguida en una cookie o en la sesión, o usa autoInjectVariable / AUTO_INJECT_VARIABLES.
  • Un servicio de push que no está activado. registerpush:// no hace nada si no hay ningún servicio de push activado en el envoltorio. Revisa la configuración antes de depurar tu JavaScript.
  • Secretos en el cliente. La clave de la REST API va solo en variables de entorno del servidor. Claude Code nunca necesita el valor real; dale el nombre de la variable.

Preguntas frecuentes

¿Puedo usar Firebase Cloud Messaging en lugar de OneSignal?

Sí. Activa kFirebasePushEnabled en Config.swift con tu GoogleService-Info.plist y FIREBASE_PUSH_ENABLED en Config.java con tu google-services.json. La parte web es igual, salvo que el ID llega a través de getfirebaseplayerid:// como firebaseplayerid.

¿El push es obligatorio para la aprobación en el App Store?

No, y la app no debe depender de él (directriz 4.5.4). Aun así, es una de las señales más fuertes para la directriz 4.2 de que tu app es más que un sitio web.

¿Puedo enviar notificaciones sin servidor?

Sí. Los envíos masivos desde el panel de OneSignal no necesitan código, y los recordatorios locales programados con sendlocalpushmsg:// funcionan sin ningún servicio de push. Solo necesitas un servidor para mensajes dirigidos a usuarios concretos.

¿Por qué no pedir permiso en el primer inicio?

iOS muestra el diálogo del sistema una sola vez. Si el usuario lo rechaza porque todavía no conoce tu app, solo podrá cambiarlo en los ajustes del sistema. Pedirlo después de un momento que explique el valor convierte mucho mejor.

¿Funciona dentro de la app el web push de un service worker?

No cuentes con ello. Dentro de la app WebViewGold, el push es nativo a través de OneSignal, Firebase o Pushwoosh. Si usas web push, resérvalo solo para los visitantes del navegador.

Tres formas de llevar tu app a las tiendas

El mismo resultado, con distinta cantidad de trabajo por tu parte. Las tres incluyen la garantía de aprobación y soporte humano 24/7.

Hazlo tú mismo

$109 por plataforma, pago único

La licencia de WebViewGold: un proyecto de Xcode o Android Studio listo para usar. Pega tu URL, define nombre e icono, activa funciones, compila y envía. Actualizaciones gratuitas para siempre.

Ver planes en la página principal

Full Service

$698 por plataforma $798

Envíanos tu URL y tu icono. Nuestro equipo configura, compila y entrega tu app en 72 horas, en marca blanca y con los proyectos fuente. Ambas plataformas por $1,158.

Detalles del Full Service Con tecnología de WeSetupYourWebViewApp

Precios de la Oferta de invierno válidos hasta el 31 de diciembre de 2026.

¿Listo para lanzar tu app?

Garantía de aprobación en App Store & Google Play – o te devolvemos el dinero en 14 días

¿Prefieres delegarlo? Full Service: configuramos, compilamos y entregamos en 72 horas, desde $698 por plataforma. ¿Preguntas? Chatea con nosotros 24/7.

Los reembolsos se conceden bajo las condiciones indicadas en nuestras FAQ: un rechazo por motivos ajenos al contenido por parte de Apple y/o Google, reclamado dentro de los 14 días posteriores a la compra.