Skip to content

About

Open-source certificate automation tool to generate, download, and email personalized certificates using CSV or Google Sheets.

Topics

Resources

Contributing

Stars

22 stars

Watchers

0 watching

Forks

Repository files navigation

Next.js 16 React 19 Flask API TypeScript 5 Tailwind CSS 4

πŸ“œ MailMyCertificate

Generate and send professional certificates in minutes β€” mostly in your browser.

Open-source, privacy-first certificate automation for hackathons, educators, and event organizers.
Upload a template β†’ Add participants (CSV or Google Sheets) β†’ Place fields β†’ Generate PDFs β†’ Download ZIP or send via Gmail.

Live site β€’ Features β€’ Architecture β€’ Getting Started β€’ Deployment β€’ Roadmap


🌟 Overview

MailMyCertificate is a full certificate workflow: design on a visual canvas, batch-generate PDFs client-side, then optionally send them through your own Gmail account via Google OAuth.

Layer What runs where
PDF generation 100% in the browser (Web Worker + pdf-lib)
Participant data Stored in IndexedDB (Dexie) on your device
Gmail send + OAuth Flask API on Vercel (/api/*) β€” only when you choose to email

Production: mailmycertificate.tech


Built by Akshat Thakur

Created by Akshat Thakur, a software developer building web applications and tools that solve real problems.

If you like MailMyCertificate, you might also find these useful:

Connect on GitHub β€’ LinkedIn β€’ Twitter/X


✨ Features

Certificate wizard (/tool)

Feature Description
Template upload JPG/PNG templates with dimension detection
CSV import Up to 400 rows, header detection, preview table
Google Sheets import Paste a public sheet URL and sync participant data
Visual field editor Drag-and-drop fields, zoom, properties panel (size, alignment, color)
Undo / redo Field placement history via zundo (Ctrl+Z / Ctrl+Y)
Single-certificate preview Preview modal before batch generation
Batch PDF generation Web Worker + chunked processing; resume after refresh
ZIP download All completed PDFs in one archive
Session recovery Restore in-progress batches from IndexedDB

Email delivery (/email)

Feature Description
Gmail OAuth Connect your Google account (Gmail API gmail.send)
Personalized compose Subject/body with {{column}} variables from CSV
Attachments Sends generated PDF per recipient
Send tracker Live progress, failures list, retry-friendly queue
Refresh guard Warns before leaving during an active send

Site & privacy

Page Purpose
/ Landing + marketing
/guide How-to, FAQs, OAuth walkthrough
/about Project story
/contact Contact
/settings Local data management (view / delete sessions)
/privacy-policy, /terms-of-service Legal pages

Also: SEO metadata, JSON-LD, sitemap, PWA manifest, service worker (static assets), Vercel Analytics.


πŸ— Architecture

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                         Browser (Next.js 16)                              β”‚
β”‚  /tool  β†’ Wizard (Zustand + Dexie IDB) β†’ Web Worker β†’ pdf-lib β†’ ZIP      β”‚
β”‚  /email β†’ Gmail composer β†’ fetch('/api/...', credentials: 'include')       β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
                                β”‚  /api/*  (Vercel Services)
                                β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚                    Flask backend (api/index.py)                           β”‚
β”‚  GET  /api/auth/login      β†’ Google OAuth URL                             β”‚
β”‚  GET  /api/auth/callback   β†’ Exchange code, session + CSRF                  β”‚
β”‚  GET  /api/auth/status     β†’ Connected Gmail + csrf_token sync              β”‚
β”‚  POST /api/send-email      β†’ Gmail API send (PDF attachment)                β”‚
β”‚  POST /api/sheets/import   β†’ Google Sheets CSV fetch                        β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

Vercel routing (vercel.json): Next.js at /, Flask at /api via experimentalServices.

Local dev: next.config.ts rewrites /api/* β†’ http://localhost:8000 when NODE_ENV=development.


πŸ›  Tech Stack

Category Technology Purpose
Frontend Next.js 16, React 19, TypeScript 5 App Router, UI
Styling Tailwind CSS 4 Design system
State Zustand + zundo + persist Wizard state, undo/redo
Storage Dexie (IndexedDB) Sessions, templates, PDFs, email queue
PDF pdf-lib + Web Worker Client-side generation
ZIP JSZip Batch download
CSV PapaParse File parsing
Backend Flask, google-auth-oauthlib, Gmail API OAuth + send + Sheets proxy
Deploy Vercel (Next + Python services) Production hosting
Analytics @vercel/analytics Usage metrics

πŸ“ Project Structure

MailMyCertificate/
β”œβ”€β”€ api/
β”‚   β”œβ”€β”€ index.py              # Flask app (OAuth, send-email, sheets)
β”‚   └── site_config.py        # APP_URL, CORS, redirect URI helpers
β”œβ”€β”€ public/
β”‚   β”œβ”€β”€ logo.png              # Brand asset
β”‚   β”œβ”€β”€ icon-192.png, icon-512.png, favicon-48.png
β”‚   β”œβ”€β”€ manifest.json         # PWA
β”‚   └── sw.js                 # Service worker (static cache; skips /api)
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ app/                  # Routes (/, /tool, /email, /guide, …)
β”‚   β”œβ”€β”€ views/                # Page-level views
β”‚   β”œβ”€β”€ components/           # UI, wizard, email, session, seo, guide
β”‚   β”œβ”€β”€ core/
β”‚   β”‚   β”œβ”€β”€ db/schema.ts      # Dexie tables
β”‚   β”‚   β”œβ”€β”€ session/          # Session manager + recovery
β”‚   β”‚   β”œβ”€β”€ queue/            # Email queue
β”‚   β”‚   └── worker/           # PDF generation worker
β”‚   β”œβ”€β”€ services/             # template, csv, email, sheets, zip, pdf
β”‚   β”œβ”€β”€ store/useAppStore.ts  # Zustand + temporal + persist
β”‚   β”œβ”€β”€ config/site.ts        # Public URL helpers (frontend)
β”‚   └── lib/                  # metadata, SEO, structured data
β”œβ”€β”€ vercel.json               # Next + Flask services
β”œβ”€β”€ requirements.txt          # Python dependencies
β”œβ”€β”€ next.config.ts
└── .env.example

πŸš€ Getting Started

Prerequisites

  • Node.js β‰₯ 18
  • Python β‰₯ 3.10 (for local Gmail API)
  • Google Cloud OAuth client (Web) with Gmail API enabled

1. Clone & install

git clone https://github.com/akshatthakur22/MailMyCertficate.git
cd MailMyCertficate
npm install
pip install -r requirements.txt

2. Environment variables

Copy .env.example β†’ .env.local and fill in:

NEXT_PUBLIC_APP_URL=http://localhost:3000
APP_URL=http://localhost:3000
FLASK_SECRET_KEY=<random-hex>
GOOGLE_CREDENTIALS_JSON={"web":{...,"redirect_uris":["http://localhost:3000/api/auth/callback"]}}

In Google Cloud Console β†’ OAuth client β†’ add:

  • Authorized JavaScript origins: http://localhost:3000
  • Authorized redirect URIs: http://localhost:3000/api/auth/callback

For production, also add https://mailmycertificate.tech and
https://mailmycertificate.tech/api/auth/callback.

3. Run locally (two terminals)

Terminal A β€” Flask API (port 8000):

python api/index.py

Terminal B β€” Next.js:

npm run dev

Open http://localhost:3000. Gmail connect and send only work when both are running.

Alternatively, with the Vercel CLI: vercel dev -L runs frontend + backend together.

Scripts

Command Description
npm run dev Next.js dev server
npm run build Production build
npm run start Start production Next server
npm run lint ESLint
python api/index.py Flask API on :8000 (local)

🚒 Deployment (Vercel)

  1. Import the GitHub repo on Vercel.
  2. Set Production environment variables:
Variable Example
APP_URL https://mailmycertificate.tech
NEXT_PUBLIC_APP_URL https://mailmycertificate.tech
FLASK_SECRET_KEY long random string
GOOGLE_CREDENTIALS_JSON full OAuth client JSON (single line)
  1. Ensure vercel.json uses experimentalServices (already in repo).
  2. Redeploy after env changes.

Checklist after deploy

  • GET /api/auth/login returns JSON with authorization_url (not HTML 500).
  • redirect_uri in that URL matches Google Console exactly.
  • Connect Gmail on /email, then send a test message.

πŸ“§ How email works

  1. User clicks Connect Gmail β†’ /api/auth/login β†’ Google OAuth.
  2. Callback β†’ /api/auth/callback stores tokens in an encrypted Flask session cookie.
  3. Frontend syncs CSRF token from redirect URL + /api/auth/status.
  4. Each send: POST /api/send-email with credentials: 'include', X-CSRF-Token, and PDF attachment (multipart).

Tokens stay on the server session; certificate bytes are read from IndexedDB and only sent when you hit Send.


πŸ—Ί Roadmap

Done recently

  • Gmail OAuth + send via Flask on Vercel
  • IndexedDB sessions + recovery
  • Google Sheets import
  • Undo/redo, preview modal, email send UI
  • SEO, PWA, settings / legal pages

Next

  • Custom font embedding in PDFs (beyond Helvetica)
  • Personalized ZIP filenames from CSV columns
  • Stronger CSV validation (duplicates, email column hints)
  • Dark mode
  • Automated tests (unit + E2E)
  • Rate-limit UX for large Gmail batches

🀝 Contributing

  1. Fork the repo
  2. Create a branch (git checkout -b feature/your-feature)
  3. Commit and push
  4. Open a Pull Request

Issues and PRs are welcome.


πŸ“„ License

MIT License β€” see LICENSE if present in the repo root.


πŸ™ Acknowledgements

Built with dedication by Akshat Thakur using:

Thanks to the open-source community for tools that make this possible.


Built with ❀ by Akshat Thakur


πŸ‘¨β€πŸ’» For Developers

If you're looking to fork, customize, or contribute to MailMyCertificate:

  • Check out the /for-developers page (coming soon) for architecture deep-dive and customization guide
  • Read CONTRIBUTING.md for development workflow, code style, and PR process
  • Review GitHub Issues for bugs and feature requests
  • Join the discussion on Discussions or email via GitHub profile

Why fork MailMyCertificate?

  • You don't need to build certificate generation + Gmail integration from scratch
  • The entire workflow is open and transparent β€” no black box
  • Deploy to your own infrastructure (Vercel, self-hosted, Docker)
  • Customize fields, styling, or logic to fit your specific workflow

About

Open-source certificate automation tool to generate, download, and email personalized certificates using CSV or Google Sheets.

Topics

Resources

Contributing

Stars

22 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages