Publicar en YaDominios Cloud: guía técnica completa (para desarrolladores e IA)
Actualizado: 2026-07-18 · YaDominios
YaDominios Cloud publica un repositorio de GitHub como sitio en vivo en nombre.sitios.dev, sobre nuestra red global (330+ ciudades). Hay dos modos: sitio estático (un index.html en el repo) o app con backend (un _worker.js compilado en la raíz, que recibe base de datos SQL en env.DB, almacenamiento de archivos en env.BUCKET y assets en env.ASSETS). Cada push a GitHub republica el sitio automáticamente. Esta página es la referencia técnica completa; una IA puede leerla y dejar una app lista sin ayuda humana.
Qué es (modelo mental en 20 segundos)
YaDominios Cloud es hosting serverless: conectas un repositorio público de GitHub desde el panel (app.yadominios.com → YaDominios Cloud), eliges un nombre, y el sitio queda en vivo en <nombre>.sitios.dev con HTTPS automático, en 330+ ciudades del mundo. No corremos tu build: desplegamos lo que hay en el repo. Tu repo debe traer el resultado final (HTML estático o un worker compilado). Cada git push republica solo, en segundos.
git push publica solo.Modo 1 — Sitio estático
Requisito único: un index.html. Lo buscamos en la raíz del repo o en public/, dist/, build/, site/, _site/, docs/ u out/ (la primera carpeta que lo tenga es la raíz publicada). Todos los archivos de esa carpeta se sirven como assets con caché de borde; el HTML se revalida siempre (max-age=0), así los cambios se ven al instante.
Modo 2 — App con backend (_worker.js)
Si la raíz publicada trae un archivo _worker.js, el sitio es una APP: ese archivo corre como un worker en el servidor de YaDominios Cloud y recibe TODAS las peticiones. Debe ser un solo archivo JavaScript ES-module ya compilado (haz bundle de tus dependencias con esbuild/rollup) con esta forma:
export default {
async fetch(request, env, ctx) {
const url = new URL(request.url);
if (url.pathname.startsWith("/media/")) {
// tu backend aquí (env.DB, env.BUCKET)
return Response.json({ ok: true });
}
return env.ASSETS.fetch(request); // el resto: tus archivos estáticos
}
};
⚠️ No uses /api/ para tus rutas de backend. Los assets estáticos se sirven antes que tu worker; en apps que traen assets (Next.js/OpenNext) el prefijo /api/* puede quedar capturado por el enrutado de archivos y devolver 404 sin llegar a tu código. Usa otro prefijo (/media, /upload, /datos…). Es un detalle real de la plataforma, comprobado en producción.
Node.js: no necesitas configurar nada para usar APIs de Node (node:stream, node:crypto, etc.). Toda app con backend corre con Node compat activado automáticamente por YaDominios Cloud, con una fecha de compatibilidad reciente. Por eso los frameworks (Next.js con OpenNext, etc.) funcionan sin ajustes.
Al publicar una app, provisionamos automáticamente (idempotente, sin configurar nada):
| Binding | Qué es | Cómo se usa |
|---|---|---|
env.DB | Base de datos SQL propia del sitio (motor SQLite serverless). Se crea con nombre site-<nombre>-db. | await env.DB.prepare("SELECT * FROM t WHERE id=?").bind(1).all() |
env.BUCKET | Almacenamiento de archivos e imágenes propio del sitio (bucket site-<nombre>). | await env.BUCKET.put("foto.jpg", bytes) · await env.BUCKET.get("foto.jpg") |
env.ASSETS | Tus archivos estáticos del repo. | return env.ASSETS.fetch(request) |
env.UPLOAD_TOKEN | Contraseña que la nube genera sola para proteger tu ruta de subida. La ves y copias en el panel; no la inventes. | if (req.headers.get("x-upload-token") !== env.UPLOAD_TOKEN) return new Response("401", { status: 401 }) |
Nota sobre env.BUCKET: el binding y los permisos ya están en la plataforma. Si R2 aún no está activado en la cuenta al momento de publicar, la app sale igual (sin storage) y el bucket se conecta automáticamente en el siguiente deploy cuando se active. Programa contra env.BUCKET con normalidad.
Tablas: schema.sql
Si la raíz publicada trae schema.sql, lo ejecutamos contra la base del sitio en cada publicación. Escribe DDL idempotente:
CREATE TABLE IF NOT EXISTS clientes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nombre TEXT NOT NULL,
creado_en TEXT DEFAULT (datetime('now'))
);
_worker.js y schema.sql no se sirven al público: son código/config.
Next.js y frameworks (SSR, server actions, rutas dinámicas)
Una app Next.js SÍ corre en YaDominios Cloud, pero hay que compilarla a Worker antes del push (nosotros no corremos next build). El camino oficial es el adaptador OpenNext para Cloudflare (@opennextjs/cloudflare), que convierte la app en un worker + assets. Automatízalo con un GitHub Action que construya y deje el resultado en el repo (o en una rama deploy que conectas al panel):
# .github/workflows/build.yml
name: build-para-yadominios-cloud
on: { push: { branches: [main] } }
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with: { node-version: 22 }
- run: npm ci && npx opennextjs-cloudflare build
# IMPORTANTE: .open-next/worker.js NO es autónomo (importa ./cloudflare/,
# ./middleware/, etc.). Hay que empaquetarlo a UN solo archivo:
- run: |
npx esbuild .open-next/worker.js --bundle --format=esm --platform=neutral --conditions=workerd,worker,browser --external:cloudflare:workers --outfile=_worker_bundle.js
mkdir out-deploy
mv _worker_bundle.js out-deploy/_worker.js
cp -r .open-next/assets/* out-deploy/ 2>/dev/null || true
- uses: peaceiris/actions-gh-pages@v4
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
publish_branch: deploy
publish_dir: ./out-deploy
Límites actuales del modo app: la plataforma aún NO soporta Durable Objects ni colas. Configura OpenNext sin cola de revalidación (ISR desactivado o caché simple en assets) para que el worker empaquetado no dependa de esos exports. El worker final debe ser un único archivo ES-module cuyo default export tenga fetch.
Para sitios sin servidor (blogs, landings), más simple: next build con output: "export" genera out/ con HTML estático — y out/ es una de las carpetas que detectamos.
Publicar y republicar
- Primera vez: panel → app.yadominios.com → Servicios → YaDominios Cloud → nombre del sitio + URL del repo → «Publicar mi sitio». Reglas del nombre: minúsculas, números y guiones, máx. 63, sin
--ni nombres reservados (www, api, admin, docs…). - Después: cada
git pusha la rama conectada republica el sitio automáticamente (webhook de GitHub). No hay paso 2.
API de base de datos (consola y migraciones)
Cada sitio con base de datos puede consultarse por HTTP con un token de un solo sitio que se genera en el panel (Cloud → tu sitio → «Abrir base de datos»). El token solo da acceso a la base de ESE sitio, expira, y sirve para que una IA o script corra consultas y migraciones:
POST https://hooks.sitios.dev/db/query
Content-Type: application/json
{ "token": "<token del panel>", "sql": "SELECT * FROM clientes LIMIT 10", "params": [] }
→ { "ok": true, "site": "misitio", "results": [ … ], "meta": { … } }
Para migraciones, manda tus CREATE TABLE/ALTER TABLE en sql (una sentencia o varias separadas por «;»). Errores devuelven { "ok": false, "error": "…" } con HTTP 4xx.
Configuración de plataforma (wrangler.jsonc)
Para variables, KV, Durable Objects, colas, cron y compatibility flags, pon un yadominios.json en la raíz publicada (también aceptamos wrangler.jsonc, el formato que ya generan las IA). Leemos ese archivo y provisionamos/enlazamos todo automáticamente en YaDominios Cloud, aislado por sitio.
{
"compatibility_flags": ["nodejs_compat"],
"vars": { "API_URL": "https://api.tuservicio.com" },
"kv_namespaces": [{ "binding": "CACHE" }],
"durable_objects": { "bindings": [{ "name": "SALA", "class_name": "Sala" }] },
"migrations": [{ "new_sqlite_classes": ["Sala"] }],
"queues": { "producers": [{ "binding": "COLA", "queue": "trabajos" }] },
"triggers": { "crons": ["*/10 * * * *"] }
}
| Capacidad | Cómo se declara | Cómo se usa en tu código |
|---|---|---|
| Variables públicas | vars en el archivo (van en el repo) | env.API_URL |
| Variables SECRETAS (API keys) | En el panel → tu sitio → Variables de entorno (NO en el repo) | env.STRIPE_KEY |
| KV (caché/clave-valor) | kv_namespaces | await env.CACHE.get("k") |
| Durable Objects (estado, tiempo real) | durable_objects + migrations (usa new_sqlite_classes) | env.SALA.get(env.SALA.idFromName("x")) |
| Colas | queues.producers (requiere Queues activo en la cuenta) | await env.COLA.send(msg) |
| Cron | triggers.crons | Tu worker responde a GET /__scheduled (te lo invocamos según tu cron) |
| Compatibility flags | compatibility_flags | — |
Variables secretas: nunca las pongas en el repo. Van en el panel (se guardan cifradas del lado del servidor y se inyectan como secretos al desplegar; el panel solo muestra los nombres, nunca los valores). Al guardarlas, el sitio se re-publica para aplicarlas.
Cron (tareas programadas): declara la expresión en triggers.crons y expón una ruta GET /__scheduled en tu worker con tu tarea. Nuestro planificador la invoca al minuto que corresponda (llega con el header x-yad-cron). Con OpenNext/Next, agrega esa ruta como un endpoint más de tu worker.
Dominio propio (minegocio.com)
Los planes Órbita en adelante incluyen dominio propio. Es autoservicio desde el panel: YaDominios Cloud → tu sitio → «Conectar mi dominio propio». Escribes tu dominio y el panel te muestra 2 nameservers únicos; los pegas en tu registrador (cada uno tiene su casilla para copiar) y en minutos u horas tu dominio sirve tu sitio con HTTPS automático. Tu subdominio nombre.sitios.dev sigue funcionando siempre.
Registro de errores (observabilidad)
Si tu app lanza una excepción en producción, el visitante ve una página de error amable y el error queda registrado con su stack completo en YaDominios Cloud → tu sitio → «Registro de errores» (últimos 20). Si tu página la maneja una IA, copia el error tal cual y pégaselo: tiene la ruta, el método y la traza para arreglarlo.
Checklist para una IA que va a publicar aquí
- ¿La app es estática? → asegura
index.htmlen la raíz (oout/con export estático) y push. - ¿Tiene backend? → genera
_worker.jscompilado (bundle único,export default { fetch }), usaenv.DB/env.BUCKET/env.ASSETS, agregaschema.sqly push. - ¿Next.js con SSR? → adaptador OpenNext + Action de arriba; conecta la rama
deployen el panel. - Conecta el repo en app.yadominios.com (una sola vez). Cada push siguiente publica solo.
- ¿Datos? → usa el token del panel contra
POST /db/querypara crear tablas, sembrar y consultar.
Preguntas frecuentes
Corren mi npm run build?
No. Desplegamos lo que hay en el repo: HTML estático o un _worker.js ya compilado. El build se automatiza con un GitHub Action en tu propio repo.
Puedo usar Node.js puro (Express)?
No directamente: el backend corre como un worker (export default { fetch }). Express no aplica; usa el patrón worker o un framework con adaptador (Next.js vía OpenNext, Hono, etc.).
El repo debe ser publico?
Sí por ahora: conectamos repos públicos de GitHub. Los archivos se leen por la API de GitHub al publicar.
Que limites tiene la base de datos?
Es una base SQLite serverless: ideal para apps pequeñas y medianas. Cada sitio tiene su propia base aislada, con respaldo automático.
Como conecto mi dominio propio (midominio.com)?
Los planes Orbita en adelante incluyen dominio propio: se configura con nuestro equipo desde el panel. El subdominio nombre.sitios.dev queda siempre disponible.