NuestraVoz is organized as a pnpm monorepo with two applications and one shared library, all managed from a single repository. The workspace topology — declared inDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/Renzo717/Aula-Virtual-Universidad-Radiolocucion/llms.txt
Use this file to discover all available pages before exploring further.
pnpm-workspace.yaml — ensures that internal packages resolve through pnpm’s workspace protocol rather than being published to a registry. This keeps types, validation schemas, and utility helpers in sync across the frontend and backend without any duplication.
Monorepo Layout
Package Roles
@nuestravoz/web — Astro + React Frontend
The web application is a server-side-rendered Astro site using the @astrojs/node adapter in standalone mode. Static shell pages (.astro) handle routing, authentication guards, and layout; interactive components (.tsx) are hydrated as React islands where needed.
Key dependencies from apps/web/package.json:
| Package | Version | Purpose |
|---|---|---|
astro | ^5.5.3 | SSR framework + dev server |
@astrojs/react | ^4.2.1 | React island integration |
@astrojs/node | ^9.1.0 | Node.js standalone adapter |
@astrojs/tailwind | ^6.0.0 | Tailwind CSS integration |
react | ^19.0.0 | UI component library |
@nuestravoz/shared | workspace:* | Local types and schemas |
output: 'server' (full SSR), runs on port 4321, and registers a Vite proxy that forwards every /api/* request to the Express server at http://localhost:3001.
@nuestravoz/api — Express.js REST API
The API is a standard Express.js + TypeScript server. It mounts the following route groups, each in its own file under src/routes/:
helmet— sets security-oriented HTTP headers;crossOriginResourcePolicyis set tocross-originto allow Supabase Storage URLs.cors— restricts origins to the value ofCORS_ORIGINwith credentials enabled, so cookies are sent cross-origin in production.express.json()— parses JSON request bodies.cookie-parser— parses thenv_sessioncookie used for session authentication.
apps/api/.env through a lib/config.ts module that exports typed constants (config.port, config.corsOrigin, etc.).
@nuestravoz/shared — Shared TypeScript Library
packages/shared is the single source of truth for every type and validation rule consumed by both the frontend and the backend. Its src/index.ts re-exports four modules:
types.ts) include: UserRole, UserStatus, CarreraTipo, Profile, AuthUser, Carrera, Materia, Curso, Inscripcion, Actividad, Entrega, ForoHilo, ForoRespuesta, NotaFinal, BoletinMateriaFila, DashboardStats, and many more.
Zod schemas (schemas.ts) mirror every write operation — loginSchema, registerSchema, createUserSchema, createCarreraSchema, createMateriaSchema, createActividadSchema, upsertNotaFinalSchema, and so on. Each schema is paired with an inferred TypeScript input type (e.g. LoginInput, CreateUserInput) so both API route handlers and frontend form validation share identical rules.
Schedule helpers (horarios.ts) provide formatHorarios, parseHorarioLegacy, horariosFromDb, and sanitizeHorarios — pure functions that normalize the HorarioCursado[] structure used across Materia and Curso records.
Data Flow
/api/* which is proxied to Express. The Supabase service-role key never reaches the browser.
Supabase: Auth, Storage, and RLS
Supabase serves three roles in the platform: PostgreSQL database — All application data lives in Supabase’s managed Postgres. Thedatabase.types.ts file (auto-generated by the Supabase CLI) provides fully-typed table and view definitions consumed by both the API and the shared package.
Row Level Security — RLS policies (first introduced in migration 002_fix_rls_policies.sql and refined through 010_preceptor_role.sql) enforce per-role visibility at the database layer. Even if the API were compromised, users could only read and write rows their role is authorized for.
Supabase Storage — Activity material attachments, student submission files, and resource documents are stored in Supabase Storage buckets. The API uploads files server-side using the service-role key and returns signed or public URLs to the frontend.
Versioned Migrations — The supabase/migrations/ directory contains 19 sequential SQL files. Notable milestones include the initial schema (001), preceptor role addition (010), final grades (011, 016, 017), subject-in-courses relationship (018), and the most recent preceptor write-access grant (019_preceptor_notas_finales_write.sql).
pnpm Workspace Configuration
Thepnpm-workspace.yaml at the repo root declares which directories are workspace packages:
allowBuilds and onlyBuiltDependencies keys restrict native build scripts to esbuild (used by the API’s TypeScript compilation) and sharp (used by Astro for image optimization), improving install security and reproducibility.
The root package.json dev script compiles the shared package before launching servers in parallel:
@nuestravoz/web and @nuestravoz/api import freshly-built type declarations from packages/shared/dist/ at startup.
Further Reading
Quickstart
Step-by-step instructions to clone, configure, seed, and run the platform locally in under 10 minutes.
Introduction
Overview of the platform’s four user roles, core capabilities, and feature set.