Volver al inicio
Anexo: Despliegue del proyecto
Ampliación opcional del proyecto

Despliegue del proyecto

Hasta ahora la aplicación solo vive en tu portátil: corre en localhost:4321 y localhost:8080. Si apagas el ordenador, se acabó. Aquí vamos a llevarla a la nube: Vercel para el front, Railway para el back en Java y Supabase, que ya está desplegado de fábrica.

1 ¿Qué significa "desplegar"?

Desplegar (deploy) es coger tu código y ponerlo a correr en un servidor que esté conectado a Internet 24/7, con una URL pública para que cualquiera pueda usarlo.

En tu máquina (lo que has hecho hasta ahora)

  • • El servidor lo arrancas tú con npm run dev
  • • Solo accesible desde tu portátil
  • • Si lo apagas, deja de funcionar
  • • URL: localhost:4321

En producción (a partir de aquí)

  • • El servidor está en un datacenter, siempre encendido
  • • Accesible desde cualquier sitio del mundo
  • • HTTPS automático, dominio público
  • • URL: mi-app.vercel.app

Importante

Este anexo es opcional: el proyecto se entrega funcionando en local. Pero si quieres enseñárselo a alguien que no esté sentado a tu lado, o ponerlo en tu portfolio, desplegar es lo que te lo permite.

2 CI/CD: el ciclo automático que dispara cada push

Plataformas como Vercel y Railway no son "FTP de toda la vida". Son sistemas de CI/CD: cada vez que haces git push, ellas solas se encargan de compilar, testear y publicar la nueva versión.

CI Continuous Integration

"Integración continua". Cada cambio que subes se compila y se prueba automáticamente. Si algo se rompe, te avisa antes de que llegue a producción.

CD Continuous Deployment

"Despliegue continuo". Si la CI pasa, la nueva versión se publica sola, sin que tengas que tocar nada. Cero "subir manualmente al servidor".

El flujo CI/CD: del editor al dominio público

CI = Continuous Integration (compilar y testear cada push). CD = Continuous Deployment (publicar lo que pasó la CI).

1. Escribís código en local
Editor + git. El cambio todavía solo vive en tu máquina.
Código
localhost
GitHub
git push
Build
CI
Deploy
CD
Live
producción

La idea clave

Tu trabajo es git push. Lo demás lo hace la plataforma. Si el build falla en la nube, te llega un email con el log y la versión anterior se queda viva. Cero downtime.

3 El stack: tres servicios, tres dominios

Cada parte del proyecto va a vivir en su propio sitio. Esto se llama arquitectura distribuida: cada servicio se especializa en lo suyo.

Vercel

Front en Astro. Optimizado para frameworks de JavaScript, deploys casi instantáneos.

mi-app.vercel.app

Railway

API en Spring Boot. Detecta el JAR de Maven y lo arranca con su buildpack de Java.

mi-api.up.railway.app

Supabase

Base de datos PostgreSQL. Ya está en la nube desde el día 1, no hay que desplegar nada.

db.supabase.co

Tres servicios, tres dominios

Cada pieza del stack vive en su propia plataforma y se habla con las demás por HTTPS.

Vercel
Front (Astro)
mi-app.vercel.app
Railway
API (Spring Boot)
mi-api.up.railway.app
Supabase
PostgreSQL
db.supabase.co
Un usuario abre mi-app.vercel.app en su navegador.

4 Paso 1: Build local antes de subir nada

Esto es obligatorio. Antes de subir el código a GitHub, comprueba que compila en tu máquina. Si aquí falla, en la nube va a fallar igual, pero perdiendo 5-10 minutos por intento.

Front (Astro)

npm install
npm run build
npm run preview  # opcional, prueba el build

Genera dist/ con todo lo que va a producción.

Back (Spring Boot)

