Crafty Hosting CLI (crafty deploy)

@craftware/crafty-cli despliega los archivos de build de un frontend en Crafty Hosting. El flujo es: la CLI comprime tu build, lo sube a tu tenant de Crafty, y Crafty lo envía al proveedor de hosting desde su propia cuenta centralizada. Nunca tocas al proveedor directamente; solo te comunicas con "Crafty Hosting".

Cuándo usarlo

  • Iniciar un sitio nuevo a partir de un starter oficial: npm create crafty / crafty create.
  • Desplegar, enviar o publicar un frontend compilado (./dist, .output/public, out/, …) en Crafty Hosting.
  • Ejecutar cualquier comando de crafty: login, init, deploy, status, logout.
  • Crear o editar crafty.json.
  • Conectar un dominio personalizado a un sitio desplegado, o depurar un despliegue fallido.

Alcance

  • Incluido: usar el paquete publicado @craftware/crafty-cli con un tenant de Crafty ya desplegado.
  • No incluido: crear contenido (usa la skill crafty-cms / el servidor MCP), construir el backend de Crafty, o el panel del proveedor de hosting.
  • Relacionado: la misma CLI genera tipos de TypeScript para los modelos de contenido del sitio: crafty types escribe crafty.types.ts a partir de la clave API del entorno (CRAFTY_API_KEY / --api-key, sin necesidad de login). Ejecútalo antes de escribir código que lea entradas o bloques; consulta el README de la CLI ("Content types").

Proyecto nuevo: npm create crafty

Para un sitio nuevo, omite login + init de abajo: npm create crafty@latest <dir> -- --url=https://<tenant>.crafty.do --yes (igual que crafty create) copia un starter oficial (Astro "sitio de servicios"), inicia sesión mediante el flujo de dispositivo con los scopes necesarios (deploy crafty:read crafty:write crafty:publish), crea el sitio con el modelo de contenido y el contenido de demostración del starter (publicado salvo que uses --draft), y escribe .env, crafty.json y src/crafty.types.ts. Luego ejecuta npm install && npm run dev, y npm run deploy (build + crafty deploy). Lee el AGENTS.md del proyecto generado antes de modificarlo. Flags y detalles: references/cli-commands.md.

Requisitos previos

  1. Node.js 20+ y la CLI instalada: npm i -g @craftware/crafty-cli.
  2. Un frontend compilado: ejecuta primero el build del framework (npm run build) para que exista el directorio de salida.
  3. CRAFTY_API_URL presente en el .env del proyecto (la misma URL que usa la app para leer la API de Crafty). La CLI obtiene el tenant a partir de ella, así que no hay nada más que configurar.

El flujo

crafty login     # flujo de dispositivo OAuth: aprueba en el navegador
crafty init      # escribe crafty.json (site, environment, buildDir)
npm run build    # genera los archivos de build (depende del framework)
crafty deploy    # comprime el directorio de build, lo sube e imprime la URL pública
  1. crafty login: muestra una URL y un código corto; el usuario aprueba en un navegador que ya tenga sesión iniciada en Crafty. El token (scope deploy) se guarda por host de tenant en ~/.crafty/credentials. No se pegan tokens a mano. La CLI mantiene una sesión por tenant, así que un usuario con varios tenants permanece conectado a todos y nunca vuelve a iniciar sesión al cambiar de proyecto. Usa crafty login --host=<url> para autenticar un tenant sin estar dentro de su proyecto.
  2. crafty init: elige el slug de site y el environment (por defecto production); buildDir tiene por defecto dist. No interactivo: crafty init --site=<slug> --environment=<env> --build-dir=<dir>.
  3. crafty deploy [dir]: empaqueta el directorio de build (por defecto el de crafty.json), lo sube, consulta el estado hasta deployed/failed e imprime la URL. Puedes cambiar el directorio con un argumento posicional (p. ej. crafty deploy .output/public).
  4. crafty status: muestra el estado y la URL del último despliegue del proyecto.
  5. crafty skills install: copia las skills de agente de Crafty en .claude/skills/ (--global para ~/.claude/skills/, --dir=<path> para otros agentes); vuelve a ejecutarlo para actualizarlas.
  6. crafty logout: revoca y elimina la sesión del tenant del proyecto actual (los demás tenants siguen conectados).
  7. crafty update (--update / -u): actualiza la CLI instalada globalmente a la última versión de npm (no hace nada si ya está actualizada).

