A no-JS static site generator using Markdown + Jinja2 templates.
- No JavaScript — Pure static HTML output
- Markdown content — Write in MD, get HTML
- Jinja2 templates — Flexible templating
- YAML frontmatter — Metadata in your content files
- User blogs — Support for
~user/subdirectories with per-user blog posts - Date-prefixed posts —
YYYY-MM-DD-slug.mdformat - Config driven — Simple
config.yamlfor site settings - Static assets — Automatic copying of CSS, images, etc.
- Blog feed — Recent posts from all users shown on homepage
- RSS feed — Auto-generated
feed.xmlof all blog posts - Custom 404 —
content/404.mdrenders to a root404.html - Sitemap — Auto-generated
sitemap.xmlfor SEO
pip install -r requirements.txt- Python 3.7+
- jinja2 >= 3.1.0
- markdown >= 3.5.0
- pyyaml >= 6.0
python generator.py [--content CONTENT] [--output OUTPUT] [--config CONFIG] [--static STATIC] [--templates TEMPLATES]content/— Markdown source filesoutput/— Generated HTMLconfig.yaml— Site configurationtemplates/— Jinja2 templatesstatic/— Static assets (CSS, images, etc.)
When using pagegen.py as a submodule in another project, you typically want to override the templates and static directories:
python lib/pagegen/generator.py --config config.yaml --templates templates --static staticcontent/
├── index.md # Homepage
├── about.md # Regular page -> output/pages/about.html
├── ~sigttou/
│ ├── index.md # User index -> output/~sigttou/index.html
│ └── 2025-01-15-hello-world.md # Blog post -> output/~sigttou/hello-world.html
└── ~otheruser/
└── 2025-01-20-another-post.md
Markdown files support YAML frontmatter:
---
title: My Page Title
section: about
date: 2025-01-15
downloads:
- name: PDF
url: /files/doc.pdf
---
# Content here
Write your markdown content below the frontmatter.Four templates are provided:
base.html— Base layouthome.html— Homepagepage.html— Regular pagesblog_index.html— User blog index
Run unit tests:
pip install -r requirements-dev.txt
pytest tests/Run specific test:
pytest tests/test_generator.py::test_parse_frontmatter_with_yamlMIT License — see LICENSE file.