Diamante
Sitio institucional + CMS Strapi (Astro + Strapi)
Sistema institucional full stack: frontend en Astro 7 + React 19 con más de 20 páginas (noticias, galería, sedes, especialidades, PQRSF, admisiones) y backend CMS en Strapi 5 con PostgreSQL y Cloudinary para gestionar noticias, galerías, sedes, documentos, slides y solicitudes. Desplegado en diamante-nu.vercel.app.
Contexto y propósito
Diamante es un sistema institucional full stack: web pública en Astro 7 + React 19 y CMS headless en Strapi 5 con PostgreSQL y Cloudinary. La web tiene 20+ páginas (identidad, noticias, galería, sedes, especialidades, admisiones, PQRSF, corrupción, contacto) y todo el contenido dinámico sale de Strapi.
Verificado en el repo: /web (Astro) con src/pages/*.astro + /api, /strapi con ~20 content-types en src/api, /data con state_store.db y strapi/.env.example. Deploy web en diamante-nu.vercel.app.
Propósito declarado: Digitalizar la presencia y gestión de contenido de una institución educativa: noticias, galerías, sedes, especialidades, documentos institucionales y canales de atención ciudadana.
Arquitectura
Frontend Astro 7 desacoplado que consume la API REST de Strapi 5. Strapi con ~20 content-types (noticia, galeria-item, sede, especialidad, slide-carrusel, solicitud-pqrsf, mensaje-contacto, etc.), PostgreSQL como base y Cloudinary como provider de uploads.
Editores ──▶ Strapi 5 Admin ──▶ PostgreSQL
│ uploads ──▶ Cloudinary
▼ REST /api/*
Astro 7 SSG/SSR (diamante-nu.vercel.app)
noticias · galería · sedes · especialidades · PQRSF · admisiones - Desacople total: Strapi solo expone REST; Astro hace fetch en build/SSR y genera páginas estáticas rápidas con islas React donde hay interactividad.
- Content-types: noticia, categoria-noticia, galeria-item, categoria-galeria, sede, especialidad, slide-carrusel, documento-institucional, pagina-* (inicio, identidad, contacto, admisiones, conexiones, invitaciones-home), configuracion-general, mensaje-contacto, solicitud-pqrsf, denuncia-corrupcion, invitacion-contratacion.
- Uploads a Cloudinary vía @strapi/provider-upload-cloudinary; PG vía pg driver; state local en data/state_store.db para utilidades.
Stack detallado
| Capa | Tecnología | Detalle |
|---|---|---|
| Frontend | Astro 7 + React 19 | SSG + SSR selectivo; sitemap vía @astrojs/sitemap |
| CMS | Strapi 5.52 | users-permissions, plugin-cloud, REST auto-generado |
| BD | PostgreSQL | Driver pg; SQLite solo dev local |
| Media | Cloudinary | Provider oficial de uploads |
| Deploy | Vercel (web) | diamante-nu.vercel.app |
Endpoints principales
| Método | Ruta | Qué hace | Auth |
|---|---|---|---|
GET | /api/noticias?populate=* | Noticias con categorías e imágenes | Token Strapi / público |
GET | /api/galeria-items · /api/sedes · /api/especialidades | Contenido institucional | Público |
POST | /api/mensaje-contacto · /api/solicitud-pqrsf · /api/denuncia-corrupcion | Formularios ciudadanos | Público + captcha/rate-limit |
GET | /api/pagina-inicio · /api/configuracion-general | Home y ajustes globales | Público |
Datos y conexiones
noticia *──1 categoria-noticia · galeria-item *──1 categoria-galeria sede 1──* especialidad · slide-carrusel (home) documento-institucional (manual, PEI, útiles, resoluciones) mensaje-contacto · solicitud-pqrsf · denuncia-corrupcion (escritura pública)
Autenticación y seguridad
- Roles Strapi (public/authenticated) por content-type; escritura pública solo en formularios.
- Validación de uploads (tipo/tamaño) en Cloudinary; CORS restringido al dominio Vercel.
Frontend y rutas
/ (home con slides)/noticias/*, /galeria, /sedes/*, /especialidades/*/mision, /vision, /valores, /pei, /organigrama, /directorio/inscripciones, /contratacion, /peticiones-quejas-y-reclamos, /denuncias, /contacto, /canales
- Muchas páginas son Markdown/collections + fetch a Strapi; sitemap.xml.ts dinámico.
- Formularios POST directo a Strapi con estados y validación cliente.
Despliegue
Dónde: Vercel (web) + Strapi en VPS/Render + PostgreSQL gestionado + Cloudinary
- Web: pnpm build en /web con STRAPI_URL pública
- Strapi: strapi build && strapi start con .env (DB + Cloudinary + JWT secrets)
- Revalidar Astro al publicar en Strapi (webhook → redeploy)
Variables de entorno clave (.env — tú pones los valores):
STRAPI_URL, STRAPI_TOKEN DATABASE_URL, CLOUDINARY_NAME/KEY/SECRET JWT_SECRET, ADMIN_JWT_SECRET, API_TOKEN_SALT
Metodología y decisiones
- CMS-first: primero se modelan content-types, luego las páginas Astro los consumen.
- Contenido versionable: documentos institucionales como colección, no PDFs sueltos.
- Accesibilidad y SEO para sector público/educativo.
Retos y soluciones
Qué aprendí
- Modelado CMS real con Strapi 5.
- SSG a escala con decenas de rutas y sitemap dinámico.
- Formularios públicos seguros (PQRSF/denuncias).
Ejecutar en local
Web: cd diamante/web && pnpm install && pnpm dev (→ :4321) CMS: cd diamante/strapi && npm install && cp .env.example .env && npm run develop (→ :1337) Configurar STRAPI_URL en la web hacia http://localhost:1337
Próximos pasos
- Búsqueda full-text de noticias/documentos.
- Portal de admisiones con trazabilidad.
- Internacionalización.