Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ivanespinosa/esg-mexico-sitio-web/llms.txt

Use this file to discover all available pages before exploring further.

Sanity actúa como la fuente única de verdad para todo el contenido editorial del sitio: artículos del blog, noticias, autoras y etiquetas. El sitio consume Sanity a través de su API CDN usando el cliente oficial @sanity/client; el contenido se obtiene en tiempo de build mediante queries GROQ y se pre-renderiza como HTML estático. El Sanity Studio —incluido en la carpeta studio/— es la interfaz de edición para el equipo de contenido.

Cliente Sanity

La instancia del cliente se crea en src/lib/sanity.ts y se reutiliza en todo el proyecto. Usa el CDN de Sanity (useCdn: true) para máxima velocidad en lecturas de build.
src/lib/sanity.ts — cliente
import { createClient } from '@sanity/client'

export const sanity = createClient({
  projectId: import.meta.env.PUBLIC_SANITY_PROJECT_ID,
  dataset:   import.meta.env.PUBLIC_SANITY_DATASET ?? 'production',
  apiVersion: '2024-01-01',
  useCdn: true,
})
apiVersion: '2024-01-01' fija la versión de la API para garantizar compatibilidad. Actualizar este valor a una fecha más reciente puede desbloquear nuevas funcionalidades de GROQ pero requiere pruebas de regresión.

Funciones de imagen

El mismo módulo src/lib/sanity.ts exporta tres utilidades para construir URLs optimizadas desde el Image Pipeline de Sanity CDN.

sanityImg

Aplica transformaciones de redimensión, recorte y formato automático a una URL del CDN. Las URLs que no pertenecen a cdn.sanity.io se devuelven sin modificar.
src/lib/sanity.ts — sanityImg
export function sanityImg(
  url: string | undefined,
  opts: { w: number; h?: number; q?: number } = { w: 640 },
): string {
  if (!url || !url.includes('cdn.sanity.io')) return url ?? ''
  const params = new URLSearchParams()
  params.set('w', String(opts.w))
  if (opts.h) {
    params.set('h', String(opts.h))
    params.set('fit', 'crop')
  }
  params.set('auto', 'format')
  params.set('q', String(opts.q ?? 75))
  return `${url}${url.includes('?') ? '&' : '?'}${params.toString()}`
}
ParámetroTipoDefaultDescripción
urlstring | undefinedURL pública de la imagen en Sanity CDN
opts.wnumber640Ancho en píxeles
opts.hnumberAlto en píxeles; activa fit=crop
opts.qnumber75Calidad de compresión (1–100)

sanitySrcset

Genera una cadena srcset con múltiples anchos para imágenes responsivas. Ideal para el atributo srcset de <img> o <source>.
src/lib/sanity.ts — sanitySrcset
export function sanitySrcset(
  url: string | undefined,
  widths: number[] = [400, 640, 960],
): string {
  if (!url || !url.includes('cdn.sanity.io')) return ''
  return widths.map((w) => `${sanityImg(url, { w })} ${w}w`).join(', ')
}
Ejemplo de salida:
https://cdn.sanity.io/images/.../foto.jpg?w=400&auto=format&q=75 400w,
https://cdn.sanity.io/images/.../foto.jpg?w=640&auto=format&q=75 640w,
https://cdn.sanity.io/images/.../foto.jpg?w=960&auto=format&q=75 960w

imageUrl

Convierte una referencia interna de Sanity (formato image-HASH-WxH-ext) en una URL pública del CDN, sin aplicar transformaciones adicionales.
src/lib/sanity.ts — imageUrl
export function imageUrl(ref: string | undefined): string {
  if (!ref) return ''
  const projectId = import.meta.env.PUBLIC_SANITY_PROJECT_ID
  const dataset   = import.meta.env.PUBLIC_SANITY_DATASET ?? 'production'
  // ref format: image-HASH-WxH-ext
  const [, id, dims, ext] = ref.split('-')
  return `https://cdn.sanity.io/images/${projectId}/${dataset}/${id}-${dims}.${ext}`
}

Esquemas de contenido

El Sanity Studio define cuatro tipos de documentos. A continuación se describe cada uno con sus campos clave.
Tipo principal del blog. Agrupa sus campos en tres pestañas: Contenido, Metadatos y SEO.
studio/schemas/blogPost.ts — campos principales
defineType({
  name: 'blogPost',
  title: 'Artículos del Blog',
  type: 'document',
  fields: [
    { name: 'title',       type: 'string',    /* min:10, max:120, required */ },
    { name: 'slug',        type: 'slug',      /* source: title, max:96, required */ },
    { name: 'author',      type: 'reference', /* → author, required */ },
    { name: 'date',        type: 'date',      /* required */ },
    { name: 'category',    type: 'string',    /* radio list, required */ },
    { name: 'tags',        type: 'array',     /* references → tag[] */ },
    { name: 'featured',    type: 'boolean',   /* default: false */ },
    { name: 'coverImage',  type: 'image',     /* hotspot, required */ },
    { name: 'excerpt',     type: 'text',      /* max:300, warning >160 */ },
    { name: 'body',        type: 'array',     /* Portable Text, required */ },
    { name: 'readingTime', type: 'number',    /* default: 5 */ },
  ],
})
Categorías disponibles: Estrategia ESG · Regulación y Cumplimiento · Reportes y Estándares · Sostenibilidad Financiera · Fundaciones · Casos y TendenciasEl campo body admite bloques de tipo block (con estilos h2, h3, blockquote, marcadores strong/em y anotaciones de enlace) e image con campos alt y caption.

