The Blockchain Certificate Verifier is a full-stack decentralized application (dApp) that combines blockchain technology, IPFS storage, and PDF generation to create tamper-proof digital certificates.
┌─────────────────────────────────────────────────────────────────┐
│ USER INTERFACE │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ React Frontend (Port 5173) │ │
│ │ - Certificate issuance form │ │
│ │ - Certificate verification │ │
│ │ - IPFS link display │ │
│ │ - QR code rendering │ │
│ └──────────────────────────────────────────────────────────┘ │
│ │ │
│ │ Web3.js │
│ ▼ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ MetaMask Wallet │ │
│ │ - Account management │ │
│ │ - Transaction signing │ │
│ │ - Network switching │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ HTTP/JSON-RPC
▼
┌─────────────────────────────────────────────────────────────────┐
│ BLOCKCHAIN LAYER │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Ethereum Network (Ganache Local) │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ CertificateVerifier Smart Contract │ │ │
│ │ │ │ │ │
│ │ │ Storage: │ │ │
│ │ │ - Certificate ID (bytes32) │ │ │
│ │ │ - Student name (string) │ │ │
│ │ │ - Course name (string) │ │ │
│ │ │ - Issue date (uint256) │ │ │
│ │ │ - IPFS hash (string) │ │ │
│ │ │ - Issuer address (address) │ │ │
│ │ │ │ │ │
│ │ │ Functions: │ │ │
│ │ │ - issueCertificate() │ │ │
│ │ │ - verifyCertificate() │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ Axios HTTP
▼
┌─────────────────────────────────────────────────────────────────┐
│ BACKEND SERVICES │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Express.js Server (Port 3001) │ │
│ │ │ │
│ │ API Endpoint: │ │
│ │ POST /api/generate-certificate │ │
│ │ │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ 1. generateCertificateHTML() │ │ │
│ │ │ - Create HTML template │ │ │
│ │ │ - Embed student data │ │ │
│ │ │ - Generate QR code │ │ │
│ │ │ - Apply professional styling │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ 2. generatePDF() │ │ │
│ │ │ - Launch Puppeteer (headless Chrome) │ │ │
│ │ │ - Render HTML to PDF │ │ │
│ │ │ - A4 format, print backgrounds │ │ │
│ │ │ - Return PDF buffer │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ │ │ │ │
│ │ ▼ │ │
│ │ ┌────────────────────────────────────────────────────┐ │ │
│ │ │ 3. uploadToIPFS() │ │ │
│ │ │ - Create FormData with PDF │ │ │
│ │ │ - Add metadata (name, course, date) │ │ │
│ │ │ - POST to Pinata API │ │ │
│ │ │ - Return IPFS hash (CID) │ │ │
│ │ └────────────────────────────────────────────────────┘ │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
│
│ HTTPS API
▼
┌─────────────────────────────────────────────────────────────────┐
│ STORAGE LAYER │
│ │
│ ┌──────────────────────────────────────────────────────────┐ │
│ │ Pinata (IPFS Gateway) │ │
│ │ │ │
│ │ - Stores PDF files │ │
│ │ - Returns content identifier (CID) │ │
│ │ - Provides public gateway access │ │
│ │ - Manages file metadata │ │
│ │ │ │
│ │ Gateway URLs: │ │
│ │ - https://ipfs.io/ipfs/{CID} │ │
│ │ - https://gateway.pinata.cloud/ipfs/{CID} │ │
│ └──────────────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘
1. User Input
↓
[Name: "John Doe"]
[Course: "Blockchain Dev"]
[Email: "john@example.com"]
↓
2. Frontend Processing
↓
Generate certId = keccak256(email + course)
Get current timestamp
↓
3. Backend API Call
↓
POST /api/generate-certificate
{
name: "John Doe",
course: "Blockchain Dev",
issueDate: 1699564800,
certId: "0xabc123..."
}
↓
4. HTML Generation
↓
Create certificate template
Embed QR code
Apply styling
↓
5. PDF Conversion
↓
Puppeteer launches Chrome
Renders HTML
Generates PDF buffer
↓
6. IPFS Upload
↓
Upload PDF to Pinata
Receive CID: "QmXYZ..."
↓
7. Backend Response
↓
{
cid: "QmXYZ...",
ipfsUrl: "https://ipfs.io/ipfs/QmXYZ...",
pdfUrl: "https://gateway.pinata.cloud/ipfs/QmXYZ..."
}
↓
8. Blockchain Transaction
↓
contract.issueCertificate(
certId,
"John Doe",
"Blockchain Dev",
1699564800,
"QmXYZ..."
)
↓
9. MetaMask Confirmation
↓
User signs transaction
Transaction mined
↓
10. Success Display
↓
Show IPFS link
Display success message
Clear form
1. User Input
↓
[Email: "john@example.com"]
[Course: "Blockchain Dev"]
↓
2. Frontend Processing
↓
Generate certId = keccak256(email + course)
↓
3. Blockchain Query
↓
contract.verifyCertificate(certId)
↓
4. Smart Contract Response
↓
{
issuer: "0x123...",
name: "John Doe",
course: "Blockchain Dev",
issueDate: 1699564800,
ipfsHash: "QmXYZ...",
exists: true
}
↓
5. Frontend Display
↓
Show certificate details
Display IPFS link
Generate QR code
↓
6. User Actions
↓
Click link → View PDF on IPFS
Scan QR → View on mobile
- User Interface: Forms, buttons, displays
- Web3 Integration: Connect to MetaMask, send transactions
- State Management: Track certificate data, verification results
- API Communication: Call backend for PDF generation
- QR Code Display: Render verification QR codes
- API Endpoints: Handle certificate generation requests
- HTML Generation: Create certificate templates
- PDF Conversion: Use Puppeteer to generate PDFs
- IPFS Integration: Upload files to Pinata
- Error Handling: Manage failures gracefully
- Logging: Track operations and errors
- Data Storage: Store certificate metadata on-chain
- Access Control: Only owner can issue certificates
- Verification: Anyone can verify certificates
- Events: Emit events for certificate issuance
- Immutability: Ensure data cannot be altered
- File Storage: Store PDF files permanently
- Content Addressing: Generate unique CIDs
- Gateway Access: Provide public URLs
- Metadata Management: Tag files for organization
- React 19: UI framework
- Web3.js 4.x: Blockchain interaction
- Axios: HTTP client
- qrcode.react: QR code generation
- Vite: Build tool and dev server
- Node.js: Runtime environment
- Express 5.x: Web framework
- Puppeteer 24.x: Headless browser
- QRCode 1.5.x: QR code generation
- Axios: HTTP client
- form-data: Multipart form handling
- dotenv: Environment variables
- Solidity 0.8.x: Smart contract language
- Truffle 5.x: Development framework
- Ganache: Local blockchain
- Web3.js: Blockchain library
- IPFS: Decentralized file system
- Pinata: IPFS pinning service
User → MetaMask → Blockchain
↓
Private Key Signing
↓
Transaction Verification
- Private Keys: Never leave MetaMask
- API Keys: Stored in .env (not in git)
- Smart Contract: Only owner can issue
- IPFS: Content-addressed (tamper-proof)
- CORS: Restricted to frontend origin
- HTTPS: Required for production
- Input Validation: Sanitize all inputs
- Error Handling: No sensitive data in errors
- Sequential PDF generation (one at a time)
- Single Puppeteer instance per request
- Pinata free tier rate limits
- Local blockchain (Ganache)
- Job Queue: Use Bull or RabbitMQ for async processing
- Instance Pooling: Reuse Puppeteer instances
- Caching: Cache generated PDFs temporarily
- Load Balancing: Multiple backend servers
- CDN: Use IPFS CDN for faster access
- Testnet/Mainnet: Deploy to public networks
Localhost:5173 (Frontend)
↓
Localhost:3001 (Backend)
↓
Localhost:8545 (Ganache)
↓
Pinata Cloud (IPFS)
Vercel/Netlify (Frontend)
↓
Heroku/AWS (Backend)
↓
Sepolia/Mainnet (Blockchain)
↓
Pinata Cloud (IPFS)
- Certificate generation requests
- PDF conversion status
- IPFS upload results
- Error details with timestamps
- User actions
- API responses
- Transaction status
- Error messages
- CertificateIssued events
- Transaction hashes
- Gas usage
- HTML generation: <100ms
- PDF conversion: 2-5 seconds
- IPFS upload: 1-3 seconds
- Blockchain tx: 1-2 seconds
- Total issuance: ~5-10 seconds
- Memory: ~100-200 MB (Puppeteer)
- CPU: Moderate during PDF generation
- Network: ~50-100 KB per certificate
- Storage: ~50-100 KB per PDF on IPFS
- Blockchain: Immutable, permanent
- IPFS: Pinned on Pinata, permanent
- Local: No critical data stored locally
- Smart contract code in git
- Frontend/backend code in git
- IPFS files backed up by Pinata
- Environment variables documented
- Redeploy smart contract if needed
- Restart backend server
- Rebuild frontend
- IPFS files remain accessible
This architecture ensures:
- ✅ Decentralization (blockchain + IPFS)
- ✅ Tamper-proof certificates
- ✅ Permanent storage
- ✅ Easy verification
- ✅ Scalability potential
- ✅ Security best practices