A full-stack certificate issuance, delivery & verification platform.
Issuing certificates for an event sounds simple.
Until you have 500 participants.
Spreadsheet
↓
Copy names manually
↓
Design certificate
↓
Generate PDFs one-by-one
↓
Rename files
↓
Send emails manually
↓
Track who received what
↓
Handle verification requests
That's where the workflow breaks.
┌──────────────────────┐
│ ORGANIZER │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ CREATE EVENT │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ IMPORT CSV DATA │
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ REVIEW PARTICIPANTS│
└──────────┬───────────┘
│
▼
┌──────────────────────┐
│ CHOOSE TEMPLATE │
└──────────┬───────────┘
│
▼
┌─────────────────────────────┐
│ BULK CERTIFICATE ENGINE │
└─────────────┬───────────────┘
│
┌─────────────┼─────────────┐
▼ ▼ ▼
┌───────┐ ┌───────┐ ┌───────┐
│ PDF │ │ ZIP │ │ EMAIL │
└───┬───┘ └───────┘ └───┬───┘
│ │
└────────────┬───────────────┘
▼
┌─────────────────────┐
│ PARTICIPANT │
│ DASHBOARD │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ PUBLIC VERIFICATION │
└─────────────────────┘
|
|
Two sides of the platform:
Authentication
│
┌────────┴────────┐
▼ ▼
Organizer Participant
│ │
▼ ▼
Dashboard Dashboard
Authentication and authorization are handled using Supabase Auth.
Organizers can create an event and associate participants and certificates with it.
Event
├── Name
├── Date
├── Participants
├── Template
└── Certificates
This keeps large certificate batches organized instead of treating every certificate as an isolated file.
Upload participant data instead of manually entering hundreds of records.
participants.csv
│
▼
Papa Parse
│
▼
Data Validation
│
▼
Duplicate Check
│
▼
Participant Preview
│
▼
Import
Package: papaparse
Before generating anything, organizers can inspect imported participants.
┌──────────────────────────────────────────────────┐
│ PARTICIPANTS │
├──────────────────────────────────────────────────┤
│ Name Email Status │
├──────────────────────────────────────────────────┤
│ Aryansh Gupta aryansh@email.com ✓ │
│ Stuti Verma stuti@email.com ✓ │
│ Shaurya Agrawal shaurya@email.com ✓ │
└──────────────────────────────────────────────────┘
This prevents bad data from becoming bad certificates.
The platform currently supports:
Traditional certificate styling.
A cleaner contemporary certificate layout.
CERTIFICATE
OF
ACHIEVEMENT
This certifies that
SHAURYA AGRAWAL
has successfully participated in
EVENT NAME 2026
CERT-2026-305NDF
This is the core of the application.
Instead of:
1 participant → 1 manual certificate
the system handles:
500 participants
│
▼
500 personalized certificates
Each certificate gets:
- Participant name
- Event information
- Personalized content
- Unique certificate ID
- PDF output
Every certificate receives a unique identifier.
CERT-YYYY-XXXXXX
Example:
CERT-2026-305NDF
The repository currently documents this certificate ID format and uses it as part of the verification flow.
Generating hundreds of certificates shouldn't mean downloading hundreds of files individually.
Generated PDFs
│
┌─────────────┼─────────────┐
▼ ▼ ▼
Alice.pdf Bob.pdf Charlie.pdf
│ │ │
└─────────────┼─────────────┘
▼
JSZip
│
▼
certificates.zip
Package: jszip
Certificates can be distributed directly to participants.
Certificate PDF
│
▼
Resend
│
▼
Participant Email
│
▼
📬 Certificate Delivered
Package: resend
Participants get their own certificate library.
┌──────────────────────────────────────────┐
│ MY CERTIFICATES │
├──────────────────────────────────────────┤
│ │
│ Hackathon 2026 [Download] │
│ CERT-2026-305NDF │
│ │
│ Workshop 2026 [Download] │
│ CERT-2026-81K2PQ │
│ │
└──────────────────────────────────────────┘
Certificates are grouped by event for easier discovery.
A certificate isn't useful if nobody can verify it.
The verification system allows a certificate ID to be checked independently.
CERT-2026-305NDF
│
▼
Verification Page
│
▼
Database Lookup
│
┌───────┴───────┐
▼ ▼
VALID INVALID
│ │
▼ ▼
Certificate Info Not Found
This turns the PDF from a static document into a verifiable digital credential.
Security is built into the data layer.
┌──────────────┐
│ Client │
└──────┬───────┘
│
▼
┌──────────────┐
│ Supabase │
│ Auth │
└──────┬───────┘
│
▼
┌──────────────┐
│ PostgreSQL │
│ │
│ RLS │
└──────────────┘
- Supabase Authentication
- PostgreSQL Row Level Security
- Authenticated dashboards
- Organizer/participant separation
- Duplicate participant protection
- Unique certificate identifiers
- Controlled public verification
Supabase provides the project's authentication, PostgreSQL database and RLS layer.
┌──────────────────────┐
│ Browser │
│ Next.js + React │
└──────────┬───────────┘
│
┌──────────▼───────────┐
│ Authentication │
│ Supabase Auth │
└──────────┬───────────┘
│
┌────────────────┼────────────────┐
│ │ │
▼ ▼ ▼
Organizer Participant Public
Dashboard Dashboard Verification
│ │ │
└────────────────┼────────────────┘
│
▼
┌──────────────────────┐
│ Next.js API Layer │
│ Node.js │
└──────────┬───────────┘
│
┌─────────────────┼─────────────────┐
│ │ │
▼ ▼ ▼
Supabase pdf-lib Resend
PostgreSQL PDF Engine Email Service
│ │ │
└─────────────────┼─────────────────┘
│
▼
JSZip
│
▼
Download / Delivery
| Technology | Purpose |
|---|---|
| Next.js 16 | Full-stack React framework |
| React 19 | UI & component architecture |
| TypeScript 5 | Type-safe development |
| Tailwind CSS 4 | Styling |
| React Compiler | React optimization |
| Technology | Purpose |
|---|---|
| Next.js API Routes | Server-side APIs |
| Node.js | Runtime |
| Zod | Validation |
| Technology | Purpose |
|---|---|
| Supabase | Backend platform |
| PostgreSQL | Relational database |
| Supabase Auth | Authentication |
| RLS | Database-level authorization |
| Package | Purpose |
|---|---|
pdf-lib |
Generate PDFs |
papaparse |
Parse CSV files |
jszip |
Create ZIP archives |
nanoid |
Generate unique IDs |
zod |
Validate structured data |
| Package | Purpose |
|---|---|
resend |
Certificate email delivery |
GitHub
│
▼
Vercel
│
└── Next.js Application
│
├── Supabase
└── Resend
These packages and versions are reflected in the current repository's package.json.
One of the things I wanted to make clear in this project is why each dependency exists.
certificate-generator
│
┌─────────────────────┼─────────────────────┐
│ │ │
▼ ▼ ▼
UI / App Data Layer Services
│ │ │
▼ ▼ ▼
next.js supabase-js resend
react @supabase/ssr
tailwind zod
│
├─────────────────────────────────────────┐
│ │
▼ ▼
Document Processing File Processing
│ │
▼ ▼
pdf-lib jszip
papaparse nanoid
next → Application framework
react → UI
typescript → Type safety
tailwindcss → Styling
supabase-js → Database + Auth
@supabase/ssr → Supabase server integration
pdf-lib → PDF generation
papaparse → CSV processing
jszip → ZIP generation
resend → Email delivery
nanoid → Unique identifiers
zod → Runtime validation
The current dependency set includes all of the above packages.
LOGIN
│
▼
DASHBOARD
│
▼
CREATE EVENT
│
▼
UPLOAD CSV
│
▼
PARSE CSV
│
▼
VALIDATE
│
▼
CHECK DUPLICATES
│
▼
PREVIEW
│
▼
SELECT TEMPLATE
│
▼
GENERATE PDFs
│
├──────────────┐
▼ ▼
DOWNLOAD ZIP SEND EMAILS
│ │
└───────┬──────┘
▼
DATABASE
RECEIVE CERTIFICATE
│
▼
LOGIN
│
▼
DASHBOARD
│
▼
VIEW CERTIFICATE
│
▼
DOWNLOAD
│
▼
SHARE / VERIFY
Certificate ID
│
▼
Public Verification
│
▼
Database Query
│
┌──┴──┐
▼ ▼
VALID INVALID
│ │
▼ ▼
Details Failed
certificate-generator/
│
├── public/
│ └── assets
│
├── src/
│ ├── app/
│ │ ├── api/
│ │ ├── dashboard/
│ │ ├── login/
│ │ ├── verify/
│ │ └── ...
│ │
│ ├── components/
│ │ └── reusable UI
│ │
│ └── lib/
│ ├── supabase/
│ ├── validation/
│ ├── certificates/
│ └── utilities/
│
├── package.json
├── next.config.ts
├── tsconfig.json
├── eslint.config.mjs
├── postcss.config.mjs
└── README.md
git clone https://github.com/shaurya3571/certificate-generator.git
cd certificate-generatornpm installCreate:
.env.local
Configure your Supabase and Resend credentials.
NEXT_PUBLIC_SUPABASE_URL=your_supabase_url
NEXT_PUBLIC_SUPABASE_ANON_KEY=your_supabase_anon_key
RESEND_API_KEY=your_resend_api_keynpm run devThen open:
http://localhost:3000
Available scripts in the current project include:
npm run dev
npm run build
npm run start
npm run lint| Feature | Status |
|---|---|
| Organizer authentication | ✅ |
| Participant authentication | ✅ |
| Event creation | ✅ |
| CSV participant import | ✅ |
| Participant preview | ✅ |
| Classic template | ✅ |
| Modern template | ✅ |
| Bulk PDF generation | ✅ |
| Unique certificate IDs | ✅ |
| ZIP export | ✅ |
| Email delivery | ✅ |
| Participant dashboard | ✅ |
| Event-wise grouping | ✅ |
| Certificate downloads | ✅ |
| Public verification | ✅ |
| Supabase RLS | ✅ |
| Duplicate protection | ✅ |
| Vercel deployment | ✅ |
The current GitHub README documents these as the project's implemented main features.
Move from predefined templates to a visual editor.
┌────────────────────────────────────┐
│ CANVAS │
│ │
│ ┌──────────────────────┐ │
│ │ CERTIFICATE │ │
│ │ │ │
│ │ {{NAME}} │ │
│ │ │ │
│ └──────────────────────┘ │
│ │
└────────────────────────────────────┘
│
▼
Drag • Drop • Resize • Customize
Future support for:
- Organization logos
- Custom colors
- Custom fonts
- Signature uploads
- Background images
- Brand presets
Add a QR code directly to every certificate.
Certificate
│
▼
QR Code
│
▼
Scan
│
▼
Verification Page
Future organizer analytics:
Certificates Generated 1,248
Certificates Delivered 982
Certificates Downloaded 734
Verification Checks 421
Move beyond individual organizers.
Organization
│
┌────┼────┐
▼ ▼ ▼
Admin Staff Staff
Role-based access could allow teams to collaboratively manage events and certificates.
Future:
verify.yourorganization.com/CERT-2026-305NDF
instead of a generic verification route.
NOW
│
▼
┌──────────────────────┐
│ Certificate Platform │
└──────────┬───────────┘
│
┌──────────┼──────────┐
▼ ▼ ▼
Templates Delivery Verification
│ │ │
└──────────┼──────────┘
│
▼
┌─────────────────┐
│ Visual Designer │
└────────┬────────┘
│
▼
QR Verification
│
▼
Analytics
│
▼
Organizations
│
▼
SaaS Platform
Building this project involved solving problems beyond UI development.
How should participant records, events and certificates relate?
Who should be allowed to access each certificate?
How should hundreds of certificates be generated efficiently?
How do you reliably create personalized PDFs programmatically?
How can generated certificates be delivered automatically?
How can a third party determine whether a certificate is legitimate?
How can a complicated workflow feel simple to an organizer?
FULL STACK
│
┌───────────────┼────────────────┐
│ │ │
▼ ▼ ▼
Frontend Backend Database
│ │ │
Next.js API Routes PostgreSQL
React Node.js Supabase
TypeScript RLS
│
├─────────────────────────────────────┐
│ │
▼ ▼
Document Systems DevOps
│ │
pdf-lib Vercel
JSZip Deployment
Papa Parse