Project Design
This blog post is about why I chose my current design pattern for writing my website generator.
My Design Choices For Websites Generator

This is a small blog where I explain some of my design choices for my website generator.
It is also a demonstration of the project itself, since this blog post (and the website you are reading it on) is generated by the tool.
1. Why I Built It
I wanted to learn how static site generators work internally and design one myself, with a focus on:
- Flexibility -> supporting different site types like blogs, shops, portfolios.
- Extensibility -> making it easy to add new features through plugins.
- Clarity -> keeping the codebase small but structured enough to be maintainable.
This project also serves as a portfolio project for my resume, to show my understanding of design patterns and architecture.
2. The Core Abstractions
I designed three main building blocks:
-
Page
Represents a single page (Markdown, HTML, or other). It holds metadata, content, and output paths.
I added attributes likeslug,page_type, andoutput_pathso the generator can reason about where and how to render the page. -
Site
Holds all pages, global metadata, and exposes methods likeget_pages().
This makes it easy to query pages (for example, a plugin can find all pages withtype: blog). -
Project
Orchestrates everything: configuration, loading pages, running plugins, and rendering.
By separating "orchestration" (Project) from "data" (Site, Page), the design stays modular.
3. The Plugin System
Instead of hardcoding features like a blog index or RSS feed, I added a plugin system.
Plugins can hook into lifecycle events:
after_config_loadedbefore_buildafter_document_loadedafter_build
For example, my CollectionIndexerPlugin searches for all pages in a collection and automatically generates an index page.
This pattern is common in real-world projects because it balances simplicity with extensibility.
4. Content Processors and Template Engine
To process different input formats (Markdown, HTML, etc.), I added a ContentProcessor factory.
This way, supporting new formats in the future will be as simple as writing a new processor class.
Rendering is done through a Template Engine factory, which abstracts away the underlying templating engine.
This allows swapping templating logic later without changing the rest of the system.
5. Tradeoffs I Made
- Focused on clarity over optimization -> readability mattered more than micro-optimizations.
- YAML config -> I chose YAML because it is widely used in static site generators and is more readable than JSON for non-developers.
6. What I Learned
Through this project I practiced:
- Designing modular, extensible systems.
- Using factories and plugins to decouple responsibilities.
- Writing cleaner Python with logging, type hints, and tests.
- Building something practical enough to showcase.
7. What's Next
- Add more plugins.
- Improve test coverage.
- Deploy this demo site to show the generator in action.