Skip to content

CV en PDF

HUMAE genera automáticamente un CV profesional con la identidad de marca, listo para compartir. No requiere que el candidato diseñe nada — se produce desde el perfil ya capturado.

Cómo se genera

Endpoint: GET /api/v1/me/profile/cv.pdf

  • Response type: application/pdf
  • Content-Disposition: attachment; filename="CV_Nombre_Apellido.pdf"
  • Rate limit: 30 por minuto (es operación cara)

Desde la UI

En /me/profile, botón "Descargar CV en PDF". El frontend:

  1. Llama al endpoint.
  2. Recibe un blob.
  3. Crea un Blob URL y simula el click de descarga.

No se abre en nueva pestaña (para evitar que queden tabs huérfanas con el PDF).

Motor de generación

  • Librería: DomPDF 3.x (dompdf/dompdf).
  • Servicio: App\Services\CvGenerationService.
  • Template Blade: resources/views/pdf/cv.blade.php.

Flujo técnico

GET /me/profile/cv.pdf


ProfileController@cv


CvGenerationService::generate($user)

      ├── Carga el CandidateProfile con 8 relaciones (eager loading):
      │     experiences, educations, courses, certifications,
      │     references, documents, skills, languages

      ├── Transforma los datos a un array para la vista

      ├── Renderiza la vista Blade con los tokens de marca:
      │     ─ Logo HUMAE (base64 inline)
      │     ─ Paleta: primary #314259, dark #081828
      │     ─ Font: Helvetica (DomPDF no soporta custom fonts trivialmente)

      ├── Instancia Dompdf, setea papel A4 portrait

      └── Devuelve el stream binario

Transliteración del filename

Los nombres con acentos y ñ se transliteran para que el archivo sea válido en Windows/macOS/Linux:

"Pérez Núñez" → "Perez_Nunez"

Se hace con un mapa manual (iconv con //TRANSLIT tenía bugs con ñ en algunos locales).

Estructura del CV

El template tiene 6 secciones fijas en orden:

1. Encabezado

┌──────────────────────────────────────┐
│  [FOTO]   NOMBRE APELLIDO            │
│           Headline del candidato     │
│           email | teléfono | LinkedIn│
│           Ciudad, Estado, País       │
└──────────────────────────────────────┘

La foto viene de User.avatar_url. Si no hay, se omite y se ajusta el layout.

2. Resumen profesional

Muestra summary del perfil (hasta 5000 caracteres). Si está vacío, se omite la sección.

3. Experiencia laboral

Orden cronológico inverso. Cada experiencia:

[Mar 2023 — Actual]  Software Engineer · HUMAE
CDMX, Remoto
  Descripción de responsabilidades y logros...

4. Educación

[2018 — 2022]  Licenciatura en Ingeniería · UNAM
Mexico City · Computer Science

5. Habilidades e idiomas

Dos columnas:

HABILIDADES              IDIOMAS
React (Experto)          Español (Nativo)
Python (Avanzado)        Inglés (C1)
SQL (Avanzado)           Portugués (B1)

6. Pie de página

────────────────────────────────────────
CV generado por HUMAE · humae.com.mx · 19 de abril, 2026

Personalización

MVP: el template es fijo. No se puede reordenar, elegir colores ni cambiar idioma.

Fase 2 (roadmap):

  • Templates alternos (minimalista, corporativo, creativo).
  • Selector de secciones a incluir/excluir.
  • Idiomas: generar CV en inglés con lang=en query param.

Visto por recruiters

Los recruiters pueden descargar el CV de cualquier candidato visible en el directorio:

Endpoint: GET /api/v1/recruiter/candidates/{id}/cv.pdf

  • Mismo template, mismo flujo.
  • Requiere role:recruiter o role:admin.
  • Se registra en el log de auditoría: "Recruiter Juan descargó CV de Ana Pérez".

Consideraciones técnicas

Performance

  • Generar un PDF con DomPDF toma ~300–800ms (depende del número de experiencias/educaciones).
  • Se ejecuta sincrono dentro del request. No se encola.
  • Para candidatos con muchísimas entradas (>50 experiencias), considerar paginar o limitar el CV.

Fonts

DomPDF usa fuentes embebidas. El MVP usa Helvetica para garantizar renderizado consistente. Agregar custom fonts (Inter, por ejemplo) requiere:

  1. Descargar TTF y convertirlo con dompdf font:convert.
  2. Hospedarlo en storage/fonts/.
  3. Referenciarlo en el CSS del Blade con @font-face.

Pendiente para fase 2.

Images

El logo y la foto de perfil se incrustan en base64 inline dentro del HTML. Esto evita llamadas HTTP durante el render (DomPDF no soporta bien fetching remoto).

php
$logoDataUri = 'data:image/png;base64,' . base64_encode(file_get_contents($logoPath));

Caching

El PDF no se cachea. Cada request regenera. Motivos:

  • Los datos del candidato cambian con frecuencia.
  • Regenerar es rápido comparado con cachear + invalidar.
  • Evita guardar PDFs con datos personales en disco más tiempo del necesario.

Errores comunes

ErrorCausaSolución
"No tienes permiso para acceder"Candidato sin login o intentando bajar CV de otroLogin; solo puedes bajar tu CV
"Perfil incompleto"Faltan datos básicos (nombre)Completar perfil antes de descargar
PDF en blancoBug de DomPDF con caracteres especiales (raro)Revisar logs, reportar
Filename con caracteres raros en WindowsFalla de transliteraciónEl mapa manual cubre acentos y ñ; reportar si ocurre

Notificaciones relacionadas

Ninguna. La descarga del CV es silenciosa — no se notifica al candidato cuando un recruiter descarga su CV (por diseño: evita ansiedad).

Siguiente

Ya con CV y todo listo, el candidato puede recibir propuestas de entrevista cuando los recruiters lo asignen a una vacante. Entrevistas del candidato →

Manual de usuario HUMAE · Uso interno