ESP32-S3 Bench Guide
ESP32-S3 N16R8 bench guide: live pinout, lessons, simulators and the bench log.
QR-Verified Training Certificate Generation Platform
Translation pending
EducationGitHub @himonmistOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
Repository information has not been collected yet.
No updates detected yet. GitHub releases will appear here.
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗A QR-verified training certificate generation platform. A training organization manages trainers, programs, and participants, and bulk-generates tamper-evident certificates with a permanent public verification link and QR code.
Built with Next.js 14 (App Router, TypeScript), Prisma + Postgres, pdf-lib, and qrcode, following a test-driven approach for every trust-critical code path (certificate id/hash generation, auth, rate limiting, revoke/reissue, public verification). Designed to run on a serverless host (Vercel) — see DEPLOY.md.
PREFIX-YEAR-PROGRAMCODE-000001), a QR code encoding a permanent verification URL, a print-ready PDF, and a SHA-256 tamper-evidence hash (data + server-only secret salt) — idempotent per participant. The PDF and QR are rendered on demand from a snapshot frozen at issuance (see below), not written to disk — required for serverless, where local disk doesn't persist between requests./verify (manual lookup) and /verify/[uid] (QR target), no login required, shows Valid/Invalid/Revoked/Superseded states, rate-limited and logged.bcryptjs (password hashing), jose (session JWTs)qrcode, pdf-lib@vercel/blob for image uploads (falls back to local disk when unset, for local dev)papaparse / xlsx for bulk importRequires a local Postgres instance (createdb qrcertificate or equivalent).
npm install
cp .env.example .env # fill in real secrets — see below
npx prisma migrate dev # applies the schema to your local Postgres
npx tsx prisma/seed.ts # creates the bootstrap super admin from SEED_ADMIN_EMAIL/PASSWORD
npm run dev # http://localhost:3000
npm test # run the full test suite (spins up a throwaway *_test database)
npm run build # production build (also runs `prisma migrate deploy`)
Required environment variables (see .env.example):
| Variable | Purpose |
|---|---|
DATABASE_URL | Postgres connection string |
SESSION_SECRET | Signs admin session JWTs — generate with openssl rand -hex 32 |
CERT_HASH_SECRET | Secret salt mixed into every certificate's verification hash — generate the same way, never reuse across environments |
NEXT_PUBLIC_APP_URL | Public base URL used to build the QR verification link |
SEED_ADMIN_EMAIL / SEED_ADMIN_PASSWORD | One-time bootstrap super admin (seed script only) |
BLOB_READ_WRITE_TOKEN | Vercel Blob token for image uploads — required in production, optional locally (falls back to public/uploads/) |
See DEPLOY.md for step-by-step Vercel setup (Postgres + Blob storage provisioning, env vars, running the seed script against production).
This was built to demonstrate the full trust chain (issue → QR/PDF → tamper-evident hash → public verify → revoke/reissue) with strong test coverage and a hardened admin surface, within a reasonable build. A few things are deliberately out of scope for this pass, called out here rather than silently skipped:
certificate_templates.layoutJson is a JSON document of field coordinates (see src/lib/certificateLayout.ts for the schema and default layout); the admin UI edits it as raw JSON. A visual designer is a natural follow-up.src/lib/certificateService.ts is the integration point.prisma/seed.ts or directly in the database. Super Admin vs Admin roles exist in the schema and are enforced by middleware, but there's no /admin/admins CRUD screen yet.maxDuration on Vercel); a queue (BullMQ) is the documented next step for hundreds-of-certificates batches.DEPLOY.md's "Known gaps" section and src/lib/rateLimit.ts.See SECURITY.md for the security model and what was verified.
Two separate mechanisms back the spec's requirement that a certificate's verification page and content must never change once issued, even if an admin edits the underlying program/participant record afterward:
verificationHash (SHA-256 of {certificateUid, participantId, programId, issuedAt} + a server-only secret) proves the certificate record itself hasn't been tampered with or fabricated.renderedSnapshotJson freezes every displayed field (participant name, program title, organizer, trainer, dates, location) at the moment of issuance. The PDF, QR, and public verify page all render from this snapshot — never from a live join to the Participant/TrainingProgram tables — so a later correction to a program's title, for example, can't silently rewrite what an already-issued certificate shows. reissueCertificate is the one place that intentionally re-snapshots current data, since a reissue is often because something needed correcting.This was tightened while adapting the app for serverless deployment (PDF rendering moved from "render once, save to disk" to "render on demand from stored data"), and is covered by tests/integration/certificates-api.test.ts's "keeps an already-issued certificate's displayed data frozen..." test.
Every trust-critical library was written test-first: tests/unit/*.test.ts cover crypto.ts (hash tamper-evidence), certificateId.ts (id format + collision-scope), auth.ts (password hashing, JWT expiry/tampering), rateLimit.ts, validation.ts, bulkImport.ts, pdf.ts, middleware.ts (CSP/CSRF/auth), storage.ts, and imageUrl.ts (upload trust boundary). tests/integration/*.test.ts exercise the real Next.js route handlers against a real (temporary) Postgres database for auth, CRUD, certificate generation/revoke/reissue, and public verification. Run with npm test.
Bugs caught this way before shipping (not by inspection): a cross-program certificate-uid collision, a path-traversal hole in template backgrounds, a CSP that silently broke all client-side JS in the browser, and the live-data snapshot gap described above.