Skip to content

zest-ssg/zest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

23 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zest

Zest SSG

Zenith Efficient Static Toolkit

License · Quick Start · Docs


Zest is a hybrid F# + C# static site generator where templates are real code — not strings. Built on the philosophy that your templating language and your host language should be one and the same.

Features

  • Template as Code.zpage.fsx are real F# scripts executed at build time via dotnet fsi. Full F#: list comprehensions, pattern matching, string interpolation, arbitrary computation.
  • .zhtml Lightweight Pages — Pure HTML pages with optional Nunjucks template syntax. No FSI overhead.
  • HTML DSL — Compose HTML declaratively: render [ h1 []; p [] ].
  • Markdown — Standard .md files with frontmatter support.
  • ZCSS — A CSS superset with nesting, F#-style let bindings, math expressions, color functions, and mixins — compiled to standard CSS.
  • ZestNjk Templates — Nunjucks-compatible template engine for layouts: filters, expressions, macros, {% if %}, {% for %}, template inheritance, Zest API integration. Files use .znjk extension.
  • _init.fsx — Optional initialization script (runs before build) to inject dynamic data, load JSON/TOML, read env vars.
  • TOML Config — Zero-config defaults; customize via _config.toml and _data/*.toml. No YAML.
  • Live Reloadzest serve watches for changes and auto-rebuilds.
  • Batch Evaluation — Multiple F# page scripts evaluated in a single FSI process for fast builds.
  • Incremental Builds — File change detection skips unchanged pages and assets.
  • Cross-Platform — Builds for Windows x64, Linux x64/ARM64, macOS ARM64.

Quick Start

# Scaffold a new project
zest init my-site

# Develop with live reload
cd my-site && zest serve --port 8080

# Build for production
zest build

# Preview the built site
zest preview

Example: .zpage.fsx Page

// @title Hello World
// @layout default
// @description My first Zest page

let pageTitle = "Hello from F#"
let items = ["F#"; "Zest"; "SSG"]

render [
    h1 [ text pageTitle ]
    p  [ text "This page is generated by real F# code at build time." ]
    ul [ for i in items -> li [ text i ] ]
]

Example: ZCSS Stylesheet

// F#-style let bindings with math expressions
let primary    = #3b82f6
let space1     = 0.25r
let space4     = space1 * 4     // 1rem
let primary-light = primary |> lighten(45%)

// Two-letter property shorthands
.tag
  c: $primary
  bgc: $primary-light
  py: $space4
  bdr: 9999px

Compiles to:

.tag {
  color: #3b82f6;
  background-color: #adf4ff;
  padding-block: 1rem;
  border-radius: 9999px;
}

Example: _init.fsx

// _init.fsx — runs before every build
addGlobal "api_url" "https://api.example.com"

let team = loadJson "data/team.json"
addGlobal "team" team

let env = loadEnv "ZEST_ENV"
if env = "production" then
    addGlobal "analytics_id" "UA-XXXXX-Y"

Project Structure

my-site/
├── _config.toml            # Site configuration (TOML)
├── _init.zpage.fsx         # Optional init script (runs before build)
├── _data/
│   └── site.toml           # Global data (accessible from scripts/templates)
├── content/
│   ├── index.zpage.fsx     # Home page (F# script template)
│   ├── about.md            # About page (Markdown)
│   └── posts/
│       ├── hello-world.zpage.fsx
│       └── contact.zhtml   # Pure HTML (no FSI overhead)
├── _layouts/
│   ├── default.html        # Layouts (Nunjucks or native replace)
│   └── post.html
├── assets/
│   └── css/
│       └── style.zcss      # ZCSS → auto-compiled to style.css
└── _site/                  # Build output (auto-generated)

Architecture

Project Language Responsibility
Zest.App C# CLI entry point, command routing
Zest.Engine F# Core engine: builds, HTML DSL, ScriptRunner, Markdown, ZCSS compiler, ZestNjk template engine
Zest.Dsl F# Precompiled DSL helpers for FSI script evaluation
Zest.Infra C# Configuration loading, file watching, dev server

Build from Source

git clone https://github.com/YOUR_USER/zest
cd zest
dotnet build Zest.sln

# Publish for your platform
dotnet publish src/Zest.App/Zest.App.csproj -c Release -r win-x64 --self-contained false
# Linux:  -r linux-x64
# macOS:  -r osx-arm64

Documentation

File Types

Extension Purpose Processing
.zpage.fsx F# script templates (F# + Markdown + HTML DSL) Compiled via dotnet fsi
.zhtml Pure HTML pages Copied as-is (optional ZestNjk)
.znjk Zest Nunjucks templates (Nunjucks-compatible syntax with Zest API integration) Rendered via ZestNjkEngine — supports filters, expressions, {% if %}, {% for %}, macros, template inheritance
.zcss ZCSS stylesheets (CSS superset) Compiled to .css
.md Standard Markdown Rendered to HTML
.toml Configuration and data (no YAML) Parsed at build time

Commands

Command Description
zest build Build the site to _site/
zest serve Start dev server with live reload
zest preview Preview the built site
zest init <name> Scaffold a new project
zest clean Clean build output

ZCSS Reference

Feature Syntax
Variables (SCSS) $name: value;
Variables (F#) let name = value
Math let x = 0.25r * 4
Color functions lighten(#hex, %), darken(#hex, %), mix(a, b, %)
Pipe operator value |> fn(args)fn(value, args)
Unit shorthands rrem, p%
Property shorthands pypadding-block, mxmargin-inline, bgcbackground-color
Nesting Indent or brace mode
Mixins @mixin, @include
Loops @each, @for
Conditionals @if, @else
Built-in modules @use "zest:utilities", @use "zest:palette", etc.

Layout Engines

Engine Config Value Features
ZestNjk (default) template_engine = "znjk" Filters, expressions, {% if %}, {% for %}, macros, template inheritance, Zest API filters (pages_by_tag, recent, by_collection, search, where)
Native Replace template_engine = "replace" Simple {{ variable }} substitution

HTML DSL Reference

// Elements
h1 [ text "Title" ]
p  [ text "Paragraph" ]
a  [ href "https://example.com"; text "Link" ]

// Attributes
div [ class' "container"; id "main" ] [ ... ]

// CSS class shortcuts
divC "card" [ p [ text "Content" ] ]   // <div class="card">
spanC "badge" [ text "New" ]           // <span class="badge">

// List comprehensions
ul [ for item in items -> li [ text item ] ]

// Conditionals
if condition then
    p [ text "Yes" ]
else
    p [ text "No" ]

_init.fsx API

Function Purpose
addGlobal key value Inject key-value into global data
loadJson path Parse JSON file
loadToml path Parse TOML file
loadEnv key Read environment variable
console_log msg Debug output to stderr
exec cmd args Run shell command

Design Philosophy

Zest is not a general-purpose static site generator. It is a specific answer to specific constraints.

  1. F# as the Template — The template is the program. .zpage.fsx files are real F# code, not strings.
  2. ZCSS as the Layout Engine — Not a CSS pre-processor, but a layout engine that emits CSS.
  3. TOML as the Contract — No YAML. Ever.
  4. JavaScript as Order — No Node.js, no npm, no bundlers. JavaScript exists only for client-side interactivity.
  5. The Zealous Few — Built for those who love F#, hate YAML, and prefer simple tools.

License

Apache 2.0 — see LICENSE.

About

F#-powered static site generator with template-as-code & ZCSS styles (no YAML, no Node.js)

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors