Data Layer Architecture
Relevant source files
The following files were used as context for generating this wiki page:The data layer architecture of CertDb is designed around Astro's content collections, which provide a structured way to manage and query local content files. The core of this system is the certifications collection, which sources data from Markdown files. This data is then exposed through statically generated JSON API endpoints.
On the client side, a reactive datatable component consumes these JSON endpoints, implementing efficient, client-side search functionality using Fuse.js with a pre-computed search index. This architecture ensures that the certification data is both easy to manage for contributors and highly performant for end-users.
Content as Data: The certifications Collection
The primary data source for the application is a set of Markdown files located in src/content/certifications. Astro's content collection feature is used to parse these files, validate their frontmatter against a defined schema, and make the data available to the rest of the application.
Sources: src/content.config.ts
Schema Definition
The schema for the certifications collection is defined in src/content.config.ts using zod. This ensures type safety and data consistency for all certification entries.
The diagram below illustrates the structure of the certification data model.
Sources: src/content.config.ts:6-19
The table below details each field in the schema.
| Field | Type | Description | Required | Default |
|---|---|---|---|---|
title | z.string() | The full title of the certification. | Yes | |
acronym | z.string() | The acronym for the certification. | Yes | |
last_updated_at | z.date() | The date the certification information was last updated. | Yes | |
image | image() | An optimized image for the certification. | Yes | |
reference | z.string() | A URL to the official certification page. | Yes | |
aliases | z.array(z.string()) | An array of alternative names or acronyms. | No | undefined |
draft | z.boolean() | A flag to indicate if the entry is a draft. | No | false |
career_paths | z.array(z.enum(CareerPathsList)) | An array of associated cybersecurity career paths. | Yes | |
price | z.string() | The price of the certification. | Yes | |
currency | z.string() | The currency for the price. | Yes |
Sources: src/content.config.ts:8-19, src/lib/career-paths.ts:14-26
Data Model
The CertificationMetadata type defines the shape of a single certification record used throughout the application, from the API endpoints to the frontend components.
Sources: src/types/certification-metadata.ts
CertificationMetadata Interface
This interface ensures that data passed between different parts of the application is consistent.
// src/types/certification-metadata.ts
export interface CertificationMetadata {
image: string;
provider: string;
title: string;
acronym: string;
last_updated_at: Date;
reference: string;
aliases?: string[] | undefined;
career_paths: string[];
price: string;
currency: string;
slug: string;
}
Sources: src/types/certification-metadata.ts:1-13
The diagram below shows the class structure for the certification metadata.
Static API Endpoints
The application generates several static JSON files at build time. These files act as API endpoints that serve the certification data to the client-side application. This approach leverages Astro's static site generation for maximum performance.
The following diagram shows the data flow from Markdown files to the final JSON endpoints.
Core Data Endpoints
GET /database/data.json: This endpoint returns a JSON array containing the complete metadata for all non-draft certifications. It is generated bysrc/pages/database/data.json.ts.GET /database/data-index.json: To optimize client-side search, this endpoint provides a pre-computed Fuse.js search index for all certifications. It is generated bysrc/pages/database/data-index.json.ts.
Sources: src/pages/database/data.json.ts, src/pages/database/data-index.json.ts
Career Path Endpoints
The application also provides filtered data based on career paths.
GET /career-paths/[path]/data.json: A dynamic route that generates a JSON file for each career path (e.g.,/career-paths/penetration-tester/data.json). It contains only the certifications associated with that specific path.GET /career-paths/[path]/data-index.json: The corresponding pre-computed Fuse.js index for the filtered career path data.
The makeCareerPathLookupTable function creates a mapping from kebab-case URL paths to the proper career path names to facilitate this filtering.
Sources: src/pages/career-paths/[path]/data.json.ts, src/pages/career-paths/[path]/data-index.json.ts
Client-Side Data Consumption and Search
The ReactiveDatatable component is responsible for fetching, displaying, and enabling search on the certification data.
Sources: src/components/astro/database/reactive-datatable.tsx
Data Fetching and Initialization
On component mount, ReactiveDatatable fetches both /database/data.json and the pre-computed /database/data-index.json. It then initializes a new Fuse instance using the fetched data, the index, and a shared configuration. This allows for extremely fast client-side searching without needing to build the index in the browser.
The sequence diagram below illustrates the client-side data loading and search process.
Search Configuration
The search behavior is configured in src/pages/database/fuse.config.ts. This configuration specifies which fields of the CertificationMetadata object should be searched and assigns a weight to each, determining their relevance in the search results.
| Key | Weight | Description |
|---|---|---|
title | 0.7 | The primary field for searching. |
acronym | 0.6 | The certification's acronym. |
aliases | 0.5 | Alternative names for the certification. |
provider | 0.4 | The organization providing the certification. |
career_paths | 0.3 | Associated career paths. |
Sources: src/pages/database/fuse.config.ts:4-20
Summary
The data layer of CertDb is a robust system that leverages Astro's static site generation capabilities to deliver a fast user experience. By defining content in structured Markdown files, validating it with a schema, and serving it via static JSON endpoints, the architecture ensures data integrity and performance. The use of pre-computed Fuse.js indexes for client-side search further enhances responsiveness, providing users with a powerful and efficient way to explore cybersecurity certifications.