A Flutter package for creating and exporting customizable certificates as PNG/PDF with dynamic data and templates.

Made by - Shinjan Saha
- Create beautiful certificates with customizable templates
- Fill in certificate data dynamically (recipient name, course title, descriptions, etc.)
- Export certificates as PNG or PDF
- Share certificates directly from your app
- Three built-in certificate templates (Elegant, Modern, Minimalist)
- Support for custom templates and layouts
- Generate unique certificate IDs
dependencies:
certify_me: ^0.1.2
Run flutter pub get
to install the package.
Property |
Type |
Description |
Required |
recipientName |
String |
Name of the certificate recipient |
Yes |
courseTitle |
String |
Title of the course or achievement |
Yes |
description |
String |
Description or details of the achievement |
Yes |
issueDate |
DateTime |
Date when the certificate was issued |
Yes |
expiryDate |
DateTime? |
Optional expiry date for the certificate |
No |
issuerName |
String |
Name of the issuer/organization |
Yes |
issuerTitle |
String |
Title/position of the issuer |
Yes |
certificateId |
String |
Unique identifier for the certificate |
Yes |
metadata |
Map<String, String>? |
Additional metadata as key-value pairs |
No |
Property |
Type |
Description |
Required |
data |
CertificateData |
Certificate data to export |
Yes |
template |
CertificateTemplate |
Template to use for certificate design |
Yes |
customBuilder |
Widget Function(BuildContext, CertificateData, CertificateTemplate)? |
Custom widget builder for certificate layout |
No |
width |
double? |
Width of the exported image. Default: 1000 |
No |
height |
double? |
Height of the exported image. Default: 750 |
No |
fileName |
String? |
Custom filename for the exported file |
No |
Property |
Type |
Description |
Required |
data |
CertificateData |
Certificate data to export |
Yes |
template |
CertificateTemplate |
Template to use for certificate design |
Yes |
customBuilder |
Widget Function(BuildContext, CertificateData, CertificateTemplate)? |
Custom widget builder for certificate layout |
No |
width |
double? |
Width of the exported PDF. Default: 1000 |
No |
height |
double? |
Height of the exported PDF. Default: 750 |
No |
fileName |
String? |
Custom filename for the exported file |
No |
Property |
Type |
Description |
Required |
context |
BuildContext |
Flutter build context for sharing |
Yes |
data |
CertificateData |
Certificate data to share |
Yes |
template |
CertificateTemplate |
Template to use for certificate design |
Yes |
customBuilder |
Widget Function(BuildContext, CertificateData, CertificateTemplate)? |
Custom widget builder for certificate layout |
No |
width |
double? |
Width of the shared certificate |
No |
height |
double? |
Height of the shared certificate |
No |
asPdf |
bool |
Share as PDF format. Default: false |
No |
fileName |
String? |
Custom filename for the shared file |
No |
subject |
String? |
Subject line for sharing. Default: auto-generated |
No |
Property |
Type |
Description |
Required |
data |
CertificateData |
Certificate data to generate |
Yes |
template |
CertificateTemplate |
Template to use for certificate design |
Yes |
Property |
Type |
Description |
Required |
data |
CertificateData |
Certificate data to preview |
Yes |
template |
CertificateTemplate |
Template to use for certificate design |
Yes |
customBuilder |
Widget Function(BuildContext, CertificateData, CertificateTemplate)? |
Custom widget builder for certificate layout |
No |
width |
double |
Width of the preview widget |
Yes |
height |
double |
Height of the preview widget |
Yes |
Template Name |
Description |
elegant() |
Elegant design with classic styling |
modern() |
Modern design with contemporary elements |
minimalist() |
Clean, minimalist design with simple layout |
Method |
Return Type |
Description |
exportAsPng() |
Future |
Export certificate as PNG image file |
exportAsPdf() |
Future |
Export certificate as PDF document |
shareCertificate() |
Future |
Share certificate via system share dialog |
buildPreview() |
Widget |
Build a preview widget of the certificate |
generateCertificateId() |
String |
Generate a unique certificate ID |
copyWith() |
CertificateData |
Create a copy with modified properties |
import 'package:flutter/material.dart';
import 'package:certify_me/certify_me.dart';
void main() {
runApp(const MaterialApp(home: CertificateTestPage()));
}
class CertificateTestPage extends StatefulWidget {
const CertificateTestPage({super.key});
@override
State<CertificateTestPage> createState() => _CertificateTestPageState();
}
class _CertificateTestPageState extends State<CertificateTestPage> {
final CertificateData certificateData = CertificateData(
recipientName: 'John Doe',
courseTitle: 'Flutter Development Masterclass',
description: 'Successfully completed 40 hours of intensive Flutter training',
issueDate: DateTime.now(),
issuerName: 'Jane Smith',
issuerTitle: 'Lead Instructor',
certificateId: CertificateGenerator.generateCertificateId(),
);
late List<CertificateGenerator> generators;
late List<Widget> previews;
List<String?> pdfPaths = [null, null, null]; // For elegant, modern, minimalist
@override
void initState() {
super.initState();
// Create generators with each template
generators = [
CertificateGenerator(data: certificateData, template: CertificateTemplate.elegant()),
CertificateGenerator(data: certificateData, template: CertificateTemplate.modern()),
CertificateGenerator(data: certificateData, template: CertificateTemplate.minimalist()),
];
// Create preview widgets
previews = generators.map((g) => g.buildPreview()).toList();
// Export all PDFs
exportAllPDFs();
}
Future<void> exportAllPDFs() async {
for (int i = 0; i < generators.length; i++) {
final name = ['elegant', 'modern', 'minimalist'][i];
final path = await generators[i].exportAsPdf(
fileName: '${name}_certificate.pdf',
);
pdfPaths[i] = path;
}
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Certificate Templates')),
body: ListView.builder(
itemCount: previews.length,
itemBuilder: (context, index) {
final templateNames = ['Elegant', 'Modern', 'Minimalist'];
return Card(
margin: const EdgeInsets.all(12),
elevation: 4,
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(16)),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
children: [
Text(
'${templateNames[index]} Template',
),
const SizedBox(height: 12),
previews[index],
const SizedBox(height: 12),
],
),
),
);
},
),
);
}
}