Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/Taykl12/Classify/llms.txt

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

Classify ships with 15 ordered SQL migrations that build the complete database schema incrementally. You must apply all of them in sequence before starting the server. After the migrations run you also need to seed the roles table with the three built-in roles.
All migration files live in supabase/migrations/ and are numbered 001 through 015. Each file is idempotent in the sense that re-running an already-applied migration will not corrupt data, but the safest approach is to apply them once in order on a fresh Supabase project.

Applying the migrations

You have two options: the Supabase SQL editor (no extra tooling required) or the Supabase CLI (recommended for automated deployments).
1

Option A — Supabase SQL Editor

  1. Open your project in the Supabase Dashboard.
  2. Navigate to SQL Editor.
  3. For each file in supabase/migrations/, open the file locally, copy its contents, paste into the SQL editor, and click Run. Work through them in numerical order (001015).
You can concatenate all 15 files into a single script and run it in one go:
cat supabase/migrations/*.sql > full_schema.sql
Then paste full_schema.sql into the SQL editor and run it.
2

Option B — Supabase CLI

The Supabase CLI can apply migrations directly against your remote project.
# Install the CLI (if not already installed)
npm install -g supabase

# Link to your remote project (you will be prompted for your project ref)
supabase login
supabase link --project-ref <your-project-ref>

# Push all pending migrations
supabase db push
This approach is preferred for CI/CD pipelines because it tracks which migrations have already been applied.
3

Seed the roles table

After all migrations have been applied, insert the three built-in roles. Without this seed the application cannot assign roles to users and sign-up will fail.
INSERT INTO roles (id_rol, nombre_rol)
VALUES
  (1, 'admin'),
  (2, 'profesor'),
  (3, 'alumno');
Run this in the Supabase SQL editor or via supabase db execute.
The roles table is readable by both anonymous and authenticated users (the RLS policy grants public SELECT access). This allows the sign-up form to list available roles without requiring a prior login.

Migration overview

The table below summarises what each migration does so you understand what is being applied to your database.
#Key changes
001Add estado_proyecto and es_favorito UI columns to grupos_proyectos
002Grant API roles on the public schema
003Add favorito columns and CRUD Row-Level Security policies to grupos_proyectos
004Drop legacy escuela and members tables (schema cleanup)
005Create create_grupo_proyecto RPC function
006Add RLS member-access policies
007Add project config columns: alcance_detalle, notas_alcance, anteproyecto_validado, link_respaldo, link_calificaciones, documentos
008Create the avatars profile storage bucket
009Create search_usuarios_dni search function
010Create create_tarea_grupo RPC function
011Create eventos_calendario table
012Create admin academic schema: cursos, materias, cursos_usuarios_asignados, materia_profesor
013Add division, materia, and horario columns to cursos
014Create asistencias attendance table
015Add project lock columns (lock_alcance, lock_documentacion, lock_equipo) and proyecto_asignado_profesor

Key tables

usuarios

Stores the user profile for every registered account, linked to Supabase Auth via the user UUID. Includes nombre, apellido, dni, foto_perfil (URL to the Storage avatar), and a foreign key to roles.

grupos_proyectos

The central project entity. Each row represents a student group’s project and tracks status, scope details, supporting links, document references, lock flags, and the assigned professor.

tareas_grupo

Tasks scoped to a specific project group. Created via the create_tarea_grupo RPC to ensure atomic assignment and permission checks.

eventos_calendario

Calendar events associated with courses or project groups, used to schedule milestones, presentations, and deadlines.

cursos

Academic course instances, including division, subject (materia), and schedule (horario). Used by the admin panel and linked to attendance records.

materias

The catalogue of subjects that can be assigned to courses and to professor accounts via the materia_profesor join table.

asistencias

Attendance records keyed to a user, a course, and a timestamp. Records can be created manually by a professor or automatically by an ESP32 device via the device token endpoint.

RPC functions

Classify uses PostgreSQL functions (called via supabase.rpc()) for operations that require atomicity or that need to bypass client-side permission boundaries safely.
FunctionMigrationPurpose
create_grupo_proyecto005Creates a new project group and assigns the calling user as the initial member in one atomic transaction
create_tarea_grupo010Creates a task and associates it with a project group, enforcing membership checks
search_usuarios_dni009Full-text search over user DNIs, used by the invite flow to find users without exposing the full usuarios table
Call these functions from the server using the user client so that the RPC executes under the caller’s RLS context:
const client = createUserClient(accessToken);
const { data, error } = await client.rpc('create_grupo_proyecto', { nombre: 'My Project' });

Row-Level Security policies

All sensitive tables have RLS enabled. The policies follow a consistent pattern:
  • usuarios — authenticated users can read only their own row (auth.uid() = id_usuario). Admin operations use the service role client which bypasses RLS entirely.
  • grupos_proyectos — a user can access a project row if they appear in proyecto_profesor (the assigned professor column) or are a member of the associated grupo_estudiante group.
  • roles — SELECT is open to both anonymous and authenticated callers so the sign-up form can list roles; INSERT/UPDATE/DELETE are restricted to the service role.
Do not disable RLS on any table in production. If a server route needs elevated access (e.g. a professor listing all projects in a course), use createAdminClient() in that route handler rather than weakening the table-level policy.

Profile avatars storage bucket

Migration 008 creates a Supabase Storage bucket named avatars. When a user uploads a profile photo the server stores the file in this bucket and writes the resulting public URL to usuarios.foto_perfil. The bucket is configured with the following access rules:
  • Authenticated users can upload and replace their own avatar (path scoped to their user UUID).
  • Public read is enabled so avatar URLs can be embedded in <img> tags without requiring a signed URL.
If the avatars bucket does not exist when the server starts (for example, if migration 008 was skipped), avatar uploads will fail with a storage error. Verify the bucket is present under Storage in the Supabase Dashboard after running the migrations.

Build docs developers (and LLMs) love