Connect with Amin Boulouma Official
End-to-End Integration Testing of Jekyll with Concrete Templates
We have constructed individual parsing processors for Markdown and YAML, implemented clean abstraction wrappers around network/file I/O operations, and engineered an orchestration facade. To tie our series together, let’s look at an end-to-end integration test case using a concrete layout schema and global configuration payload.
This walkthrough demonstrates exactly how our token hydration system marries templates, asset definitions, and static configurations together in production.
1. The Inputs: Configuration and Base Layout
To initialize the compilation pipeline, the site relies on two vital core files: a localized global state configuration (config.yaml) and an HTML template blueprint shell (layout.html).
Global Site State (config.yaml)
This configuration models key-value data mappings containing site-wide attributes:
title: AI Systems Design From First Principles
description: Rebuilding enterprise systems and AI from first principles.
url: https://aminblm.github.io/ai_systems_design_from_scratch
css: ../styles.css
author: Amin Boulouma
footer_text: AI Systems Design From First Principles
The Document Blueprint (layout.html)
This file uses explicit Liquid-style double-curly-brace interpolation markers (``) to indicate exactly where dynamic content strings belong:
<!DOCTYPE html>
<html>
<head>
<title> AI Systems Design From Scratch </title>
<link rel="stylesheet" href="">
</head>
<body>
<div class="hero">
<header>
<h1>AI Systems Design From Scratch</h1>
<p>Rebuilding enterprise systems and AI from first principles.</p>
</header>
</div>
<main>
<div class="container">
</div>
</main>
<footer>
<div class="container">
<p><a href="https://aminblm.github.io/ai_systems_design_from_scratch"> by {"name"=>"Amin Boulouma", "bio"=>"Software Engineer"}</a></p>
</div>
</footer>
</body>
</html>
2. Behind the Scenes: The Hydration Logic
When you trigger the entrypoint via Jekyll.generate_site(input_dir, layout_path, config_file_path), our engine handles compilation through an elegant substitution loop inside HTMLRenderer.render_html.
Let’s look at the data mutation sequence step-by-step:
Step A: Markdown Splitting & Translation
First, the rendering framework isolates an active post (e.g., welcome.md) and compiles its markdown payload to raw structural HTML. The template placeholder is then swapped out with this newly generated content body:
html = layout.replace('', MarkdownToHTMLBuilder.create_from_file(md_file_path).md_file_to_html())
Step B: Recursive Dictionary Hydration
Next, our YAMLParser mapping object is looped over line by line. Every key found inside config.yaml explicitly overwrites its matching layout placeholder:
for key in config:
html = html.replace('', config[key])
3. The Compiled Output
Once FileOperations.write_html_content finishes committing the text stream to disk inside the newly formed /output destination folder, your resulting output is a completely unified, zero-dependency HTML document ready for delivery:
<!DOCTYPE html>
<html>
<head>
<title> AI Systems Design From First Principles </title>
<link rel="stylesheet" href="../styles.css">
</head>
<body>
<div class="hero">
<header>
<h1>AI Systems Design From First Principles</h1>
<p>Rebuilding enterprise systems and AI from first principles.</p>
</header>
</div>
<main>
<div class="container">
<p>Welcome to the first principles system generation workspace!</p>
</div>
</main>
<footer>
<div class="container">
<p><a href="https://aminblm.github.io/ai_systems_design_from_scratch">AI Systems Design From First Principles by Amin Boulouma</a></p>
</div>
</footer>
</body>
</html>
Systems Review and Architecture Summary
Over this multi-part series, we took a seemingly complex task—cloning an enterprise static site generator—and split it into lightweight, single-responsibility layers:
JekyllFacade: Provides a clean single-line API for compilation.DependenciesManager: Decouples file lookups and loading from the transformation logic.HTMLRenderer: Handles string template compilation as a deterministic, stateless pipe.ErrorHandler: Abstracts out error boundaries via clean Python decorators, protecting processing loops from runtime edge-case crashes.
By designing code around explicit boundaries and relying on zero external packages, your architecture remains fast, stable, and simple to test or extend indefinitely.