./mvnw clean package
java -jar target/*.jar  # opcional, prueba el JAR

Genera el JAR ejecutable en target/.

Build local antes del push: 30 segundos que te ahorran un disgusto

Si no compila en tu máquina, no va a compilar en la nube. Comprobalo ANTES de subirlo.

$npm run build
Front (Astro)
npm run build
Back (Spring Boot)
./mvnw clean package

Errores típicos del build

  • Imports rotos: en local funciona porque el caché tiene archivos antiguos. Borra node_modules y haz npm install limpio.
  • Variables de entorno faltantes: en local las tienes en .env, en la nube hay que configurarlas en el panel.
  • Versión de Java distinta: el pom.xml debe declarar la misma que vas a usar en Railway (Java 17 o 21 idealmente).

5 Paso 2: variables de entorno y .gitignore

Las claves de API, contraseñas y URLs de servicios privados nunca se suben a GitHub. Aunque el repo sea privado. Aunque digas "luego lo arreglo". Una vez en el historial de git, está filtrado.

Asegúrate de que tu .gitignore contiene esto:

# Variables de entorno
.env
.env.local
.env.*.local

# Dependencias
node_modules/
target/

# Builds
dist/
build/

# IDEs
.vscode/
.idea/
*.iml

Buena práctica: .env.example

Sube al repo un archivo .env.example con los nombres de las variables pero sin valores. Así cualquiera que clone el proyecto sabe qué claves necesita.

# .env.example (sí se sube a GitHub)
SUPABASE_URL=
SUPABASE_KEY=
OPENAI_API_KEY=
SPRING_DATASOURCE_URL=

Variables de entorno: lo que se queda fuera del repo

Las claves van en el panel de la plataforma, nunca en el código.

En tu máquina
// .env (NO subir)
SUPABASE_URL=...
SUPABASE_KEY=sk_...
OPENAI_API_KEY=sk-...
Listado en .gitignore
En GitHub
esperando push...
Panel de Vercel / Railway → Environment Variables
SUPABASE_URL
••••••••••
SUPABASE_KEY
••••••••••
OPENAI_API_KEY
••••••••••
La plataforma las inyecta como variables de entorno reales en tiempo de ejecución.

Si por error subes una clave

  1. Rota la clave inmediatamente en el panel del proveedor (Supabase, OpenAI...). Asume que está comprometida.
  2. Borrarla con un commit nuevo NO sirve: sigue en el historial de git.
  3. Para limpiar el historial: git filter-repo o reescribir el repo. Pero la clave ya estuvo expuesta.

6 Paso 3: subir el código a GitHub

Tanto Vercel como Railway funcionan conectándose a un repositorio de GitHub. Sin repo, no hay deploy.

1. Crea el repositorio en GitHub

En github.com → New repository. Ponle nombre (sin espacios), elige "Private" si no quieres que sea público, y NO marques "Initialize with README" (si tu proyecto ya tiene archivos).

2. Conecta tu carpeta local

git init
git add .
git commit -m "Initial commit"
git branch -M main
git remote add origin https://github.com/tu-usuario/tu-repo.git
git push -u origin main

3. Comprueba en la web

Refresca la página del repo. Tienen que estar todos los archivos del proyecto. Importante: abre el repo y busca .env. Si aparece, tu .gitignore no estaba bien. Para de hacer todo y rota las claves.

¿Front y back en el mismo repo o separados?

Las dos opciones son válidas. Para este proyecto, lo más sencillo es dos repos separados: uno para el front (Astro) y otro para el back (Spring Boot). Así Vercel y Railway pueden cada uno "vigilar" su propio repo sin liarse.

7 Paso 4: desplegar el front en Vercel

Vercel es la plataforma "creada por los autores de Next.js" pero compatible con Astro de fábrica. El proceso es prácticamente cero clicks una vez conectado.

1. Crear cuenta y conectar GitHub

En vercel.com → "Sign up with GitHub". Vercel te pide permiso para leer tus repos. Concédelo (puedes acotar a un repo concreto si prefieres).

2. Importar el repo del front

Dashboard → Add New → Project → seleccionas el repo del front. Vercel detecta solo que es Astro y rellena los campos de build:

Framework Preset: Astro
Build Command:    npm run build
Output Directory: dist
Install Command:  npm install

3. Configurar variables de entorno

ANTES de hacer click en "Deploy", abre Environment Variables y añade todas las que tu front necesita:

PUBLIC_SUPABASE_URL=https://xxx.supabase.co
PUBLIC_SUPABASE_ANON_KEY=eyJhbGc...
PUBLIC_API_URL=https://mi-api.up.railway.app

En Astro, las variables que empiezan por PUBLIC_ son accesibles desde el navegador. Las que NO llevan ese prefijo solo son accesibles desde el servidor (endpoints, SSR).

4. Deploy

Click en Deploy. Vercel clona el repo, ejecuta npm install && npm run build, y a los 30-60 segundos tienes la URL pública: tu-proyecto.vercel.app.

Bonus: deploys automáticos

A partir de aquí, cada git push a main dispara un deploy nuevo automáticamente. Y cada Pull Request tiene su propia URL de preview aislada para revisar antes de mergear.

8 Paso 5: desplegar el back (Spring Boot) en Railway

Railway está pensado para backends. Detecta automáticamente que tu repo tiene un pom.xml, compila con Maven y ejecuta el JAR resultante. Cero Dockerfile obligatorio.

1. Crear cuenta y nuevo proyecto

En railway.app → Login con GitHub → New Project → Deploy from GitHub repo. Selecciona el repo del back.

2. Detección automática de Spring Boot

Railway lee el pom.xml, instala el JDK que declares (Java 17 o 21 recomendado), ejecuta ./mvnw clean package -DskipTests y arranca el JAR. Tú no escribes nada de eso.

Si quieres forzar una versión concreta de Java, añade un system.properties en la raíz del repo:

java.runtime.version=21

3. Variables de entorno

En el dashboard del servicio → pestaña Variables. Añade las del back:

SPRING_DATASOURCE_URL=jdbc:postgresql://db.supabase.co:5432/postgres
SPRING_DATASOURCE_USERNAME=postgres
SPRING_DATASOURCE_PASSWORD=tu-password-de-supabase
CORS_ALLOWED_ORIGINS=https://mi-app.vercel.app
PORT=8080

4. El puerto: usar $PORT

Railway te asigna un puerto dinámico mediante la variable $PORT. Spring Boot lee esta variable de fábrica si la tienes en application.properties:

server.port=$${PORT:8080}

Si dejas 8080 hardcodeado, Railway no podrá rutear las peticiones y el deploy fallará.

5. Generar dominio público

Pestaña Settings → Networking → Generate Domain. Te da una URL gratis tipo mi-api.up.railway.app. Esta es la URL que va a usar tu front.

Tier gratuito de Railway

Railway da unos $5 de crédito al mes en el plan gratis. Para un proyecto pequeño que no recibe tráfico 24/7 sobra. Si la app se queda dormida sin uso, la primera petición tarda 1-2 segundos en despertar.

9 Paso 6: ¡los localhost ya no existen!

Este es el error más común al desplegar por primera vez. En tu código tienes hardcodeados http://localhost:8080 o http://localhost:4321. En la nube esas direcciones no existen.

Mal

// front: src/lib/api.js
const API = 'http://localhost:8080';

fetch(`$${API}/productos`)

En producción esto intenta llamar al puerto 8080 del navegador del usuario. Falla siempre.

Bien

// front: src/lib/api.js
const API = import.meta.env.PUBLIC_API_URL;

fetch(`$${API}/productos`)

La URL viene de la variable de entorno: en local apunta a localhost, en Vercel apunta a Railway.

CORS: el back tiene que aceptar al front

Por defecto, el back de Spring Boot bloquea peticiones desde un dominio distinto al suyo. Hay que decirle explícitamente que mi-app.vercel.app sí está autorizado:

@Configuration
public class CorsConfig {
  @Bean
  public WebMvcConfigurer corsConfigurer() {
    return new WebMvcConfigurer() {
      @Override
      public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
          .allowedOrigins(System.getenv("CORS_ALLOWED_ORIGINS").split(","))
          .allowedMethods("GET","POST","PUT","DELETE");
      }
    };
  }
}

En la variable CORS_ALLOWED_ORIGINS de Railway pones la URL pública de Vercel. Si la cambias luego, recuerda actualizarla aquí.

Resumen de URLs

Pieza En local En producción
Front localhost:4321 mi-app.vercel.app
API localhost:8080 mi-api.up.railway.app
DB db.supabase.co (no cambia, ya estaba en la nube)

10 Paso 7 (opcional): dominio propio

Si vas a probar, mi-app.vercel.app te vale. Si vas a enseñárselo a clientes o ponerlo en producción real, vas a querer un dominio propio: miempresa.com.

Dominio gratis vs dominio propio

Para probar: el subdominio gratis vale. Para producción real: tu propio dominio + DNS.

Opción A — Gratis
Subdominio de la plataforma
mi-app.vercel.app
mi-api.up.railway.app
Cero configuración
HTTPS automático
Dominio largo y poco profesional
Opción B — Tu dominio
Dominio propio + DNS
miempresa.com
api.miempresa.com
Dominio profesional
Hay que pagar el dominio (~10€/año)
Configurar registros DNS
Registros DNS típicos (en tu registrador: Namecheap, IONOS, GoDaddy...)
TipoNombreValor
A@76.76.21.21 (Vercel)
CNAMEwwwcname.vercel-dns.com
CNAMEapimi-api.up.railway.app
Los nameservers son distintos: cambian quién resuelve tu dominio (delegás todo el DNS a otro proveedor, ej. Cloudflare). Los registros A/CNAME los configurás dentro del proveedor que tenga los nameservers activos.

¿Qué son los nameservers?

Son los servidores que responden "qué IP tiene este dominio". Cuando compras un dominio en Namecheap, IONOS o GoDaddy, por defecto sus nameservers son los que responden. Si quieres usar Cloudflare (o cualquier otro panel DNS), tienes que cambiar los nameservers en tu registrador. Eso delega el control DNS a otro proveedor.

¿Qué son los registros A / CNAME?

Dentro del panel del proveedor que tenga los nameservers activos, tú añades los registros DNS: A apunta a una IP, CNAME apunta a otro dominio. Vercel y Railway te dicen exactamente qué valores poner en su panel de "Custom Domain".

Conectar dominio en Vercel

Project → Settings → Domains → Add. Escribes miempresa.com. Vercel te dice los registros que tienes que añadir (normalmente un A para la raíz y un CNAME para www).

Conectar subdominio en Railway

Service → Settings → Networking → Custom Domain. Pones api.miempresa.com. Railway te da un CNAME que tienes que añadir en tu panel DNS apuntando a mi-api.up.railway.app.

Los DNS tardan

Cuando cambias un registro DNS, los cambios se propagan por Internet entre 5 minutos y 48 horas (en la práctica casi siempre menos de 1 hora). Si después de cambiarlo no funciona enseguida, no entres en pánico: espera, comprueba con dig miempresa.com o nslookup.

11 Checklist final

Build local funciona
npm run build y ./mvnw clean package sin errores.
.env está en .gitignore
Ningún archivo .env aparece en el repo de GitHub.
Repo subido a GitHub
Front y back en repos separados (recomendado).
Vercel conectado al repo del front
Variables PUBLIC_* configuradas. URL pública responde.
Railway conectado al repo del back
Variables de Spring configuradas. server.port=$${PORT}. Dominio generado.
Supabase accesible desde Railway
La conexión JDBC funciona. Las tablas existen y los datos se leen.
Las URLs en el código son variables de entorno
Cero localhost hardcodeado en el front que vaya a producción.
CORS configurado en el back
El dominio de Vercel está en CORS_ALLOWED_ORIGINS.

12 En una frase

"Si compila en local y los .env están donde deben estar, desplegar es git push."

La nube ya no es un misterio: Vercel, Railway y Supabase hacen el trabajo pesado por ti. Tu único trabajo es escribir buen código y respetar el contrato del entorno.

Volver a anexos Ir al temario