Queries GROQ

Todas las queries del sitio están centralizadas en src/lib/queries.ts. Se ejecutan en tiempo de build con sanity.fetch(QUERY, params).
*[_type == "blogPost"] | order(date desc) {
  _id,
  title,
  "slug": slug.current,
  excerpt,
  date,
  category,
  featured,
  readingTime,
  "coverImage": coverImage.asset->url,
  "author": author-> {
    name,
    "slug": slug.current,
    role,
    "photo": photo.asset->url,
    "signatureUrl": signature.asset->url,
    linkedin,
    twitter,
    instagram,
  },
  "tags": tags[]->{ name, "slug": slug.current },
}
  • "slug": slug.current — desnormaliza el objeto slug a string directo.
  • author-> y coverImage.asset-> — dereferencia las referencias de Sanity en una sola query, evitando N+1.
  • tags[]->{ ... } — itera el array de referencias y proyecta solo los campos necesarios.
  • $slug en BLOG_POST_QUERY — parámetro de query tipado; se pasa como sanity.fetch(BLOG_POST_QUERY, { slug }).
  • | order(date desc) — orden cronológico inverso por defecto en listados.

Colecciones de contenido (Astro)

Además de Sanity, el proyecto mantiene colecciones locales en src/content/ para contenido estático (archivos .md y .json). Los schemas se validan con Zod en src/content.config.ts.
src/content.config.ts
import { defineCollection, z } from "astro:content";
import { glob } from "astro/loaders";

const blog = defineCollection({
  loader: glob({ pattern: "**/*.md", base: "./src/content/blog" }),
  schema: z.object({
    title: z.string(),
    excerpt: z.string(),
    date: z.coerce.date(),
    author: z.enum(["ximena-ugarte", "valeria-garcia"]),
    category: z.enum([
      "Regulación y Cumplimiento",
      "Reportes y Estándares",
      "Estrategia ESG",
      "Fundaciones",
      "Sostenibilidad Financiera",
      "Casos y Tendencias",
    ]),
    tags: z.array(z.string()).default([]),
    coverImage: z.string(),
    readingTime: z.number(),
    featured: z.boolean().default(false),
  }),
});

const noticias = defineCollection({
  loader: glob({ pattern: "**/*.json", base: "./src/content/noticias" }),
  schema: z.object({
    title: z.string(),
    date: z.coerce.date(),
    image: z.string(),
    excerpt: z.string(),
    externalUrl: z.string().url(),
    category: z.enum(["Medio", "Evento", "Premio", "Aparición"]),
  }),
});

export const collections = { blog, noticias };
Las colecciones locales (src/content/) son independientes del contenido en Sanity. El sitio puede servir artículos desde ambas fuentes simultáneamente. En producción, Sanity es la fuente principal para contenido nuevo; los archivos locales pueden contener contenido migrado o de prueba.

Sanity Studio

El Studio está en la carpeta studio/ con su propia configuración en studio/sanity.config.ts. Incluye el structureTool con navegación personalizada y el visionTool para ejecutar queries GROQ interactivas.
1

Instalar dependencias del Studio

Desde la raíz del repositorio
cd studio
npm install
2

Configurar variables de entorno del Studio

Crea el archivo studio/.env con las credenciales del proyecto:
studio/.env
SANITY_STUDIO_PROJECT_ID=xxxxxxxxx
SANITY_STUDIO_DATASET=production
3

Iniciar el Studio en local

Servidor de desarrollo del Studio
cd studio
npx sanity dev
# Studio disponible en http://localhost:3333
4

Desplegar el Studio (opcional)

Publicar Studio en sanity.io/studios
cd studio
npx sanity deploy
Esto publica el Studio en una URL https://<nombre>.sanity.studio accesible para el equipo editorial sin necesidad de ejecutar nada localmente.
La estructura de navegación del Studio organiza los tipos de documentos en dos grupos separados por un divisor:

Contenido editorial

📝 Artículos del Blog — documentos blogPost
📰 Noticias — documentos noticia

Datos de referencia

👤 Autoras — documentos author
🏷️ Etiquetas — documentos tag

Build docs developers (and LLMs) love