Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/DincaAlex/unilink/llms.txt

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

server/data.sqlite is a WAL-mode SQLite database managed by better-sqlite3. The file does not need to exist before the first run — db.js creates it automatically when the backend starts, executes all CREATE TABLE IF NOT EXISTS statements, then checks whether the jobs table is empty. If it is, a single atomic transaction seeds the database with 14 demo job listings, two user accounts, one student profile, and one company profile. No migration tool or manual setup step is needed.

Auto-seed behaviour

When jobCount === 0 on startup, db.js runs a db.transaction() that inserts every record from seedData.js in one commit. This means the seed runs only once — on the very first start. After that, the data persists across restarts in server/data.sqlite. The seed inserts:
  • 2 users — one estudiante (admin@unmsm.edu.pe) and one empresa (maria.fernandez@talenthub.pe)
  • 14 jobs — a mix of interna (UNMSM-posted) and externa (private-sector) internships
  • 1 student — Juan Pérez, Ingeniería de Sistemas, 7° semester
  • 1 company — María Fernández, TalentHub Perú

Tables

users

Stores login credentials for both demo accounts.
ColumnTypeNotes
idINTEGER PK
emailTEXT UNIQUE
passwordTEXTPlain text — demo only, no hashing
roleTEXTestudiante or empresa

students

One row only — the single student profile (always id = 1).
ColumnTypeNotes
idINTEGER PKAlways 1
nameTEXTProfile fields
careerTEXTe.g. Ingeniería de Sistemas e Informática
facultyTEXT
semesterTEXTe.g. 7° semestre
gpaTEXTe.g. 15.2
emailTEXTContact fields
phoneTEXT
locationTEXT
bioTEXT
skillsTEXTJSON array of skill strings
languagesTEXTJSON array of { lang, level } objects
certificationsTEXTJSON array of { name, issuer, year } objects
experienceTEXTJSON array of { id, role, org, period, desc } objects
educationTEXTJSON object { degree, university, years }
savedJobsTEXTJSON array of saved job IDs

companies

One row only — the single company/recruiter profile (always id = 1). Shares the same contact and JSON-serialised columns as students, but replaces the student-specific fields with company fields. There is no savedJobs column.
ColumnTypeNotes
idINTEGER PKAlways 1
contactNameTEXTRecruiter’s name
roleTEXTRecruiter’s job title
companyNameTEXT
industryTEXT
companyDescriptionTEXT
websiteTEXT
initialsTEXTTwo-letter avatar initials
colorTEXTHex accent colour for the avatar
emailTEXTContact fields
phoneTEXT
locationTEXT
bioTEXT
skillsTEXTJSON array of skill strings
languagesTEXTJSON array of { lang, level } objects
certificationsTEXTJSON array of { name, issuer, year } objects
experienceTEXTJSON array of { id, role, org, period, desc } objects
educationTEXTJSON object { degree, university, years }

jobs

One row per internship listing. Arrays (requirements, benefits, skills) are stored as JSON strings.
ColumnTypeNotes
idINTEGER PK
titleTEXT
companyTEXTDisplay name of the posting organisation
locationTEXTe.g. Lima, Híbrido
typeTEXTinterna or externa
modalityTEXTPresencial / Híbrido / Remoto
areaTEXTe.g. Tecnología, Finanzas, Legal
salaryTEXTFormatted string, e.g. S/ 1,800 / mes
salaryNumINTEGERNumeric salary for range filtering
postedTEXTHuman-readable string, e.g. Hace 2 días
deadlineTEXTISO date string YYYY-MM-DD
daysAgoINTEGERDays since posted, used for recency filter
durationTEXTe.g. 3 meses, 6 meses
hoursPerWeekINTEGERWeekly commitment
statusTEXTabierto / por_cerrar / cerrado
initialsTEXTTwo-letter initials for the company avatar
colorTEXTHex accent colour for the company avatar
descriptionTEXTFull job description
requirementsTEXTJSON array of requirement strings
benefitsTEXTJSON array of benefit strings
skillsTEXTJSON array of required skill strings
applicantsINTEGERApplicant count (display only)
postedByTEXTEmail of the empresa account that created the listing; null for seeded jobs

applications

One row per student application. The student ID is always 1 in the current prototype.
ColumnTypeNotes
idINTEGER PK AUTOINCREMENT
studentIdINTEGERFK to students.id (always 1)
jobIdINTEGERFK to jobs.id
statusTEXTen_revision / entrevista / rechazado / aceptado
appliedDateTEXTISO date YYYY-MM-DD

JSON column pattern

The students, companies, and jobs tables store arrays and nested objects as JSON strings. db.js serialises them with JSON.stringify() before every INSERT or UPDATE, and the route handlers in index.js deserialise them with JSON.parse() before returning responses to the client:
server/index.js
function parseJob(row) {
  if (!row) return row
  return {
    ...row,
    requirements: JSON.parse(row.requirements),
    benefits: JSON.parse(row.benefits),
    skills: JSON.parse(row.skills),
  }
}
This avoids the complexity of normalising these fields into separate tables while keeping the SQLite schema flat and easy to inspect.

Resetting the database

To wipe all data and reseed from scratch: stop the backend, delete server/data.sqlite (and server/data.sqlite-wal / server/data.sqlite-shm if they exist), then restart with npm run dev. The seed transaction runs automatically on the next startup.

Inspecting the database

Any SQLite client can read server/data.sqlite while the backend is stopped. Options include IntelliJ Ultimate’s built-in Database tool (Data Source → SQLite), DB Browser for SQLite, or the sqlite3 CLI. Point the client at server/data.sqlite in the repo root.

Build docs developers (and LLMs) love