Despliega la agencia
Pon en línea el sitio web, el panel y la API: Docker Compose en un servidor, una aplicación por host desde su Dockerfile, o Node.js sin más.
Para el paquete Full Stack
Tres formas de desplegar
| Forma | Ideal para | Qué necesitas |
|---|---|---|
| Docker Compose en un servidor | Un VPS que controlas, las tres aplicaciones juntas | El paquete Full Stack, Docker en el servidor, un proxy inverso para HTTPS |
| Una aplicación por host, desde su Dockerfile | Railway, Render, Fly.io y otros hosts que construyen desde un Dockerfile | La carpeta de cada aplicación; un volumen o MySQL y un bucket para la API |
| Node.js sin más | Cualquier host con Node | Node.js 22 o más reciente y Yarn 4 en el host |
Elijas la forma que elijas, el sitio web y el panel compilan la dirección de la API en su JavaScript cuando se construyen, así que constrúyelos con las direcciones públicas, nunca con las locales.
Docker Compose en un servidor
Copia la carpeta del paquete al servidor y pon un .env junto a docker-compose.yml con las tres direcciones públicas. De ellas se derivan los orígenes permitidos de la API, la dirección del panel, las direcciones de las fotos y la dirección de la API de los frontends.
SITE_URL=https://www.your-agency.com
ADMIN_URL=https://admin.your-agency.com
API_URL=https://api.your-agency.com
MEDIA_HOSTNAME=api.your-agency.comMEDIA_HOSTNAME es opcional, un host o varios separados por comas (añade el host de tu bucket cuando las subidas vayan a uno): las fotos en esos hosts https las redimensiona Next.js, y cualquier otra foto se carga tal cual. Luego construye e inicia en segundo plano:
docker compose up --build -d- Apunta cada dominio al servidor mediante un proxy inverso que sirva HTTPS (Caddy, Nginx o Traefik), reenviando a los puertos
3030,3031y8000. - Detrás de ese proxy, define
TRUST_PROXY=1enback-end/.env, para que los límites de inicio de sesión, formulario de contacto y solicitud de visita cuenten a cada visitante y no al proxy. El contenedor de la API leeback-end/.envcuando existe, que es también donde van las claves opcionales. - Sin un
JWT_SECRETpropio, la API genera uno en su primer inicio y lo guarda en el volumenvelra-data. La base de datos y las subidas también están en ese volumen, así que haz una copia de seguridad. - El primer inicio carga la agencia de demostración salvo que
SEED_DEMO_DATA=falseesté en el.env. Mantenlo en el primer inicio: la carga inicial es lo que crea las cuentas.
La API desde su Dockerfile
Apunta el host a la carpeta de la API (back-end/ en el Full Stack). La imagen escucha en PORT (8000 salvo que el host defina otro), responde a GET /api/health cuando su base de datos responde, y guarda SQLite y las subidas en /data.
- Monta un volumen persistente en
/data. Sin uno, cada despliegue empieza con una base de datos vacía. - Define
CORS_ORIGINcon las direcciones del sitio web y del panel (separadas por comas),FRONTEND_URLcon la del panel yPUBLIC_MEDIA_URLcon la dirección pública de la API seguida de/media. - Define
SEED_DEMO_DATA=truepara el primer inicio en un volumen nuevo: el valor por defecto de la imagen esfalse, que crea las tablas sin cuentas. Una base de datos existente nunca se vuelve a cargar. - Define tu propio
JWT_SECRET, o deja que el contenedor genere uno y lo guarde en/data/.jwt-secret. - Define
TRUST_PROXY=1: una plataforma de alojamiento pone un proxy delante del contenedor. - Con MySQL (
DB_TYPE=mysqly las cinco variablesDB_*), el contenedor no crea las tablas. Ejecuta una veznode dist/database/seeder.js(agencia de demostración) onode dist/database/sync-schema.js(tablas vacías) con el mismo entorno. - Las subidas en el volumen sobreviven a un nuevo despliegue; para mantenerlas fuera del servidor, define las cinco variables
R2_*para un bucket.
El sitio web y el panel desde sus Dockerfiles
Apunta el host a la carpeta de la aplicación y dale los valores NEXT_PUBLIC_* como argumentos de construcción, no como variables de ejecución: se compilan dentro. Cada imagen sirve el servidor independiente de Next.js en PORT (3030 para el sitio web, 3031 para el panel, salvo que el host defina otro).
| Argumento de construcción | Aplicación | Valor |
|---|---|---|
NEXT_PUBLIC_API_BASE_URL | Ambos | La dirección pública de la API seguida de /api |
NEXT_PUBLIC_SITE_URL | Ambos | La dirección pública del sitio web: las URL canónicas y el mapa del sitio en el sitio web, el enlace "View website" en el panel |
NEXT_PUBLIC_MEDIA_HOSTNAME | Ambos | Opcional. Los hosts https que sirven las fotos (el dominio de la API, el de tu bucket, o ambos), separados por comas |
NEXT_PUBLIC_WEBSOCKET_BASE_URL | Panel | La dirección pública de la API sin /api, para las notificaciones en directo |
El servidor del sitio web también consulta la API mientras renderiza las páginas de propiedad y el mapa del sitio. Con una dirección pública de la API que funcione también desde el servidor, no hace falta nada más; API_INTERNAL_URL en tiempo de ejecución la sustituye cuando el servidor debe usar otra dirección.
Node.js sin más
Construye cada aplicación una vez en el host y luego inicia. Define el .env de los frontends con las direcciones públicas antes de yarn build.
| Aplicación | Construcción | Inicio |
|---|---|---|
| API | yarn build, y una vez yarn seed:prod (agencia de demostración) o yarn db:sync:prod (tablas vacías) | yarn start:prod |
| Sitio web público | yarn build | yarn start (puerto 3030) |
| Panel de la agencia | yarn build | yarn start (puerto 3031) |
La API se enlaza a 0.0.0.0 y lee PORT. Mantén el archivo SQLite y MEDIA_UPLOAD_DIR en un almacenamiento que sobreviva a un despliegue, o usa MySQL y un bucket.
Tus primeras cuentas
No hay página de registro: las dos cuentas del panel vienen de la carga inicial. Empieza la primera vez con la agencia de demostración, inicia sesión y luego hazla tuya:
- Cambia ambas contraseñas en Ajustes, Seguridad, o crea tu propio Super Admin en Gestión de administradores y elimina las cuentas de la carga inicial.
- Archiva o elimina las propiedades de ejemplo, y elimina los barrios de ejemplo que no necesites.
- Cierra las consultas de ejemplo y cancela las visitas de ejemplo: no se pueden eliminar.
- Define el nombre, el eslogan, la descripción y el correo de contacto de la agencia en Ajustes, Agencia, y las viviendas destacadas de la página de inicio en Ajustes, Página de inicio.
Pasar a producción
Antes de que la agencia sea accesible desde internet:
- En el entorno de la API,
NODE_ENV=productiony unJWT_SECRETlargo y aleatorio propio (Docker genera uno cuando no hay ninguno). En producción la API se niega a iniciar sinCORS_ORIGINy dice qué valor falta. CORS_ORIGINcon el sitio web y el panel,FRONTEND_URLcon el panel,PUBLIC_MEDIA_URLcon la API seguida de/media.- La base de datos y las subidas en almacenamiento persistente, con una copia de seguridad.
- La comprobación de estado del host en
/api/health, yTRUST_PROXY=1detrás de un proxy. - Ambos frontends construidos con los valores públicos de
NEXT_PUBLIC_*. - En el sitio web, tu marca en
src/config/brand.config.ts, y la política de privacidad enmessages/privacyreescrita para tu agencia y tu país. - Las contraseñas de la carga inicial cambiadas, o las cuentas de la carga inicial eliminadas.
DEMO_MODE=falseen la API yNEXT_PUBLIC_DEMO_MODE=falseen ambos frontends, tal como se entrega.
No para una agencia con datos reales
yarn setup:fresh construye, elimina todas las tablas y carga los datos, cada vez que se ejecuta, y yarn db:reset elimina todas las tablas. Sirven para un entorno completamente nuevo, nunca como comando de inicio o de construcción.