crafty.json

{
  "site": "acme",
  "environment": "production",
  "buildDir": "dist"
}

Configura buildDir con la salida de tu framework: Vite/CRA dist, exportación estática de Next out, Nuxt .output/public, Astro dist.

Cómo se resuelve el contexto (en orden)

  1. CRAFTY_API_URL del .env del proyecto (se elimina un /api/v1 final) → URL base del tenant.
  2. crafty.json → site, environment, buildDir.
  3. CRAFTY_TOKEN del entorno del proceso (CI) o de ~/.crafty/credentials → token de acceso.

En CI (GitHub Actions)

En CI no hay crafty login: define CRAFTY_TOKEN (un token de acceso personal con el scope deploy, desde Perfil → Tokens en el panel) y CRAFTY_API_URL como variables de entorno, y luego ejecuta npx --yes @craftware/crafty-cli@latest deploy después del build. Nunca pongas CRAFTY_TOKEN en .env (la CLI lo ignora ahí). Para volver a desplegar cuando cambie el contenido, configura un webhook de contenido de Crafty con el formato "GitHub Actions" apuntando a https://api.github.com/repos/{owner}/{repo}/dispatches con un encabezado Authorization: Bearer <GitHub token>, y activa el workflow con on: repository_dispatch: types: [crafty-content] más concurrency: { group: crafty-deploy, cancel-in-progress: true }. El README de la CLI tiene el workflow completo.

Dominios personalizados

Un sitio recibe automáticamente un subdominio con alcance al tenant ({tenant}-{hash}.crafty.run, uno por entorno, visible en Site → Hosting). Para usar tu propio dominio, añádelo en el panel de Crafty, en Site → Hosting; Crafty devuelve un registro CNAME que debes configurar en tu proveedor de DNS. La CLI despliega; los dominios se gestionan en el panel.

  • Añade un subdominio como www.example.com. Crea solo el CNAME que muestra Crafty y no modifiques ningún otro registro, sobre todo los de correo (MX, y los TXT de SPF, DKIM y DMARC).
  • Un dominio raíz (example.com) solo se conecta cuando su DNS está en Cloudflare. Nunca pongas un CNAME en la raíz: un CNAME no puede coexistir con registros MX o TXT, y rompería el correo del dominio. Redirige la raíz a www en el proveedor de DNS.
  • Crafty nunca edita el DNS del cliente; solo gestiona registros de sus propios subdominios crafty.run.

Errores comunes

  • No has iniciado sesión → ejecuta primero crafty login (en CI, define CRAFTY_TOKEN).
  • No hay crafty.json → ejecuta crafty init en la raíz del proyecto.
  • El directorio de build no existe → ejecuta primero el build del framework, o corrige buildDir / el argumento posicional del directorio.
  • Sin CRAFTY_API_URL → crafty login/deploy no pueden encontrar el tenant; añádela a .env (o expórtala).
  • Desplegar el código fuente en lugar del build → apunta buildDir a la salida compilada, no a la raíz del proyecto ni a src/.
  • Cada despliegue reemplaza al anterior en ese entorno: la CLI no ofrece vistas previas por rama ni rollback.
  • URLs desconocidas de un build sin 404.html reciben el index.html del sitio con un 200 (fallback de aplicación de una sola página), para que las rutas del cliente funcionen. Los archivos que faltan dentro de carpetas sin HTML (assets/, _astro/, fonts/…) devuelven un 404 real: Crafty Hosting añade un 404.html allí durante el despliegue. Sube tu propio 404.html en la raíz para desactivar el fallback. Cada despliegue también sigue sirviendo los bundles con hash del despliegue anterior (assets/index-<hash>.js), así que una página cacheada antes del despliegue sigue cargando.

Referencias

  • references/cli-commands.md: cada comando, flag, comportamiento de salida y ejemplos completos por framework.
  • references/install.md: instalación de la CLI y adición de las skills de agente de Crafty (crafty skills install, o zips para Claude.ai y Claude Desktop).