zest-ssg/zest
46.1
Weak · 3 October 2026
24.7k
lines of production code
F#
with C#
2
measurements over time
What this system is
Zest is a static site generator built on .NET 10 that processes content using a flexible F\#-based DSL and supports multiple template engines including Nunjucks, Handlebars, Liquid, Haml, and Pug. It features a robust build pipeline with incremental caching, parallel processing, and atomic file writes to ensure fast and reliable site generation. The system provides a comprehensive CLI for project scaffolding, migration from other generators, and local development with live-reload capabilities.
Features
Introduce Oxygen starter theme with editorial design
The Oxygen starter theme is now available as the default theme for Zest, replacing the previous 'duo' theme. This theme features an editorial, single-article LaTeX-inspired design with a serif font stack, centered paper-style layouts, and responsive styling. It includes new template components for the page head, header, and post layout, along with a TOML configuration file defining the theme metadata.
_src/Zest.App/Starters/\themes · high confidence
Introduce PermalinkRouter for deterministic URL and output path generation
Added PermalinkRouter.fs to handle URL slug generation and route computation for content pages. This module ensures deterministic incremental builds by providing pure transformations that map relative paths and slugs to consistent URL and output file paths. It includes logic to slugify text (handling invalid characters, hyphens, and case) and to compute both explicit permalinks (supporting directory-style URLs ending in index.html) and default routes based on file names like 'index' or 'default'.
src/Zest.Engine/Routing · high confidence
Introduce custom Handlebars template engine with full Mustache compatibility
The system now includes a new Handlebars (Hbs) template engine alongside existing options. This engine provides a complete implementation of the Handlebars/Mustache syntax, including support for block helpers (if, unless, with, each), inverted sections, partials, partial blocks, block parameters, and @-data variables. It features built-in helpers for comparisons (eq, ne, lt, gt, lte, gte), logical operations (and, or, not), and data lookup, while ensuring HTML escaping by default for double-mustache expressions. The engine supports user-registered inline helpers and includes caching for both parsed ASTs and loaded partials to improve performance.
src/Zest.Engine/Template/HbsEngine · high confidence
Introduce development server with live-reload and build animation
The \src/Zest.Infra/Services\ directory now provides the core infrastructure for the local development experience. A new \DevServer\ handles file watching, incremental rebuilds, and live-reload via WebSocket (with an SSE fallback). This is supported by a \BuildAnimator\ that displays a real-time progress bar and spinner in the terminal, and a \FileWatchController\ that debounces changes and distinguishes CSS-only updates for style injection. Supporting services include \HttpServer\ (with ETag caching and path traversal protection), \ErrorPage\ (styled 404s with path suggestions), \DirectoryListing\, and \MimeMapper\.
src/Zest.Infra/Services · high confidence
Introduces incremental build caching and configurable HTML minification
The engine now supports incremental builds by tracking file modification times and content hashes, ensuring only genuinely changed pages and their dependents are rebuilt. It also adds a new HTML minification phase with configurable compression levels (Safe, Aggressive, Extreme) and formatting options, allowing users to optimize output size while preserving content integrity.
Zest.Engine · high confidence
New CLI commands for project scaffolding, migration, and cleanup
The \zest\ CLI now includes \scaffold\ to generate new projects from bundled 'blog' or 'empty' templates, \migrate\ to convert existing Jekyll, Hexo, Hugo, or Eleventy sites into Zest projects (including frontmatter and config conversion), and \clean\ to remove build artifacts and caches. Additionally, \init\ now extracts the starter site from embedded assembly resources rather than relying on on-disk template folders, ensuring the tool works immediately after installation without external file dependencies.
src/Zest.App/Controllers · high confidence
New HTML DSL and template engine components
The engine now includes a comprehensive HTML DSL and template system located in src/Zest.Engine/Html. This adds a set of F\# modules providing a fluent API for building HTML elements, attributes, and modifiers (HtmlElements, HtmlAttributes, HtmlModifiers), high-level UI components like cards, navbars, and pagination (HtmlComponents), and a Page Builder computation expression for defining page metadata and content structure (PageBuilder). It also introduces a Markdown-to-HTML converter (MarkdownEngine), a shortcode registry supporting 11ty.js-style syntax (ShortcodeRegistry), and helpers for template data and styling (HtmlHelpers, TemplateData).
src/Zest.Engine/Html · high confidence
New i18n loader, embedded pjax script, and theme resolver added
The engine now includes a new LocaleLoader module that parses TOML and JSON locale files, flattens nested keys, and supports a deterministic fallback chain (requested language → default → key) with {name} parameter interpolation. A self-contained pjax script (ZestPjax) is embedded for client-side navigation with caching, prefetching, and reduced-motion support. Additionally, a ThemeResolver module handles theme resolution from local, git, URL, or path sources, caching fetched themes in .zest/themes/ and cleaning up failed attempts.
src/Zest.Engine/I18n · high confidence
New template converters for Haml, Liquid, and Pug
The template engine now includes dedicated converters for Haml, Liquid, and Pug syntax, translating them into Nunjucks directives for unified rendering. Haml support covers tag structures, attributes, filters, and interpolation, while Liquid conversion maps standard tags and filters to their Nunjucks equivalents to allow existing Liquid templates to render without a separate engine. Pug files are converted via an indentation-aware parser that handles blocks, mixins, and control flow, ensuring dialect parity with the underlying Nunjucks kernel.
src/Zest.Engine/Template · high confidence
Starter site now includes RSS, Atom, and Sitemap feeds
The starter template now automatically generates RSS, Atom, and XML Sitemap files for new sites. These new content files (rss.zest.fsx, atom.zest.fsx, sitemap.zest.fsx) use the site's page data to create standard feed and sitemap outputs, improving discoverability and syndication for sites created with the starter.
src/Zest.App/Starters/content · high confidence
Support for multiple front matter formats in page metadata parsing
The engine now parses page front matter from three interchangeable header formats—TOML (delimited by +++), F\# comment headers (/// @key value), and HTML comment headers (\<!-- @key value --\>)—and normalizes them into a unified ContentMeta record. This allows authors to choose their preferred metadata syntax while ensuring consistent downstream rendering and proper stripping of metadata comments from the page body.
src/Zest.Engine/Parsing · high confidence
Zest.Dsl reorganized into layered modules with expanded HTML, CSS, and data APIs
The Zest.Dsl library has been restructured from a flat layout into layered directories (Core, Css, Data, Html) to improve maintainability. This change introduces a comprehensive set of new DSL helpers: Core adds HTML element builders (including semantic tags and class-shortcut variants like divC), a build context for FSI scripts that converts JSON site data to native CLR types, and a scoped CSS engine for component-style isolation. The Css layer provides a ZCSS computation expression for writing stylesheets, a validator with configurable severity levels, and a unified style API for inlining, scoping, and managing external stylesheets. Data exposes new collection query APIs for paginating, sorting, filtering, and grouping site pages, as well as tag clouds and related-page detection. Finally, Html includes pre-built component builders for forms, navigation, alerts, and layout structures.
Zest.Dsl, src/Zest.Dsl · high confidence
Removals
Removal of Zest Engine static site generator core
The Zest Engine module, which provided the core static site generation capabilities, has been removed. This deletion eliminates the build pipeline that processed content files (Markdown and F\# scripts), applied layouts, and compiled assets. It also removes the associated domain models, front-matter parsing, HTML DSL, permalink routing, and the ZSS (Zest Style Sheet) compiler used for styling.
src/Zest.Engine · high confidence
Behavioural changes
Expanded CLI with new commands and polished help output
The Zest CLI now includes new commands for scaffolding projects from presets (scaffold), migrating content from other static site generators like Jekyll or Hugo (migrate), converting configuration formats between YAML and TOML (convert-config), and clearing build artifacts (clean). The help display has been redesigned with a branded banner, aligned two-column rows for better readability, and additional options for verbose and quiet logging. Error handling for unknown commands now uses the centralized logging writer instead of direct console color manipulation.
src/Zest.App · high confidence
Introduce unified CLI argument parsing and structured help rendering
The command-line interface now uses a centralized parser (CommandParser) and typed option records (CommandOptions) for the build, serve, preview, and init commands, replacing previous ad-hoc parsing. This change standardizes common flags like --verbose, --quiet, and --help across all commands and introduces specific options such as --port, --host, --open, --spa, --watch, --livereload, and --dir where applicable. Additionally, help output is now rendered via a dedicated HelpRenderer that loads branding, version, and footer information from a bundled zest.toml configuration file, ensuring consistent and maintainable CLI help text.
src/Zest.App/CommandLine · high confidence
New scripting subsystem with persistent FSI and Nunjucks filter registry
The scripting layer has been restructured into dedicated modules: a persistent FsiSession replaces per-run process cold starts to speed up script evaluation, a FilterRegistry centralizes Nunjucks custom filters (including Zest extensions like pages\_by\_tag, recent, by\_collection, search, and locale-aware t()), and a ScriptDiscovery module handles DLL isolation to prevent FSharp.Core version conflicts. PageQuery now provides optimized, cached access to page data, tags, and collections for template rendering, while ScriptEvaluator manages content evaluation with Nunjucks context caching and support for multiple template engines (Nunjucks, Hbs, Liquid, Haml, Pug).
src/Zest.Engine/Scripting · high confidence
Nunjucks template engine restructured with expanded macro and expression support
The Nunjucks template engine has been reorganized into dedicated source files (tokenizer, compiler, evaluator, renderer, and block collector) to improve maintainability. This change introduces support for defining and using Nunjucks macros with named arguments and default values, allowing templates to define reusable content blocks. Additionally, the expression system now includes a precompilation layer that caches parsed expressions, significantly improving rendering performance for templates containing loops with complex expressions. The engine also now correctly handles block inheritance and nested comments.
src/Zest.Engine/Template/NunjucksEngine · high confidence
Parallelized build pipeline with incremental caching and atomic file writes
The build engine has been rewritten to significantly improve build speed and reliability. Content processing is now fully parallelized, with asset copying and metadata extraction running concurrently. An incremental build mode is introduced, which caches page outputs and rebuilds only genuinely changed pages based on content hashing, avoiding unnecessary full-site regenerations. To prevent file-lock errors during live preview or concurrent access, output files are now written atomically using a temporary file and rename strategy with retry logic. Additionally, the system now supports loading global data from TOML and JSON files in the \_data directory, merging theme and project data with correct priority.
src/Zest.Engine/Build · high confidence
Refactored configuration loading with validation and caching
The configuration loading logic in \src/Zest.Infra/Configuration\ has been restructured to improve reliability and performance. The previous \SiteConfigLoader\ has been replaced by a new \ConfigLoader\ that includes file-change caching to avoid redundant parsing during incremental builds. A new \ConfigGuard\ class now validates the loaded \SiteConfig\ at startup, issuing warnings for common misconfigurations such as missing content or layouts directories, empty site titles or base URLs, and conflicting dev server and live reload ports. Additionally, the \RootFinder\ utility has been extracted to handle project root detection, and TOML parsing helpers are now centralized in \TomlReader\.
src/Zest.Infra/Configuration · high confidence
Zcss engine reorganized into modular, layered components
The Zcss engine has been restructured into distinct layers to improve maintainability and clarity. The new layout separates concerns into \Builtins\ (containing predefined utility classes and module resolution helpers), \Compilation\ (handling the main processing pipeline, caching, and \@use\ import resolution), \Evaluation\ (managing value resolution, math evaluation, color manipulation, and built-in functions), and \Parsing\ (implementing brace-mode and indent-mode parsers). This reorganization introduces a modular pipeline where \Processor.fs\ acts as the public entry point, delegating to specialized modules for parsing, variable resolution, and compilation, while \ZcssHelpers.fs\ centralizes the resolution of built-in modules like \zest:utilities\ and \zest:palette\.
src/Zest.Engine/Zcss · high confidence
Zest Static Site Generator version 0.8.0
This release updates the Zest SSG to version 0.8.0, introducing a restructured project layout with a dedicated Zest.Dsl F\# module and a new CLI metadata configuration file (zest.toml) for branding and help text. The solution file has been renamed to lowercase (zest.sln) to follow naming conventions, and the .gitignore has been updated to exclude broader site output directories (docs/, site/, themes/, tests/). The README has been significantly redesigned to highlight new features such as inline Markdown support, ZCSS math expressions, and 11ty-compatible template engines, while the build configuration now targets .NET 10.0 and enforces stricter code style and documentation standards.
(repo-wide) · high confidence
Dependencies
Zest SSG project structure and packaging overhaul
The Zest static site generator has been restructured into distinct projects (Zest.Dsl, Zest.Engine, Zest.Infra, Zest.App) and reconfigured as a .NET tool. The CLI application now targets .NET 10 as a framework-dependent, platform-neutral tool (removing the previous win-x64 self-contained constraint) and embeds starter site assets and branding configuration. The engine and DSL projects now explicitly reference Tomlyn 0.17.0 for TOML parsing and include a comprehensive set of source files for features like ZCSS, Haml/Pug/Liquid converters, and Nunjucks/Handlebars engines, while Zest.Infra exposes internals for testing.
(dependencies) · high confidence
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
How this codebase got here
Score
- CAI 48 → 46 (-1.5)
- Rubric changed (rubric-2026.09.13 → rubric-2026.10.1) — scores are not directly comparable.
Lenses
- Code Health 62 → 62 (+0.0)
- Architecture 75 → 75 (+0.0)
- Maturity 55 → 55 (-0.1)
- Readiness 48 → 48 (+0.0)
- Security 40 → 37 (-3.1)
Resolved (16)
- Ambiguous method naming and potential functional overlap. 'ExecutePreview' suggests a specific mode of execution, but it is a sibling method to the generic 'Execute' on the same controller. It is unclear if 'Execute' handles both modes via args or if 'ExecutePreview' is a legacy/alternative entry point. This creates confusion about the primary entry point for the serve functionality.
- Documentation: no installation or build instructions (README.md)
- Documentation: no usage examples (README.md)
- Duplicated block (5–7 lines × 2) (src/Zest.Engine/Build/TaxonomyGenerator.fs)
- Hotspot: src/Zest.App/Controllers/ConfigConverter.cs (src/Zest.App/Controllers/ConfigConverter.cs)
- Hotspot: src/Zest.Dsl/Css/CssValidator.fs (src/Zest.Dsl/Css/CssValidator.fs)
- Hotspot: src/Zest.Engine/Html/HtmlFormatter.fs (src/Zest.Engine/Html/HtmlFormatter.fs)
- Hotspot: src/Zest.Engine/Template/HbsEngine/HbsParser.fs (src/Zest.Engine/Template/HbsEngine/HbsParser.fs)
- Hotspot: src/Zest.Engine/Template/HbsEngine/HbsRenderer.fs (src/Zest.Engine/Template/HbsEngine/HbsRenderer.fs)
- Hotspot: src/Zest.Engine/Template/HbsEngine/HbsTokenizer.fs (src/Zest.Engine/Template/HbsEngine/HbsTokenizer.fs)
- Hotspot: src/Zest.Engine/Template/NunjucksEngine/NunjucksEvaluator.fs (src/Zest.Engine/Template/NunjucksEngine/NunjucksEvaluator.fs)
- Hotspot: src/Zest.Engine/Template/NunjucksEngine/NunjucksRenderer.fs (src/Zest.Engine/Template/NunjucksEngine/NunjucksRenderer.fs)
- Hotspot: src/Zest.Engine/Theme/ThemeConfigLoader.fs (src/Zest.Engine/Theme/ThemeConfigLoader.fs)
- Hotspot: src/Zest.Engine/Zcss/Evaluation/BuiltinFunctions.fs (src/Zest.Engine/Zcss/Evaluation/BuiltinFunctions.fs)
- Inconsistent naming for logging a warning level message. One method uses the short form 'Warn' while the other uses the full form 'WriteWarning'. Given the presence of 'WriteDim', 'WriteAccent', and 'WriteSuccess', 'WriteWarning' is the consistent pattern for explicit write operations, whereas 'Warn' deviates from this convention.
- Mutually exclusive flags without enforcement or clear precedence. Having both 'Verbose' and 'Quiet' on the same options object can lead to ambiguous state if both are set to true. While common in CLIs, the API surface does not indicate how this conflict is resolved (e.g., Quiet overrides Verbose), which can be confusing for consumers or internal logic.
New (3)
- Ambiguous method naming and potential overlap. 'ExecutePreview' suggests a specific mode of execution, but it is a sibling method to the generic 'Execute'. It is unclear if 'Execute' handles both modes via args or if they are distinct entry points. Given the distinct 'PreviewCommandOptions' type, this likely represents a split in responsibility that is not clearly reflected in the method naming convention (e.g., one should be 'Serve' and the other 'Preview', or both should be variants of a single 'Run' method).
- Duplicated block (5 lines × 2) (src/Zest.Engine/Build/TaxonomyGenerator.fs)
- The concept of logging a warning message is implemented by two different methods with inconsistent naming conventions. Warn uses a short verb form, while WriteWarning uses a descriptive verb-noun phrase. This creates ambiguity for maintainers regarding which method to use for warning logs.
Architecture
- Unchanged — 1 containers · 2 contexts · 0 edges
Written by watchdog.canine.dev from the codebase's own history, inside the signed delivery this page is composed from.
Survey your own repository
zest-ssg/zest was measured the same way every project in this corpus was: the same rubric, at a pinned commit, with the result published in full. Point a surveyor at a repository you know and see whether you agree with it.
About this page
- The score is its most recent published measurement, taken on 3 October 2026 at a pinned commit. It is not a live figure and does not change until the project is measured again.
- Measured at commit b00f16fdd0a2b7e05e3baf20ed5e8533803d923a — the exact code this score is about.
- Scored under rubric-2026.10.1 — the same rubric and the same method as every other entry in this index.
- Measured by watchdog.canine.dev using codehealth-analyzer preprod-4f4226d619ea.