synsema
ES Español

Convertí un sitio renderizado en el servidor en una app instalable (PWA) con push nativo

synsema init --pwa le da a cualquier sitio de Synsema un manifiesto, un service worker, íconos y Web Push. Se instala en Android, iOS y escritorio con ícono en la pantalla de inicio y pantalla completa — nada nativo, sin tienda.

Una app web instalable necesita tres cosas que un sitio normal no tiene: un manifiesto, un service worker y unas líneas en el <head>. Synsema genera todo eso, y las notificaciones push encima, así que un sitio que renderiza en el servidor se vuelve una app en el teléfono sin cliente nativo.

Generalo§

synsema init myapp --pwa && cd myapp
synsema serve app.syn

Obtenés public/manifest.webmanifest, public/sw.js (cachea el shell, nunca /api/, nunca una respuesta fallida), public/app.js (registra el worker, muestra el botón de instalar, se suscribe al push), un ícono SVG con los tamaños PNG generados a partir de él, la API en api.syn (un grupo export routes con las rutas de push y sus límites de tasa por ruta, montado por app.syn — desde 0.6.19) y un push_keys.syn de una sola vez que imprime tu par de claves VAPID para el .env.

Del lado del servidor es el serve que ya conocés:

require serve(8080)
require file.read("index.html")

serve on 8080
    static "/" from "./public" cache "1h"     -- sw.js must live at /sw.js (scope "/")
    route "GET /"
        give render("index.html", {"title": "My app"})

El .webmanifest se sirve como application/manifest+json, que es lo que hace que los navegadores lo acepten.

Push, de punta a punta§

La página lee la clave pública de GET /api/push/config, se suscribe y manda la suscripción a POST /api/push/subscribe. Enviar es un builtin:

let r be push_send(sub, {"title": "Order shipped", "body": "Arrives Tuesday"}, {"vapid": keys})
when r["gone"]
    forget_subscription(sub)      -- 404/410: the browser dropped it

Declará un require net(...) por cada servicio de push al que entregues (FCM, Windows, Mozilla, Apple) y mantené el envío detrás de requires auth o dentro de un cron — nunca en una ruta pública.

Dónde se instala§

Android y los Chromium de escritorio muestran el cartel de instalación; iOS instala desde Compartir → Agregar a la pantalla de inicio y recibe push una vez instalada, sobre un certificado confiable. Esa última parte es una sola bandera — mirá HTTPS automático con una bandera. Firefox no tiene instalación ni modo app: ahí el sitio funciona como sitio.

Y en el escritorio, como app de verdad§

Los mismos archivos son una app de escritorio: synsema init --desktop agrega desk.syn, que sirve la misma página y la misma api.syn en 127.0.0.1, la abre como ventana de app del navegador que ya está en la máquina y termina cuando se cierra la última ventana. synsema build desk.syn -o desk --serve --no-console --icon public/icon.svg la convierte en un .exe con tu ícono (un .app en macOS, una carpeta lanzadora en Linux con --bundle). Cómo funciona, y qué hace cada sistema operativo con eso, está en Distribuí tu app web como app de escritorio.

¿Ya tenés un sitio? Corré synsema init --pwa adentro: no se pisa nada tuyo, los archivos de fábrica caen al lado de los tuyos. Los detalles y las notas de iOS están en la documentación, y podés probar el lenguaje primero en try.synsema.org.