Project Detail

InixCert: Laravel-Based Digital Certificate Management Application

2026 • IT Training, Consulting, Professional Certification, Digital Credentialing • Aug 08, 2026
Web & App Development Custom Web & Mobile Apps

InixCert is a certificate management application developed to support the operations of an IT training and consulting provider in Indonesia. Previously, the certificate issuance process relied on scattered data, spreadsheet-based records, mail merge, local file storage, and several repetitive manual steps.

In this project, I worked as a Junior Web Developer, handling requirement analysis, domain modeling, backend and user interface development, as well as automated testing for the certificate issuance workflow.

The implementation resulted in a centralized workflow that connects participant import, data validation, queue-based certificate generation, PDF rendering, private file storage, and public certificate verification.

Scope Summary

My scope of work on InixCert included:

  • designing a modular monolith architecture for the credential operations domain;
  • modeling operational branches separately from credential issuers;
  • building authentication, roles, permissions, policies, and branch-level data restrictions;
  • developing master data management for events, training programs, workshops, activity batches, and certificate templates;
  • building CSV import functionality with row-level validation, email normalization, deduplication, and result summaries;
  • separating participant identity from participation context within individual activities;
  • implementing generation batches with participant scope selection and preview before confirmation;
  • creating one queue job for each certificate;
  • developing database-backed progress tracking and item-level failure handling;
  • creating PDF templates for attendance and course completion certificates;
  • developing certificate registry, preview, PDF download, and ZIP download functionality;
  • building public certificate verification with minimum data disclosure;
  • implementing certificate snapshots to preserve historical records;
  • adding safe deletion mechanisms, counter reconciliation, and audit logging;
  • providing reusable email templates, controlled personalization, HTML sanitization, and a queue-based mailing foundation;
  • writing automated tests for happy paths, validation, idempotency, storage, queue processing, and tenant isolation.

Challenge

1. Separating Event Organizers from Credential Issuers

The branch organizing an activity is not always the institution officially issuing the certificate.

Combining these concepts into a single entity could create inconsistencies in credential history and certificate template rules.

To address this, I separated the branch and issuer concepts.

Branches are used for operational context and data access boundaries, while issuers are separate entities representing the official authority responsible for issuing certificates.

2. Maintaining Participant Identity Without Losing Activity Context

Participant names alone are not reliable identifiers for deduplication.

At the same time, the same participant may join multiple activities with different packages, data sources, or certificate numbers.

The system therefore uses a canonical participant identity within each branch, while information such as package details, import source, row number, and certificate number is stored within participation records.

This approach reduces unnecessary duplication while preserving the context of each activity.

3. Processing PDFs Without Blocking Browser Requests

Rendering PDF documents with headless Chromium is a relatively resource-intensive process.

Running the entire operation inside a web request would require operators to wait for completion and increase the risk of request timeouts.

For this reason, certificate generation was moved into a background queue.

Each certificate is processed through an individual job, while its progress and processing status are stored in the database.

This allows the application interface to remain responsive without depending on a long-running browser request.

4. Maintaining Consistent Certificate Numbers

Some activities use automatically generated certificate numbers, while certain training programs use official numbers imported from external sources.

Both mechanisms need to operate without creating duplicate numbers or numbering collisions.

For internally generated numbers, sequence allocation is handled inside database transactions with locking mechanisms. External certificate numbers are validated before certificate records are created.

Jobs are also designed to be idempotent so retrying an operation does not generate a new number for certificates that have already been successfully processed.

5. Providing Public Verification Without Exposing Private Data

Certificates need to be publicly verifiable, but the verification page must not expose internal participant data or private certificate files.

To address this, public verification uses a dedicated public identifier and displays only the minimum information required to confirm certificate validity.

The original files remain stored in private storage and are accessible only to authorized users.

6. Separating Public Catalog Content from Private Batches

InixCert also supports workshop management for both public and private activities.

Content publication status alone is not sufficient to determine whether a workshop is safe to display publicly.

Public visibility rules are therefore applied at the database query level so corporate batches, private events, or content that is not yet ready for publication cannot appear through indexes, search results, detail pages, or aggregate counts.

