Frontend Architecture
Relevant source files
The following files were used as context for generating this wiki page:The frontend architecture of CertDb is built upon a modern web stack, leveraging the Astro framework to combine static site generation with dynamic, client-side interactive components built in React. This hybrid approach optimizes for performance and SEO while providing a rich user experience for features like the certification database. Styling is managed globally via Tailwind CSS, ensuring a consistent and maintainable design system.
The core of the user-facing application is the ReactiveDatatable, a client-rendered component responsible for fetching, displaying, searching, and paginating certification data. It relies on a set of reusable, headless UI components for its structure and functionality, including tables, buttons, and pagination controls. Data is fetched from JSON endpoints, and client-side search is accelerated by a pre-computed Fuse.js index.
Core Technologies & Frameworks
The project utilizes a combination of frameworks and libraries to build the user interface and manage its functionality. The primary technologies are defined in package.json and configured in astro.config.ts.
This diagram shows the main technologies and how they are integrated.
Sources: astro.config.ts:4-25, package.json:12-26
| Dependency | Version | Role |
|---|---|---|
astro | ^5.8.0 | Core web framework for building the static site. |
@astrojs/react | ^4.3.0 | Integration for using React components as interactive islands. |
@astrojs/tailwind | ^6.0.2 | Integration for utility-first CSS styling with Tailwind CSS. |
@astrojs/mdx | ^4.3.0 | Allows using JSX and components within Markdown files. |
react | ^18.3.1 | Library for building interactive UI components. |
fuse.js | ^7.1.0 | Library for client-side fuzzy searching. |
@headlessui/react | ^2.2.4 | Unstyled, fully accessible UI components. |
tailwindcss | ^3.4.17 | Utility-first CSS framework for styling. |
framer-motion | ^11.18.2 | Animation library used in components like the Navbar. |
| Sources: package.json:12-26, src/components/react/navbar.tsx:5 |
Project Configuration
Astro Configuration
The main configuration file astro.config.ts defines the site's behavior, integrations, and build process.
| Configuration | Value | Description |
|---|---|---|
site | https://certdb.cyberpath-hq.com | The base URL for the production site. |
output | static | Specifies that the project builds to static HTML, CSS, and JS files. |
trailingSlash | ignore | Configures how trailing slashes are handled in URLs. |
build.assets | assets | The directory name for bundled assets in the build output. |
| Sources: astro.config.ts:11-28 |
The file also registers key integrations:
@astrojs/tailwind: Enables Tailwind CSS with nesting support.@astrojs/react: Enables rendering of.tsxcomponents.@astrojs/sitemap: Automatically generates asitemap.xmlfile.@astrojs/mdx: Enables MDX content processing.
Sources: astro.config.ts:15-25
TypeScript Configuration
The tsconfig.json file sets up path aliases for cleaner import statements within the project.
| Alias | Path |
|---|---|
@components/* | src/components/* |
@layouts/* | src/layouts/* |
@assets/* | src/assets/* |
| Sources: tsconfig.json:6-14 |
UI Components
The UI is composed of a set of reusable React components, which are then integrated into Astro pages. A distinction is made between generic, reusable components (e.g., Button, Table) and feature-specific composite components (e.g., ReactiveDatatable).
Reusable Base Components
These components, located in src/components/react/, provide the foundational building blocks for the user interface. They are designed to be generic and are styled using clsx and Tailwind CSS classes.
| Component | File Path | Description |
|---|---|---|
Button | src/components/react/button.tsx | A highly customizable button component with variants for solid, outline, and plain styles, and numerous color schemes. It also supports being rendered as a Link. |
Link | src/components/react/link.tsx | A wrapper around the <a> tag integrated with Headless UI for data interactivity. |
Table | src/components/react/table.tsx | A set of components (Table, TableHead, TableBody, TableRow, TableCell, TableHeader) for rendering data tables with options for striped, grid, and dense layouts. |
Pagination | src/components/react/pagination.tsx | A collection of components (Pagination, PaginationPrevious, PaginationNext, PaginationList, PaginationPage, PaginationGap) to build accessible pagination controls. |
Navbar | src/components/react/navbar.tsx | Components for building the site's main navigation bar, using framer-motion for animations on the current item indicator. |
| Sources: src/components/react/button.tsx, src/components/react/table.tsx, src/components/react/pagination.tsx, src/components/react/navbar.tsx |
ReactiveDatatable Component
This is the central interactive component of the application, responsible for rendering the certification database. It orchestrates data fetching, state management, searching, and pagination.
The following diagram illustrates the component hierarchy of the ReactiveDatatable.
State Management
The component manages its state using React's useState hook.
| State Variable | Type | Description |
|---|---|---|
is_loading | boolean | Tracks the data fetching status to show a loading indicator. |
error | `string | null` |
all_raw_data | CertificationMetadataCollection | Holds the complete, unfiltered array of certification data. |
all_data | Fuse<CertificationMetadata> | A Fuse.js instance containing all data for efficient searching. |
query | `string | null` |
pagination | { page, total_pages, per_page } | An object containing the current pagination state. |
url_search_params | URLSearchParams | Stores the URL query parameters to manage state via the URL. |
| Sources: src/components/astro/database/reactive-datatable.tsx:36-52 |
Data Flow and Searching
Initial Data Loading
On component mount, ReactiveDatatable fetches the certification data and the pre-computed Fuse.js search index from two separate JSON endpoints. This process is handled within a useEffect hook.
This sequence diagram shows the data loading process.
Search and Filtering
The component provides a client-side search functionality powered by Fuse.js.
- The user types into the
HeaderSearchBar. - The
onInputevent updates thequerystate inReactiveDatatable. - A
useMemohook,display_data, re-computes the data to be displayed. - If
queryis not empty,all_data.search(query)is called to get filtered results from Fuse.js. - If
queryis empty, the fullall_raw_datais returned. - The table re-renders with the filtered or complete data, sliced according to the current pagination state.
This flow is illustrated below:
The use of a pre-computed index, generated at build time via src/pages/database/data-index.json.ts, significantly speeds up the initialization of Fuse.js on the client.
Sources: src/pages/database/data-index.json.ts:9-15, src/components/astro/database/reactive-datatable.tsx:229-237
Styling and Theming
The project uses Tailwind CSS for styling, configured in tailwind.config.ts.
Key aspects of the styling implementation include:
- Dark Mode: Enabled via
darkMode: "class". - Custom Font: The
Nunito Variablefont is set as the default sans-serif font. - Custom Animations: A
bounce-horizontalkeyframe animation is defined. - Plugins: The official Tailwind CSS plugins for
forms,typography, andaspect-ratioare used to provide sensible defaults for common UI patterns.
Sources: tailwind.config.ts:8-33
Component-level styles are defined directly in .tsx files using utility classes. The Button component is a prime example of this, with a large styles object containing complex class arrays for different variants, colors, and states (base, solid, outline, plain). This approach encapsulates styling logic within the component itself.
Sources: src/components/react/button.tsx:5-155