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.

2026 · En desarrollo

Captura de Diamante
Diamante — captura del proyecto.
01

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.

02

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.
03

Stack detallado

CapaTecnologíaDetalle
FrontendAstro 7 + React 19SSG + SSR selectivo; sitemap vía @astrojs/sitemap
CMSStrapi 5.52users-permissions, plugin-cloud, REST auto-generado
BDPostgreSQLDriver pg; SQLite solo dev local
MediaCloudinaryProvider oficial de uploads
DeployVercel (web)diamante-nu.vercel.app
05

Endpoints principales

MétodoRutaQué haceAuth
GET/api/noticias?populate=*Noticias con categorías e imágenesToken Strapi / público
GET/api/galeria-items · /api/sedes · /api/especialidadesContenido institucionalPúblico
POST/api/mensaje-contacto · /api/solicitud-pqrsf · /api/denuncia-corrupcionFormularios ciudadanosPúblico + captcha/rate-limit
GET/api/pagina-inicio · /api/configuracion-generalHome y ajustes globalesPúblico
06

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)
07

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.
08

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.
09

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
10

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.
11

Retos y soluciones

20+ páginas sin duplicar fetchHelpers GET centralizados en /web/src/pages/api + layouts compartidos.
Imágenes pesadasCloudinary con transformaciones (responsive + lazy).
12

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).
13

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
14

Próximos pasos

  • Búsqueda full-text de noticias/documentos.
  • Portal de admisiones con trazabilidad.
  • Internacionalización.
↗

Seguir explorando