Approach

Analysis

The development process started by mapping the existing certificate issuance workflow.

From this analysis, I found that the main problem was not simply PDF generation, but the relationship between:

  • activities;
  • participants;
  • issuers;
  • certificate numbers;
  • batches;
  • generated files;
  • and the certificate issuance lifecycle.

I separated master data from transactional data so future changes to participant information would not modify the historical data of certificates that had already been issued.

Strategy

I selected a modular monolith architecture using Laravel to keep delivery straightforward while maintaining clear domain boundaries.

The participant import workflow was separated from the certificate generator.

Participants must already be validated and associated with an activity before an issuance batch can be created.

This approach makes certificate generation more deterministic and prevents the generator from becoming an implicit pathway for creating new participant data.

Batch and certificate states were also defined explicitly.

Automatically generated certificate numbers are allocated using database transactions and locking, while externally sourced numbers are validated before certificate records are created.

Snapshots of recipient and issuer information are stored with each certificate so historical records remain consistent even when master data changes.

Implementation

CSV files are processed using a streaming approach.

Headers are normalized and each row is validated before the data is committed.

When an email address is available, it can be used to identify an existing participant within the same branch. Participants with identical names but insufficient identifiers are not automatically merged.

When an operator confirms an issuance batch, the system creates one queued job for each certificate.

Each job:

  1. reloads the certificate record;
  2. checks whether the item has already been completed;
  3. renders a Blade view into PDF using Chromium;
  4. stores the file in private storage;
  5. updates the certificate status;
  6. updates batch progress atomically.

The application interface reads progress directly from the database, allowing processing status to remain available even when the browser page is refreshed.

For public verification, verification codes are directed to dedicated permanent URLs.

These pages display only the required registry information and certificate snapshot, while PDF file locations and internal data remain private.

Validation

Implementation validation was performed through unit tests and feature tests.

Test scenarios include:

  • data import;
  • participant deduplication;
  • participant selection;
  • certificate numbering;
  • queue dispatch;
  • idempotency;
  • batch status;
  • PDF rendering;
  • private storage;
  • file downloads;
  • public verification;
  • authorization;
  • and cross-branch access denial.

Laravel Pint and production asset builds were also used as additional quality checks before delivery.

Key Features / Implementations

Participant Registry and CSV Import

Participants are stored as canonical identities within the context of each branch.

Package and activity-specific information is stored within participation records, allowing the same participant to join multiple programs without creating unnecessary duplicate identities.

The import process provides summaries for:

  • valid rows;
  • invalid rows;
  • new participants;
  • existing participants;
  • and duplicate records.

Certificate Generation Engine

The certificate generator retrieves participants from stored activity data and applies the required issuance scope.

Operators can select all eligible participants or specific participant groups before confirmation.

Batch and certificate records are created within a transaction, after which each certificate is processed through an independent queue job.

This approach allows failures to be handled at the individual certificate level without causing the entire batch to fail.

Numbering and Immutable Snapshots

Internal certificate numbers are allocated using a locking mechanism.

For activities using external numbering, official source numbers are preserved and checked for duplication.

Certificates also store snapshots of important information, including:

  • recipient name;
  • issuer;
  • activity title;
  • activity period;
  • certificate number.

These snapshots preserve historical certificate information even when the associated master data is later updated.

PDF Generation, Private Storage, and Downloads

Blade-based print views are rendered into A4 PDF documents using Chromium.

Attendance and course completion templates use official artwork with controlled dynamic data placement.

Generated files are stored in private storage.

Authorized users can access certificates through:

  • preview;
  • individual PDF download;
  • batch ZIP download.

Public Certificate Verification

Completed certificates can be verified using a public identifier.

The identifier resolves to a canonical verification URL.

The verification page displays only the minimum information required to confirm certificate validity without exposing private file paths or unnecessary participant information.

Multi-Branch Authorization and Audit

Queries, policies, middleware, and relational constraints are used to restrict access according to the user's branch.

Specific roles can be granted explicit cross-branch capabilities when required.

Important actions such as data imports, certificate generation, deletion, and configuration changes are logged to support traceability and auditing.

