Construyendo un Generador de Certificados con React y TongoRender — TongoRender Blog
Volver al Blog
tutorialscertificatereacttutorial

Construyendo un Generador de Certificados con React y TongoRender

Tutorial paso a paso para construir un generador de certificados en React. Diseño de plantillas, recolección de datos, generación de PDFs vía API y descarga instantánea.

TongoRender Team28 de febrero de 202612 min

Certificados de finalización, premios de logro y diplomas de participación son esenciales para cursos en línea, talleres, conferencias y programas de capacitación corporativa. En lugar de diseñar cada certificado manualmente en una herramienta como Canva, puedes construir una aplicación web que los genere automáticamente a partir de una plantilla. En este tutorial, construiremos un generador de certificados basado en React que produce certificados PDF profesionales usando TongoRender.

Lo Que Construiremos

  1. Una plantilla de certificado diseñada con HTML y CSS
  2. Un formulario React para ingresar datos del destinatario
  3. Una ruta de API que renderiza el certificado como PDF

Paso 1: Diseño de la Plantilla de Certificado

export function certificateTemplate({ recipientName, courseName, completionDate, instructorName, certificateId }) {
  return `
  <!DOCTYPE html>
  <html lang="es">
  <head>
    <link href="https://fonts.googleapis.com/css2?family=Great+Vibes&family=Montserrat:wght@300;400;600&display=swap" rel="stylesheet">
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { width: 297mm; height: 210mm; font-family: 'Montserrat', sans-serif; }
      .certificate {
        width: 100%; height: 100%;
        border: 3px solid #1a365d; padding: 15mm;
        background: linear-gradient(135deg, #fefefe 0%, #f7fafc 100%);
      }
      .inner-border {
        width: 100%; height: 100%;
        border: 1px solid #c9a84c; padding: 15mm;
        display: flex; flex-direction: column;
        align-items: center; justify-content: center; text-align: center;
      }
      .title { font-family: 'Great Vibes', cursive; font-size: 48pt; color: #1a365d; }
      .subtitle { font-size: 14pt; color: #4a5568; letter-spacing: 4px; text-transform: uppercase; margin: 10mm 0 5mm; }
      .recipient { font-family: 'Great Vibes', cursive; font-size: 36pt; color: #c9a84c; margin: 5mm 0; }
      .description { font-size: 12pt; color: #4a5568; max-width: 500px; line-height: 1.6; }
      .cert-id { position: absolute; bottom: 10mm; right: 15mm; font-size: 8pt; color: #a0aec0; }
    </style>
  </head>
  <body>
    <div class="certificate">
      <div class="inner-border">
        <div class="title">Certificado de Finalización</div>
        <div class="subtitle">Se otorga con orgullo a</div>
        <div class="recipient">${recipientName}</div>
        <div class="description">
          Por completar exitosamente el curso
          <strong>${courseName}</strong>
          el ${completionDate}.
        </div>
      </div>
      <div class="cert-id">ID del Certificado: ${certificateId}</div>
    </div>
  </body>
  </html>`;
}

Paso 2: Construir el Formulario React

import { useState } from 'react';

export default function CertificateForm() {
  const [formData, setFormData] = useState({
    recipientName: '', courseName: '', completionDate: '', instructorName: '',
  });
  const [loading, setLoading] = useState(false);

  const handleSubmit = async (e) => {
    e.preventDefault();
    setLoading(true);

    const response = await fetch('/api/generate-certificate', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(formData),
    });

    const blob = await response.blob();
    const url = URL.createObjectURL(blob);
    const a = document.createElement('a');
    a.href = url;
    a.download = `certificado-${formData.recipientName.replace(/\s+/g, '-')}.pdf`;
    a.click();
    setLoading(false);
  };

  return (
    <form onSubmit={handleSubmit}>
      <input placeholder="Nombre del Destinatario" required
        value={formData.recipientName}
        onChange={e => setFormData({...formData, recipientName: e.target.value})} />
      <input placeholder="Nombre del Curso" required
        value={formData.courseName}
        onChange={e => setFormData({...formData, courseName: e.target.value})} />
      <input type="date" required
        value={formData.completionDate}
        onChange={e => setFormData({...formData, completionDate: e.target.value})} />
      <input placeholder="Nombre del Instructor" required
        value={formData.instructorName}
        onChange={e => setFormData({...formData, instructorName: e.target.value})} />
      <button type="submit" disabled={loading}>
        {loading ? 'Generando...' : 'Generar Certificado'}
      </button>
    </form>
  );
}

Paso 3: Crear la Ruta de API

import { certificateTemplate } from '../../templates/certificate';
import { randomUUID } from 'crypto';

export default async function handler(req, res) {
  const { recipientName, courseName, completionDate, instructorName } = req.body;
  const certificateId = randomUUID().split('-')[0].toUpperCase();

  const html = certificateTemplate({ recipientName, courseName, completionDate, instructorName, certificateId });

  const pdfResponse = await fetch('https://api.tongorender.io/v1/pdf', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-API-Key': process.env.TONGORENDER_API_KEY,
    },
    body: JSON.stringify({
      html, format: 'A4', landscape: true,
      margin: { top: '0mm', bottom: '0mm', left: '0mm', right: '0mm' },
      printBackground: true,
    }),
  });

  const pdfBuffer = Buffer.from(await pdfResponse.arrayBuffer());
  res.setHeader('Content-Type', 'application/pdf');
  res.send(pdfBuffer);
}

Paso 4: Generación en Lote

const csv = require('csv-parse/sync');

async function batchGenerate(csvPath) {
  const records = csv.parse(fs.readFileSync(csvPath), { columns: true });
  for (const record of records) {
    const pdf = await generateCertificate(record);
    fs.writeFileSync(`certificates/${record.name.replace(/\s+/g, '-')}.pdf`, pdf);
    console.log(`Certificado generado para ${record.name}`);
  }
}

Consejos de Diseño para Certificados

  • Usa fuentes decorativas con moderación — Fuentes cursivas como Great Vibes funcionan para nombres y títulos, pero el texto del cuerpo debe ser limpio y legible.
  • Incluye un ID único — Hace que los certificados sean verificables.
  • Imprime colores de fondo — Establece printBackground: true en las opciones de la API.
  • Prueba con nombres largos — Algunos destinatarios tienen nombres muy largos. Usa dimensionamiento responsivo de fuente.
  • Agrega un código QR — Vincula a una URL de verificación para mayor autenticidad.

TongoRender renderiza web fonts, gradientes CSS y layouts complejos fielmente, haciéndolo ideal para la generación de certificados.

Construye tu generador de certificados con TongoRender — 100 renderizaciones gratuitas al mes, sin necesidad de tarjeta de crédito.

Comparte este artículoCompartir en Twitter