Building PicoSSG: 'Just Enough Code'

This is the story of how PicoSSG came to be - from its humble beginnings as a minimal static site generator to its current form. It's a journey about finding the sweet spot between features and simplicity, about writing "just enough code" to get the job done without unnecessary complexity.
The Genesis of PicoSSG
The static site generator (SSG) landscape is crowded with feature-rich but increasingly complex solutions. As I looked at and used tools like lume, 11ty, lektor, or jekyll, I found myself drowning in configuration options, plugins, and middleware. What started as a simple desire to convert Markdown content into HTML had evolved into learning complex frameworks with steep learning curves.
I wanted something radically simple – a tool that would do just what I see an SSG needs to do: markdown, templating, and simple data handling. The vision was clear: process templates and markdown files predictably, with minimal dependencies and a non-magic transformation process.
On a spring day in April 2025, the very first lines of code emerged with a commit message that says it all: "The simplest processor, I think." This established the minimalist approach that would guide the entire project. Just a few lines of code to process nunjucks templates and nothing more.
The second commit was a simple test to ensure the processor worked as expected, I just have this testing in my blood. I mean how can one write software that grows and becomes bigger than what one can hold in their head without testing?
Even the testing must be simple, so I just compared the output with the expected output using the diff
command, and that's how PicoSSG still works.
The Minimal and Maximum Feature Set
From day one, I defined a clear boundary around what PicoSSG would and wouldn't do. The minimal feature set was non-negotiable:
Markdown processing - For content-focused writing without HTML clutter
Nunjucks templating - For layout flexibility and component reuse (introduced in the project's first week)
1:1 file mapping - Direct correspondence between source and output files, preserving structure without hidden transformations
Simple JS configuration - A single entry point for extending functionality through JavaScript
Just as important were the deliberate limitations - features PicoSSG would never implement:
Do the job without configuration and plugins
No hidden magic or implicit transformations
No dependencies beyond absolute necessities
The power of PicoSSG would come not from feature abundance but from its extensibility through a simple JavaScript interface. Need to process data? Write a function preprocess()
or postprocess()
in _config.js
, there is no more. Need custom template filters, extend nunjucks (not picossg!)? Create them in _njk-custom/filters.js
. This approach maximizes flexibility if needed while keeping the code small.
v1 – The Minimal Viable Product
A critical early feature was component inclusion. Rather than creating a complex component system, PicoSSG adopted a simple convention: files starting with underscore (_
) would be excluded from output but available for inclusion. This elegant approach allowed for reusable components without special handling.
Testing was also simple but effective - a straightforward comparison between generated output and expected results. By the end of the first day, a basic test setup was in place that would evolve but remain fundamentally simple.
Within 24 hours of the project's birth, PicoSSG had a README and was taking shape as a usable tool, albeit with limited features.
Evolving the Foundation: v2
About a week into development, a breakthrough came with the message "Now the front-matter block parsing is completely dynamic". This allowed metadata to be associated with content without complex infrastructure. The decision process is documented in ADR-001, which compares different approaches and ultimately selects front-matter for its compatibility with other tools and clean syntax.
The extension processing pipeline also matured during this period. The next morning brought a key insight that established the right-to-left processing of extensions, allowing combined file types like .
html.md
.njk
to be processed in sequence. Processing simply stops when there is no more "known" extension to process. Theoretically, one could also build a file such as index.html.md.njk.md.md.md
.njk
. Not sure that makes sense though :).
After a weekend of experimentation, custom filters became possible, and by the following evening, the project added two default filters: md
and mdinline
for Markdown processing within templates.
Architectural Decisions That Shaped PicoSSG
Several key architectural decisions shaped PicoSSG's development, many documented as Architecture Decision Records (ADRs):
ADR-001 explored different approaches to handling mixed Markdown and Nunjucks content, ultimately selecting front-matter as the simplest approach that maintained compatibility with other tools.
ADR-002 made the important design decision to allow user processors to modify the files map directly, optimizing for performance and memory efficiency at the cost of potential side effects.
ADR-003 documented the choice of markdown-it over alternatives like marked, based on careful evaluation of edge cases and built-in features like URL linking.
The decision to avoid framework dependencies and stick to a minimal set of npm packages was not formally documented but is evident throughout the codebase. This approach kept the tool lightweight and reduced potential points of failure from external dependencies.
v3 – Maturing the Codebase
Version 3.0 represented a significant maturation of PicoSSG while remaining true to its minimalist principles. In mid-May, preparations for this release were underway.
A major improvement came in the metadata handling. Two weeks after the project began, a subtle but important change restructured how data was passed to templates, making it more convenient while maintaining access to the original structure. Later that same day, another refinement further simplified template data access.
As the project approached its third week, the pre/post processing capability was significantly enhanced, allowing user-defined functions to transform content before and after the main processing pipeline. This expanded what users could do without adding complexity to the core.
Just days before the v3 release, performance improvements appeared with a change that parallelized file writes for better efficiency: "Make the writing of the files as parallel as it can be :)." Maybe it was just me proving I know Promises a bit :). But I have to say adding await
in front of every async operation does not feel right most of the time, even though there is a lot of room for improvement also in this project.
With clarity that comes from real-world usage, the directory structure was reorganized to make the project more intuitive for newcomers.
The Philosophy in Action
Throughout PicoSSG's development, the philosophy of "less code, not smarter code" remains evident. At one point, a commit message proudly declared: "I gladly removed (more) code." This reflects the core belief that the best code is often code you don't have to write or maintain.
The 1:1 file mapping isn't just an implementation detail but a fundamental design principle that creates predictability. Users can look at their source directory and immediately understand what the output will be, without hidden transformations or magic.
The project embraces convention over configuration without hiding complexity. Rather than extensive configuration options, PicoSSG uses simple conventions (like files starting with underscore being excluded) that are easy to remember and reason about.
This minimalist approach leads to more maintainable and understandable code. The entire build process in build.js
is under 300 lines, making it possible for users to read and comprehend the entire codebase if needed - something impossible with larger SSG frameworks.
Looking Forward
The roadmap for PicoSSG's future is outlined in the CHANGELOG.md, with plans for continued refinement rather than feature explosion. Ideas like adding size information and processing times represent the kind of thoughtful additions that add value without complexity.
The most important challenge going forward will be maintaining the balance between adding useful capabilities and preserving the simplicity that makes PicoSSG special. Each potential feature must be evaluated against the core philosophy: does it add enough value to justify the additional code and complexity?
Examples like JSCraftCamp.org's 2025 site and picostitch.com demonstrate that PicoSSG is already capable of building real-world sites with its minimal feature set. This validates the core premise - that for many static sites, "just enough code" is indeed enough.
In a world where software tends toward bloat and complexity, PicoSSG stands as a reminder that sometimes, less is truly more.
You see more code that can be removed? Let me know, please.
Subscribe to my newsletter
Read articles from Wolfram Kriesing directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Wolfram Kriesing
Wolfram Kriesing
I am currently building a startup for monitoring website speed, but not the Core Web Vitals, but the numbers behind the curtain that you can monitor and really get a grip on. Wanna know more? Ping me!