Sitio web estático para alquiler de equipos de producción audiovisual Catálogo interactivo · Cotizaciones vía WhatsApp · Sanity CMS como backend
- Descripción del Proyecto
- Stack Tecnológico
- Arquitectura
- Características Funcionales
- Estructura del Proyecto
- Instalación y Desarrollo Local
- Sanity CMS
- Despliegue en Cloudflare Pages
- CI/CD
- Mantenimiento
- Licencia
Black Rec Rental House es un catálogo en línea desarrollado por Daniel Esteban Pedroza Polo para una empresa de alquiler de equipos audiovisuales con sede en Colombia. El sitio permite a los clientes explorar el inventario completo de equipos (cámaras, iluminación, audio, grip, televisores), consultar especificaciones técnicas detalladas y solicitar cotizaciones personalizadas que se envían directamente al WhatsApp de la empresa.
El proyecto fue construido como un sitio estático (SSG) con Next.js, utilizando Sanity CMS como sistema de gestión de contenido headless. Esto permite que el personal no técnico de la empresa pueda gestionar productos, categorías, configuración del sitio y navegación sin necesidad de tocar código. El sitio se despliega en Cloudflare Pages con generación de páginas en tiempo de compilación, ofreciendo tiempos de carga ultrarrápidos y costos de hosting mínimos.
Black Rec Rental House — Alquiler de equipos para producción audiovisual en Colombia.
| Tecnología | Versión | Propósito |
|---|---|---|
| Next.js | 16.2 | Framework React con App Router y exportación estática |
| React | 19.2 | Biblioteca de interfaz de usuario |
| TypeScript | 6.0 | Tipado estático estricto |
| Sanity CMS | 6.2 | Sistema de gestión de contenido headless |
| Bootstrap 5 | 5.3 | Sistema de diseño responsivo |
| React-Bootstrap | 2.10 | Componentes Bootstrap nativos de React |
| Lucide React | 1.21 | Iconografía vectorial |
| styled-components | 6.4 | Estilos dinámicos (tema oscuro/claro) |
| CSS Modules | — | Estilos encapsulados por componente |
| pnpm | 11 | Gestor de paquetes rápido y eficiente |
| Cloudflare Pages | — | Hosting y CDN global |
El proyecto sigue una arquitectura Feature-Driven Development (FDD) combinada con Server Components de Next.js:
src/
├── app/ → Enrutamiento (App Router), layouts, metadatos SEO
├── features/ → Lógica de negocio dividida por funcionalidad
│ ├── home/ → Página principal (Hero, Categorías, Destacados)
│ ├── catalog/ → Catálogo con filtros dinámicos y detalle de producto
│ ├── quote/ → Formulario de cotización multi-sección
│ └── contacto/ → Página de contacto con redes sociales
├── components/ → Componentes globales (Navbar, Footer)
├── lib/sanity/ → Capa de datos: cliente, tipos, consultas GROQ
└── context/ → Contextos (tema oscuro/claro)
Sanity CMS (Headless)
│
▼ (GROQ queries en build time)
Next.js Static Generation
│
▼ (Server Components)
HTML Estático + ES Modules
│
▼
Cloudflare Pages (CDN Global)
Todas las consultas a Sanity se ejecutan en tiempo de compilación. El resultado es HTML puro servido desde el edge de Cloudflare, sin necesidad de servidores Node.js en producción.
- Navegación por categorías (Cámaras, Iluminación, Audio, Grip, TV, etc.)
- Galería de imágenes con hotspot y zoom
- Especificaciones técnicas detalladas
- Filtros por categoría y búsqueda por nombre
- Vista de cuadrícula con información clave
- Formulario multi-sección con datos del cliente, selección de productos y servicios adicionales
- Control de stock: no permite agregar más unidades de las disponibles
- Vista previa de la cotización antes de enviar
- Envío directo a WhatsApp Business con formato profesional
- Sanity CMS como backend headless para gestionar productos, categorías y configuración del sitio
- El panel de administración se despliega en hosting externo de Sanity (no embebido en el frontend)
- Gestión completa de productos (campos agrupados: información general, detalles, imágenes, inventario)
- Editor visual de categorías con íconos Lucide
- Configuración del sitio (logo, datos de contacto, redes sociales)
- Editor de navegación
- Vista previa de drafts en desarrollo
- Metaetiquetas dinámicas con Open Graph y Twitter Cards
- Sitemap XML generado automáticamente con rutas de productos
- Schema.org JSON-LD para organización local
- Archivo robots.txt
- Generación estática total (páginas de carga instantánea)
- Tema oscuro/claro persistente en localStorage
black-rec-rental-house/
├── frontend/ ← Aplicación Next.js
│ ├── public/
│ │ ├── BlackRecLogo.webp
│ │ ├── BlackRecLogoHeroSection.webp
│ │ └── _redirects ← Reglas de redirección (404 personalizado)
│ ├── schema/ ← Esquemas de Sanity CMS
│ │ ├── product.ts
│ │ ├── category.ts
│ │ ├── siteSettings.ts
│ │ └── navigation.ts
│ ├── scripts/
│ │ └── fetch-data.mjs ← Precarga IDs de productos para SSG (se ejecuta via prebuild)
│ ├── src/
│ │ ├── app/ ← Rutas del App Router
│ │ ├── features/ ← Lógica por funcionalidad
│ │ ├── components/ ← Componentes globales
│ │ ├── lib/sanity/ ← Capa de datos Sanity
│ │ └── context/ ← Tema oscuro/claro
│ ├── .env.example
│ ├── next.config.js
│ ├── sanity.config.ts
│ ├── sanity.cli.ts
│ ├── tsconfig.json
│ └── package.json
│
├── .github/workflows/
│ └── deploy-cloudflare.yml ← CI/CD automático
│
└── README.md ← Este archivo
- Node.js 22+
- pnpm 11+
- Una cuenta en Sanity con un proyecto creado
cp frontend/.env.example frontend/.envEdita frontend/.env con los valores de tu proyecto Sanity:
NEXT_PUBLIC_SITE_URL=http://localhost:3000
NEXT_PUBLIC_SANITY_STUDIO_PROJECT_ID=tu_project_id
NEXT_PUBLIC_SANITY_STUDIO_DATASET=productioncd frontend
pnpm installpnpm devAbre http://localhost:3000.
Nota: En desarrollo las consultas a Sanity no usan CDN (
useCdn: false), lo que permite ver drafts y datos recién editados. Las consultas también tienen fallback silencioso para evitar errores si no hay conexión.
pnpm buildGenera el sitio estático en frontend/out/. Para previsualizarlo:
pnpm start| Comando | Descripción |
|---|---|
pnpm dev |
Servidor de desarrollo con Turbopack |
pnpm build |
Build de producción completo |
pnpm start |
Sirve out/ localmente |
pnpm lint |
ESLint en src/ |
pnpm typecheck |
Verificación de tipos con TypeScript |
pnpm sanity |
CLI de Sanity |
pnpm clean |
Elimina caché de .next |
| Esquema | Tipo | Propósito |
|---|---|---|
product |
Documento | Cada equipo disponible para alquiler |
category |
Documento | Clasificación de productos |
siteSettings |
Singleton | Configuración global del sitio |
navigation |
Singleton | Enlaces del menú de navegación |
- Stock: Un producto se muestra en el catálogo SOLO si
quantity > 0. No hay camposinStocknishowInCatalog— la disponibilidad se deriva automáticamente del inventario. - Destacados: El campo
featuredpermite marcar productos para la sección "Productos Destacados" de la página principal. - Categorías: Utilizan nombres de íconos de Lucide React para mostrar el ícono correspondiente en la interfaz.
Las consultas están optimizadas con proyecciones explícitas (sin ...) para minimizar el payload. Archivo clave: frontend/src/lib/sanity/queries.ts.
El sitio se despliega como sitio estático en Cloudflare Pages. El build genera ~80 páginas HTML estáticas.
cd frontend
pnpm build # Genera frontend/out/
pnpm dlx wrangler pages deploy ./out --project-name=black-rec-rental-houseEl repositorio incluye un workflow de GitHub Actions listo. Para activarlo:
-
En GitHub: Configura los siguientes repository secrets y variables en
Settings → Secrets and variables → Actions:Secrets:
CLOUDFLARE_API_TOKEN— Token de Cloudflare con permisosPages:EditCLOUDFLARE_ACCOUNT_ID— Account ID de Cloudflare
Variables:
NEXT_PUBLIC_SANITY_STUDIO_PROJECT_IDNEXT_PUBLIC_SANITY_STUDIO_DATASETNEXT_PUBLIC_SITE_URL
-
En Cloudflare Pages: Configura las mismas variables como build-time environment variables en el dashboard del proyecto.
-
Haz push a
main— el workflow se dispara automáticamente.
Puedes configurar un webhook en Sanity CMS para disparar un rebuild cuando se actualicen productos:
- En Sanity Dashboard → API → Webhooks
- Crear webhook con URL:
https://api.github.com/repos/{tu-usuario}/{tu-repo}/dispatches - Método:
POST - Headers:
Authorization: Bearer {github_token},Content-Type: application/json - Payload:
{"event_type": "sanity-update"} - Disparar en:
create,update,deletede documentosproduct
| Variable | Local (.env) |
GitHub Actions (vars) | Cloudflare Pages (build) |
|---|---|---|---|
NEXT_PUBLIC_SANITY_STUDIO_PROJECT_ID |
✓ | ✓ | ✓ |
NEXT_PUBLIC_SANITY_STUDIO_DATASET |
✓ | ✓ | ✓ |
NEXT_PUBLIC_SITE_URL |
✓ | ✓ | ✓ |
CLOUDFLARE_API_TOKEN |
✗ | ✓ (secret) | ✗ |
CLOUDFLARE_ACCOUNT_ID |
✗ | ✓ (secret) | ✗ |
El workflow deploy-cloudflare.yml (en .github/workflows/) ejecuta:
on:
push:
branches: [main]
repository_dispatch:
types: [sanity-update]Pasos del workflow:
actions/checkout@v4pnpm/action-setup@v4— Configura pnpm 11actions/setup-node@v4— Node.js 22 con caché de pnpmpnpm install --frozen-lockfile— Dependencias exactasnode scripts/fetch-data.mjs— Precarga IDs de productos desde Sanitynext build(conNODE_OPTIONS=--max-old-space-size=4096) — Build completocloudflare/wrangler-action@v3— Despliegafrontend/out/en Pages
El workflow incluye control de concurrencia: si se dispara un nuevo build mientras otro está en progreso, el anterior se cancela automáticamente.
- Accede a Sanity Studio (en el dashboard de manage.sanity.io)
- Ve a "Productos" → "Crear nuevo"
- Completa los campos (nombre, marca, categoría, precio, cantidad, imágenes, etc.)
- Publica el documento
- El sitio se regenera automáticamente en el próximo deploy
- Accede a Sanity Studio (en el dashboard de manage.sanity.io)
- En "Configuración del Sitio" puedes cambiar: nombre, email, teléfono, WhatsApp, logo, redes sociales
- En "Navegación" puedes editar los enlaces del menú
El sitio persiste la preferencia del usuario en localStorage bajo la clave black-rec-theme. Se puede cambiar con el botón de alternancia en el Navbar.
Copyright © 2025 Daniel Esteban Pedroza Polo. Todos los derechos reservados.
Black Rec Rental House — Colombia ricardoflorianleon@gmail.com | +57 300 677 7805