El sitio de Zonda Cloud (zondacloud.com)
El sitio público de Zonda Cloud es un directorio de archivos planos, apps/zondacloud/ (HTML y CSS, sin construcción y sin dependencias; su único JavaScript es
session.js, de 1 KB y del mismo origen, que reconoce la sesión de la consola; los bloques JSON-LD son datos, no código). Es independiente del sitio de cloud-web (cloudweb.zondacloud.com: instaladores y documentación), que no cambia.
Producción corre en Cloudflare, como un Worker de solo assets (sin código de Worker): la zona zondacloud.com ya está ahí, así que el
DNS se crea solo y el sitio no depende de ninguna máquina propia. La configuración está en deploy/zondacloud/wrangler.jsonc (fuera del
directorio del sitio, para que no se publique con él). Las cabeceras de seguridad y la caché están en apps/zondacloud/_headers.
Desplegarlo
Opción 1 (recomendada): Workers Builds, sin credenciales en el CI
Cloudflare conecta el repositorio de GitLab (gitlab.com; las instancias autoalojadas no se admiten) y despliega en cada push.
- En el panel de Cloudflare: Workers & Pages → Create → Import a repository y elegí
cloud-web1/cloud-web. - Configuración del build (Settings → Build):
- Root directory: vacío (la raíz del repositorio).
- Build command: vacío. El sitio no se construye; un build de la raíz correría todo el monorepo para nada.
- Deploy command:
npx wrangler deploy --config deploy/zondacloud/wrangler.jsonc. El--configexplícito es necesario: sin él,wranglercorre en la raíz de un workspace y falla con "application detection logic has been run in the root of a workspace".
- En Build watch paths limitá el despliegue a
apps/zondacloud/*ydeploy/zondacloud/*para que los demás pushes del repositorio no lo disparen. - Primer despliegue: Cloudflare enlaza
zondacloud.comywww.zondacloud.com(crea los registros DNS). Si ya hay un registro con ese nombre, borralo antes: el enlace no pisa registros.
Opción 2: wrangler deploy desde el CI
Sirve si preferís controlar cuándo se despliega. Hace falta un token de API de Cloudflare con permiso de editar Workers (Account → Workers Scripts → Edit)
y el ID de la cuenta, cargados en Settings → CI/CD → Variables como CLOUDFLARE_API_TOKEN y CLOUDFLARE_ACCOUNT_ID, protegidas y enmascaradas
(nunca en el repositorio). El job es una línea sobre una imagen de Node:
npx wrangler@4 deploy --config deploy/zondacloud/wrangler.jsonc
Para probar la configuración sin desplegar ni usar credenciales: npx wrangler@4 deploy --dry-run --config deploy/zondacloud/wrangler.jsonc.
www al dominio sin www
www.zondacloud.com queda enlazado al mismo Worker, y la URL canónica de la página es https://zondacloud.com/. Para que www redirija, creá una
regla en la zona (Rules → Redirect Rules → Create rule → Single Redirect):
- Cuando: el nombre de host es
www.zondacloud.com. - Entonces: redirección dinámica a
concat("https://zondacloud.com", http.request.uri.path)conservando la cadena de consulta, código301.
(_redirects no distingue por nombre de host, por eso va como regla de la zona.)
Comprobar
curl -sI https://zondacloud.com | head -5 # 200, y las cabeceras de _headers (content-security-policy, x-content-type-options)
curl -sI https://www.zondacloud.com | head -3 # 301 hacia https://zondacloud.com/
curl -sI https://cloudweb.zondacloud.com/install.sh | head -1 # el instalador de cloud-web sigue donde estaba
La landing reconoce la sesión de la consola
El logo de la consola lleva a https://<dominio-base>/ (la landing) y la landing, a su vez, sabe si quien la visita ya ingresó: «Ingresar» pasa a «Mi consola» / «Ir a la
consola», aparece «Hola,
Cómo funciona: apps/zondacloud/session.js hace una petición GET https://console.zondacloud.com/api/whoami con credenciales. La cookie de sesión es de la consola
(console.zondacloud.com, sin Domain, HttpOnly, SameSite=Lax): como la landing y la consola son del mismo sitio (mismo dominio registrable), el navegador la envía en esa
petición, y la consola contesta {"authenticated": true, "name": "Ana"} y nada más (ni rol, ni configuración). Para que la landing pueda leer la respuesta, esa ruta
(y sólo esa) manda CORS con credenciales exclusivamente para https://<dominio-base> y https://www.<dominio-base>; nunca *, y no a los subdominios.
Por qué no se comparte la cookie con todo el dominio (Domain=zondacloud.com, que sería la forma «fácil»): las apps de los usuarios viven en <app>.zondacloud.com, así que recibirían la
sesión de cualquiera que las visite, incluida la de un administrador. La cookie se queda de la consola y la landing pregunta con CORS. Por la misma razón whoami no se abre a
*.zondacloud.com: una app de un usuario no puede leer si su visitante tiene sesión.
La política de seguridad del sitio (_headers) admite por eso script-src 'self' y connect-src https://console.zondacloud.com, y nada más. scripts/check-zondacloud.mjs verifica
que la CSP no se abra a otros orígenes, que session.js sólo hable con /api/whoami, no use HTML dinámico ni almacenamiento y no mande cabeceras propias (para no necesitar preflight), y
prueba su comportamiento en una página real: con sesión, sin sesión, ante errores y con un nombre malicioso. En una instancia sin dominio base no hay landing y la ruta no manda CORS.
Para otra instalación: la URL de la consola está escrita en session.js y en _headers (console.zondacloud.com); cámbiala en los dos lugares y en la comprobación.
SEO y GEO (que te encuentren los buscadores y que los asistentes de IA te citen bien)
Qué tiene el sitio y para qué:
- Cinco páginas con contenido real: la portada y cuatro guías (
/sitios-estaticos/,/contenedores-dockerfile/,/dominio-propio/,/ramas/). Una sola página no alcanza para posicionarse por preguntas concretas («cómo publico un sitio de Vite») ni para que un asistente tenga de dónde citar. Cada guía abre con la respuesta en una frase y usa los nombres exactos de las cosas (frameworks, variables, registros DNS). - Datos estructurados (JSON-LD):
Organization,WebSite,SoftwareApplicationyFAQPageen la portada;TechArticleyBreadcrumbListen las guías. Las preguntas frecuentes marcadas son las mismas que se ven en la página (la comprobación lo exige). No llevan precios, ofertas ni valoraciones: el producto no los ofrece. - Metadatos: título y descripción únicos por página,
canonical,hreflang(esyx-default), Open Graph y Twitter completos,og:localees_AR. robots.txtabierto, con los rastreadores de IA y de búsqueda nombrados de forma explícita, y el sitemap.sitemap.xmlconlastmod.llms.txt: resumen citable y enlaces a las guías, para los asistentes que lo leen.404.htmlconnoindexynot_found_handling: "404-page"en el Worker: una dirección que no existe responde 404 en lugar de servir la portada con 200 (los buscadores lo penalizan).
Lo que no hay a propósito: precios, planes, «gratis», SLA, regiones, testimonios ni promesas de registro abierto (la comprobación los rechaza), y nada que el producto no haga hoy. Es lo que un asistente va a repetir como cierto.
Después de publicar, una sola vez (esto no se puede hacer desde el repositorio):
- Google Search Console: agregá la propiedad de dominio
zondacloud.com(verificación por registro TXT en Cloudflare) y enviáhttps://zondacloud.com/sitemap.xml. Pedí la indexación de la portada y de las cuatro guías. - Bing Webmaster Tools: importá la propiedad desde Search Console. Bing alimenta a varios asistentes de IA.
- Redirección de
wwwal dominio sinwww(ver arriba): sin ella hay dos sitios idénticos y se reparte la señal. - Comprobá los datos estructurados con la Prueba de resultados enriquecidos de Google (
https://search.google.com/test/rich-results) pegando la dirección de la portada.
Cómo mantenerlo: al cambiar una guía, actualizá su <lastmod> en sitemap.xml y el dateModified de su JSON-LD; si agregás una guía, sumala a la portada (#guias), a sitemap.xml y a llms.txt (la comprobación avisa si falta alguna). Si algo del producto cambia (por ejemplo, el registro pasa a ser abierto), corregí primero el texto y la lista de frases prohibidas de scripts/check-zondacloud.mjs.
Antes de publicar un cambio del sitio
node scripts/check-zondacloud.mjs # axe, contraste AA, metadatos, SEO/GEO (JSON-LD, FAQ, sitemap, robots, llms.txt, enlaces), cabeceras, contenido veraz, sin scripts ni recursos remotos, peso
scripts/zondacloud/og.sh # si cambió el titular: vuelve a generar apps/zondacloud/og.png (Chromium + ImageMagick o Pillow)
El sitio solo puede prometer lo que el producto hace hoy: la comprobación rechaza precios, planes, niveles de servicio, regiones y testimonios.