Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/danitocsc/transporte-unrc-web-public/llms.txt

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

loadSiteData() es la función de carga de datos server-side de Transporte Tijuana. Lee en paralelo los dos archivos JSON estáticos que alimentan la página /informe — el payload del resumen estadístico y el payload del mapa de calor — y los devuelve tipados. Al importar node:fs, esta función solo puede ejecutarse en un entorno Node.js y nunca en el cliente.
Esta función es exclusivamente server-side. Importa node:fs directamente, por lo que Next.js la excluye automáticamente del bundle del cliente. Si se llama desde un Server Component, el módulo completo no cruza la frontera al navegador.

Archivo fuente completo

import { promises as fs } from "node:fs";
import path from "node:path";

import type { MapPayload, SummaryPayload } from "@/types/transport";

const SUMMARY_PATH = path.join(process.cwd(), "public", "data", "summary.json");
const MAP_PATH = path.join(process.cwd(), "public", "data", "map_points.json");

async function readJsonFile<T>(filePath: string): Promise<T> {
  const contents = await fs.readFile(filePath, "utf-8");
  return JSON.parse(contents) as T;
}

export async function loadSiteData(): Promise<{
  summary: SummaryPayload;
  map: MapPayload;
}> {
  const [summary, map] = await Promise.all([
    readJsonFile<SummaryPayload>(SUMMARY_PATH),
    readJsonFile<MapPayload>(MAP_PATH),
  ]);

  return { summary, map };
}

Rutas de los archivos de datos

Las rutas se resuelven con path.join(process.cwd(), ...) en lugar de rutas relativas al archivo fuente, ya que process.cwd() apunta al directorio web/ cuando Next.js ejecuta el servidor de producción:
ConstanteRuta resuelta en producción
SUMMARY_PATHweb/public/data/summary.json
MAP_PATHweb/public/data/map_points.json
Estos archivos JSON están en public/data/ lo que significa que también son accesibles públicamente desde el navegador en las rutas /data/summary.json y /data/map_points.json. La función loadSiteData() los lee directamente desde disco en el servidor para evitar una solicitud HTTP adicional durante el renderizado.

readJsonFile<T>

Función auxiliar genérica interna (no exportada) que abstrae la lectura y parseo de cualquier archivo JSON:
async function readJsonFile<T>(filePath: string): Promise<T> {
  const contents = await fs.readFile(filePath, "utf-8");
  return JSON.parse(contents) as T;
}
Usa fs.promises.readFile (la API asíncrona basada en promesas de node:fs) para no bloquear el event loop de Node.js durante la lectura de disco.

Carga en paralelo con Promise.all

Ambos archivos se leen de forma concurrente para minimizar la latencia de I/O en el servidor:
const [summary, map] = await Promise.all([
  readJsonFile<SummaryPayload>(SUMMARY_PATH),
  readJsonFile<MapPayload>(MAP_PATH),
]);
Si cualquiera de los dos archivos falla (no existe, está malformado, permisos insuficientes), Promise.all rechaza con el primer error y la página mostraría un error 500 de Next.js.

Tipo de retorno

Promise<{
  summary: SummaryPayload;
  map: MapPayload;
}>
summary
SummaryPayload
Payload completo del informe estadístico. Contiene métricas agregadas, series de datos para las gráficas, sugerencias analizadas e información de autoría. Ver SummaryPayload para la referencia completa de campos.
map
MapPayload
Payload del mapa de calor. Contiene el arreglo de puntos geolocalizados anonimizados, las coordenadas del centro y los bounds del encuadre sugerido. Ver MapPayload.

Uso en el Server Component

loadSiteData() se llama en el Server Component de la página /informe (web/app/informe/page.tsx). Al ser el componente un async function, Next.js lo renderiza en el servidor y serializa los datos como props para los componentes cliente:
// web/app/informe/page.tsx
export default async function HomePage() {
  const { summary, map } = await loadSiteData();
  // summary.metrics.totalResponses → 192
  // map.points.length → 190
}
Los datos de summary y map fluyen hacia abajo como props a los componentes de visualización:
loadSiteData()          ← Node.js fs, servidor

InformePage (Server Component)
    ├── <ChartCard data={summary.series.turnos} />
    ├── <ChartCard data={summary.series.dias} />
    ├── <ChartCard data={summary.series.colonias} />
    ├── <VideoPlayer src={...} />
    └── <DashboardMapLoader data={map} />

                    DashboardMap (cliente, ssr: false)
                    renderiza map.points como heatmap

Por qué no usar fetch() en el servidor

En Next.js es técnicamente posible hacer fetch('/data/summary.json') desde un Server Component, pero leer el archivo directamente con fs es preferible aquí porque:
  1. Sin overhead de red: evita una solicitud HTTP loopback al propio servidor.
  2. Sin caché HTTP: los datos siempre se leen frescos desde disco en cada petición.
  3. Tipado seguro: readJsonFile<SummaryPayload> garantiza el tipo en tiempo de compilación.

Build docs developers (and LLMs) love