Deploy
Reglas de despliegue - GitHub Pages, Vercel, Netlify, build optimization, CI/CD, env vars, dominios personalizadosFrom its SKILL.md
npx -y skills add 14BryanEspinoza/agent-stack --skill deployAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 1 stars1 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
14.2 KB, ~4.0k tokens by cl100k_base, as published. Nobody here has run it
Deploy — Reglas y Convenciones
1. Filosofía
- Deploy automatizado — Nunca manual. El deploy se hace desde CI/CD, no desde la terminal local.
- Entornos equivalentes — Staging y producción deben correr la misma build. Diferencias mínimas entre entornos.
- Inmutabilidad — Cada build produce un artefacto único e inmutable. No modificar archivos en el servidor.
- Preview por PR — Cada Pull Request genera un preview automático para revisión antes de mergear.
- Rollback rápido — El deploy debe ser reversible en segundos, no horas.
2. Versiones Mínimas
| Tecnología | Versión Mínima |
|---|---|
| Node.js | 22+ |
| npm / pnpm | pnpm 9+ |
| Git | 2.30+ |
3. Preparación para Deploy
Build scripts en package.json
{
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview",
"deploy": "vite build && npx gh-pages -d dist"
}
}
Archivos esenciales
.gitignore → node_modules/, dist/, .env
.env.example → variables necesarias (sin valores reales)
robots.txt → permitir/bloquear crawlers
_headers → Netlify: cabeceras HTTP personalizadas
_redirects → Netlify: reglas de redirección
public/
favicon.ico
CNAME → GitHub Pages: dominio personalizado
robots.txt
robots.txt
# Permitir todo
User-agent: *
Allow: /
# Bloquear staging
# User-agent: *
# Disallow: /
4. GitHub Pages
Configurar GitHub Pages
# 1. Ir a Settings > Pages del repo
# 2. Source: Deploy from a branch
# 3. Branch: gh-pages / (root) o main /docs
# O usar GitHub Actions (recomendado)
GitHub Actions (deploy automático)
# .github/workflows/deploy.yml
name: Deploy to GitHub Pages
on:
push:
branches: [main]
permissions:
contents: read
pages: write
id-token: write
jobs:
build-and-deploy:
runs-on: ubuntu-latest
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
cache: "pnpm"
- run: pnpm install --frozen-lockfile
- run: pnpm build
- uses: actions/configure-pages@v4
- uses: actions/upload-pages-artifact@v3
with:
path: ./dist
- id: deployment
uses: actions/deploy-pages@v4
gh-pages (alternativa CLI)
npm install -D gh-pages
# package.json
{
"scripts": {
"deploy": "pnpm build && npx gh-pages -d dist"
}
}
CNAME (dominio personalizado)
# Archivo: public/CNAME (o en raíz del branch gh-pages)
miproyecto.com
# GitHub Actions con dominio personalizado
steps:
- run: echo "miproyecto.com" > dist/CNAME
- uses: actions/upload-pages-artifact@v3
SPA fallback (single page app)
# Si usas React Router / Vue Router:
steps:
- run: |
pnpm build
cp dist/index.html dist/404.html # Para SPA fallback
Configuración adicional
| Concepto | Configuración |
|---|---|
| Source | Settings > Pages > Source: GitHub Actions |
| Dominio | Settings > Pages > Custom domain (o CNAME) |
| HTTPS | Automático con GitHub Pages (Enforce HTTPS) |
| Custom 404 | 404.html en raíz del branch |
| Subdirectorio | Si el proyecto no está en la raíz, configurar base en vite.config |
5. Vercel
Configurar proyecto en Vercel
# 1. Ir a vercel.com
# 2. Importar repositorio de GitHub/GitLab/Bitbucket
# 3. Configurar build command y output directory
# 4. Agregar variables de entorno
vercel.json
{
"name": "mi-proyecto",
"version": 2,
"framework": "vite",
"buildCommand": "pnpm build",
"outputDirectory": "dist",
"installCommand": "pnpm install",
"devCommand": "pnpm dev",
"regions": ["iad1"],
"env": {
"NEXT_PUBLIC_API_URL": "@api_url"
},
"headers": [
{
"source": "/(.*)",
"headers": [
{ "key": "X-Frame-Options", "value": "DENY" },
{ "key": "X-Content-Type-Options", "value": "nosniff" },
{ "key": "Referrer-Policy", "value": "strict-origin-when-cross-origin" }
]
},
{
"source": "/assets/(.*)",
"headers": [
{
"key": "Cache-Control",
"value": "public, max-age=31536000, immutable"
}
]
}
],
"rewrites": [
{ "source": "/api/(.*)", "destination": "https://api.ejemplo.com/$1" }
],
"redirects": [
{ "source": "/old-path", "destination": "/new-path", "permanent": true }
]
}
CLI de Vercel
# Instalar CLI
npm install -g vercel
# Deploy a producción
vercel --prod
# Preview
vercel
# Variables de entorno
vercel env add API_URL
vercel env pull .env
# Listar deploys
vercel list
# Ver logs
vercel logs <url>
Environment variables
# Local (.env)
API_URL=http://localhost:3000
# Vercel Dashboard
# Settings > Environment Variables
# O CLI:
vercel env add PLAIN_API_URL
Preview deployments
# Automático por PR (GitHub + Vercel)
# Cada PR genera: proyecto-git-hash.vercel.app
SPA fallback (rewrites)
{
"rewrites": [{ "source": "/(.*)", "destination": "/index.html" }]
}
Analytics y Monitoring
# Habilitar Web Analytics
# Dashboard > Analytics > Enable
6. Netlify
Configurar proyecto en Netlify
# 1. Ir a netlify.com
# 2. Importar repositorio de GitHub/GitLab/Bitbucket
# 3. Configurar build command y publish directory
# 4. Agregar variables de entorno
netlify.toml
[build]
command = "pnpm build"
publish = "dist"
base = "/"
[build.environment]
NODE_VERSION = "22"
[dev]
command = "pnpm dev"
port = 5173
targetPort = 5173
[[headers]]
for = "/*"
[headers.values]
X-Frame-Options = "DENY"
X-Content-Type-Options = "nosniff"
Referrer-Policy = "strict-origin-when-cross-origin"
[[headers]]
for = "/assets/*"
[headers.values]
Cache-Control = "public, max-age=31536000, immutable"
[[redirects]]
from = "/old-path"
to = "/new-path"
status = 301
[[redirects]]
from = "/api/*"
to = "https://api.ejemplo.com/:splat"
status = 200
SPA fallback
[[redirects]]
from = "/*"
to = "/index.html"
status = 200
_headers (alternativa a netlify.toml)
/*
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Referrer-Policy: strict-origin-when-cross-origin
/assets/*
Cache-Control: public, max-age=31536000, immutable
_redirects (alternativa a netlify.toml)
# SPA fallback
/* /index.html 200
# Redirecciones
/old-path /new-path 301
/api/* https://api.ejemplo.com/:splat 200
# Bloquear rutas
/admin/* /404.html 404
CLI
# Instalar CLI
npm install -g netlify-cli
# Login
netlify login
# Inicializar
netlify init
# Deploy preview
netlify deploy
# Deploy producción
netlify deploy --prod
# Variables de entorno
netlify env:set API_URL https://api.ejemplo.com
Branch-based deploys
| Branch | Deploy URL |
|---|---|
main | https://proyecto.netlify.app |
develop | https://develop--proyecto.netlify.app |
feature/* | Preview automático por PR |
7. Build Optimization
vite.config.js
import { defineConfig } from "vite";
export default defineConfig({
base: "/mi-repo/", // GitHub Pages subpath
build: {
outDir: "dist",
sourcemap: false,
minify: "esbuild", // 'terser' para mejor compresión
cssMinify: "lightningcss",
rollupOptions: {
output: {
manualChunks: {
vendor: ["react", "react-dom"],
},
},
},
},
});
Optimizaciones generales
| Técnica | Impacto | Implementación |
|---|---|---|
| Minificación | Reduce tamaño JS/CSS | build.minify en vite |
| Code splitting | Carga bajo demanda | manualChunks, React.lazy() |
| Tree shaking | Elimina código muerto | Automático con ES modules |
| Compresión Brotli | Reduce transferencia | Automático en Vercel/Netlify/GH Pages |
| Imágenes WebP | Menor peso imágenes | vite-plugin-imagemin o manual |
| CSS crítico | Reduce FCP | Extraer CSS del viewport inicial |
| Preload fuentes | Evita FOIT | <link rel="preload"> en HTML |
Cache headers por tipo
| Tipo de archivo | Cache-Control |
|---|---|
index.html | no-cache (siempre fresco) |
assets/*.js (con hash) | public, max-age=31536000, immutable |
assets/*.css (con hash) | public, max-age=31536000, immutable |
assets/*.{png,jpg,svg,woff2} | public, max-age=31536000, immutable |
favicon.ico | public, max-age=86400 |
8. Variables de Entorno
Por entorno
| Variable | Local | Staging | Producción |
|---|---|---|---|
API_URL | http://localhost:3000 | https://staging-api.ejemplo.com | https://api.ejemplo.com |
PUBLIC_URL | http://localhost:5173 | https://staging.ejemplo.com | https://ejemplo.com |
En frameworks
# Vite (import.meta.env)
VITE_API_URL=https://api.ejemplo.com
# CRA (process.env)
REACT_APP_API_URL=https://api.ejemplo.com
# Next.js (NEXT_PUBLIC_ para cliente)
NEXT_PUBLIC_API_URL=https://api.ejemplo.com
Manejo seguro
# .env (no committear)
API_KEY=sk-secret-key
# .env.example (committear, sin valores reales)
API_KEY=tu-api-key
# GitHub Actions
# Settings > Secrets and variables > Actions
9. CI/CD
Preview automático por PR
name: Preview Deploy
on: [pull_request]
jobs:
preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: pnpm install --frozen-lockfile
- run: pnpm build
- run: pnpm test
# Deploy preview (Netlify)
- run: npx netlify-cli deploy --dir=dist --message="${{ github.event.pull_request.title }}"
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
Pipeline completo
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
lint-and-test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: pnpm install --frozen-lockfile
- run: pnpm lint
- run: pnpm test
build-and-deploy:
needs: lint-and-test
if: github.ref == 'refs/heads/main'
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: pnpm install --frozen-lockfile
- run: pnpm build
# Deploy según plataforma
- run: npx netlify-cli deploy --prod --dir=dist
env:
NETLIFY_AUTH_TOKEN: ${{ secrets.NETLIFY_AUTH_TOKEN }}
NETLIFY_SITE_ID: ${{ secrets.NETLIFY_SITE_ID }}
10. Checklist Pre-Deploy
## Antes de deployar a producción
- [ ] Build exitoso (`pnpm build`)
- [ ] Tests pasan (`pnpm test`)
- [ ] Linter pasa (`pnpm lint`)
- [ ] Sin console.log / debugger
- [ ] Sin código comentado
- [ ] Variables de entorno configuradas en el dashboard
- [ ] Build probada en local (`pnpm preview`)
- [ ] Dominio personalizado configurado (si aplica)
- [ ] SSL/HTTPS habilitado
- [ ] 404 page personalizada
- [ ] robots.txt configurado
- [ ] Sitemap generado (si aplica)
- [ ] Analytics configurado (si aplica)
- [ ] Preview deploy aprobado
- [ ] Changelog actualizado
- [ ] Tag creado (`git tag v1.2.0`)
11. Rollback
GitHub Pages
# Opción 1: Revertir el commit y pushear de nuevo
git revert HEAD
git push origin main
# Opción 2: GitHub Actions manual
# Ir a Actions > workflow run > Re-run
Vercel
# CLI
vercel rollback <deploy-id>
# Dashboard
# Deployments > ... > Rollback to this deploy
Netlify
# CLI
netlify deploy --prod --dir=dist # Último build exitoso
# Dashboard
# Deploys > ... > Publish deploy
12. Monitoreo Post-Deploy
✅ Verificar:
- Página carga sin errores (consola del navegador)
- API reachable
- Formularios funcionales
- Links internos no rotos
- Imágenes cargan correctamente
- HTTPS funcionando
- Dominio personalizado resuelve
📊 Métricas a revisar:
- Tiempo de carga (LCP, FID, CLS)
- Errores 404/500
- Tráfico en tiempo real
13. Prohibiciones
- ❌ NO hacer deploy manual desde local (siempre CI/CD)
- ❌ No comitear
.envcon valores reales - ❌ No exponer API keys en el cliente (usar serverless functions o proxy)
- ❌ No deployar sin pasar tests y linter
- ❌ No ignorar errores de build
- ❌ No usar
console.logen producción - ❌ No modificar archivos en el servidor después del deploy
- ❌ No deployar directo a producción sin preview
- ❌ No mezclar variables de entorno entre entornos
- ❌ No olvidar el SPA fallback en routers client-side
14. Referencias
Nota: Para commits y PRs, ver Git Nota: Para linting y formato, ver Linting
Última actualización: 2026-07
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.