Skip to content

Case study · Certificate designer and bulk generator

Serenity

A web app for designing certificates on a canvas, generating them in bulk from spreadsheet data, and verifying each one through a QR code. Built with Next.js, Fabric.js and Firebase.

By · Updated

Serenity landing page reading “Create Certificates at Lightning Speed”, with buttons to start creating or verify a certificate

The problem

Events, workshops and courses often need hundreds of personalised certificates. Making them one by one is slow, and a certificate on its own is hard to verify later. Serenity puts a visual editor, bulk generation and public verification in one app.

What it does

  • A drag and drop canvas editor (Fabric.js) with variable text fields such as {{name}}, Google Fonts, shapes, image filters, element locking and undo/redo.
  • Excel or CSV import to generate a personalised certificate for every row, with progress tracking and high resolution PDF export.
  • A unique QR code on every certificate that links to a public verification page.
  • Batch email delivery of generated certificates.
  • Email and OAuth sign in (Google, GitHub), a personal template library, and light and dark themes.

Architecture

The editor and the generator run in the browser: Fabric.js renders each certificate from the template and a row of data, and jsPDF and JSZip package the results, so bulk generation does not depend on a render server.

Next.js route handlers cover the server side (templates, certificate records, verification lookups, email delivery, autosave and image uploads), backed by Firebase Auth, Cloud Firestore (with security rules), the Firebase Admin SDK and Vercel Blob storage.

Implementation details

  • Custom Fabric.js objects for variable text boxes and QR code images, so placeholders and codes can be positioned like any other element.
  • Each certificate record gets an ID that is encoded in its QR code and resolved by the /verify/[id] page and API.
  • An autosave service persists work in progress in the editor.