Workshop CMS and Email Foundation

In addition to credential operations, InixCert includes a Workshop CMS foundation covering:

  • categories;
  • collections;
  • SEO metadata;
  • workshop schedules;
  • activity batches;
  • public visibility rules.

For communication workflows, the application also provides reusable email templates, controlled personalization tags, HTML sanitization, activity-specific drafts, subscriber lists, and a queue-based mailing foundation.

Case Study

Problem

Certificate issuance previously depended on several disconnected tools and files.

Participant data, certificate numbers, templates, and generated PDF files were not managed within a single traceable lifecycle.

As the number of activities and participants increased, the manual workflow resulted in more repetitive work and a greater risk of data inconsistencies.

Analysis

I concluded that improving PDF rendering speed alone would not solve the underlying problem.

The system needed to validate data before rendering, maintain relationships between participants and activities, manage certificate numbering, track the status of individual certificates, and provide public verification without exposing private files.

Action

I developed a sequential certificate issuance workflow:

  1. create activity master data;
  2. import participants;
  3. validate participant data;
  4. select the template and recipient scope;
  5. create certificate snapshots;
  6. confirm the issuance batch;
  7. process PDF generation through the queue;
  8. store generated files in private storage;
  9. display progress from the database;
  10. provide public certificate verification.

At the application level, I also implemented database transactions, unique constraints, idempotent job behavior, branch-scoped authorization, audit logging, and minimum disclosure principles for public verification.

Result

InixCert provides a centralized certificate issuance workflow connecting participant data, generated PDF files, and public verification pages.

Operators do not need to wait for PDF rendering to complete within the browser request.

Each certificate can be tracked individually, and a failure affecting one certificate does not remove visibility into other items within the same batch.

The underlying data structure also supports multiple issuance contexts, including internal events, training programs with external numbering, workshops, and gradual expansion into multi-branch operations.

Outcome

Business Impact

  • Consolidated previously fragmented processes into a more centralized operational workflow.
  • Reduced repeated participant data entry by allowing participant records to be reused within the same branch context.
  • Established a searchable and traceable certificate registry.
  • Created a foundation for standardized certificate issuance across multiple branches.

Technical Impact

  • Moved resource-intensive PDF generation from synchronous web requests into background queue processing.
  • Maintained numbering and batch counter consistency using transactions, locking, and unique constraints.
  • Preserved certificate history using recipient and issuer snapshots.
  • Designed storage and PDF rendering components so they can be replaced with fake implementations during automated testing.
  • Limited data exposure through public verification and workshop catalog visibility rules.

User Experience Impact

  • Operators receive import validation results and error summaries before certificate generation begins.
  • Batch previews allow participants, certificate numbers, and templates to be reviewed before processing.
  • Processing progress remains available through database-backed state even after the page is refreshed.
  • Generated certificates can be accessed through previews, individual downloads, or batch ZIP downloads depending on operational requirements.

Project Detail

The InixCert project originated from a certificate issuance process that involved multiple disconnected files and operational steps.

Participant data was managed through spreadsheet-based documents, certificate generation relied on mail merge, generated files were stored locally, and operators had to perform several repetitive tasks manually.

This process introduced several challenges:

  • participant data was difficult to track across different activities;
  • certificate formats and data could become inconsistent;
  • generating documents in large batches placed additional workload on operators;
  • certificate issuance history was difficult to trace centrally;
  • managing multiple branches required clear data access boundaries.

InixCert was developed to create a centralized workflow capable of storing activity and participant data, validating information before certificate issuance, processing certificates asynchronously, and preserving the history of every generated certificate.

The system was also designed to support multiple branches without mixing operational data between units while separating the branch responsible for organizing an activity from the institution officially issuing the credential.

From an architectural perspective, the application uses a modular monolith approach. This architecture was selected to maintain clear domain boundaries without introducing the additional complexity of a distributed system that was not yet necessary.

The implementation focuses not only on generating PDF files, but also on maintaining the integrity of the entire credential lifecycle, from participant data to public certificate verification.

https://www.inixindo.id/p/cert/verify

VISIT