2026-02-28T10:32:32-0500
python>=3.12 static site generator depending on jinja2, markdown with extensions, frontmatter, feedgen, and optionally pygments.
mkdir <project_dir>
cd <project_dir>
uv init
uv add https://beguine.nekoweb.org/src/kamote.tar.gz
uv run kamote init <site_name>
# for development
curl -LO https://beguine.nekoweb.org/src/kamote.tar.gz && tar -xf kamote.tar.gz
cd kamote
uv sync
source .venv/bin/activate
pytest
# add it as project dependency
mkdir ../<project_dir>
cd <project_dir>
uv init
uv add --editable /path/to/kamote
uv run kamote init <site_name>
kamote comes with the following commands:
kamote init <site_name>: creates site.json at project root and the directory structure <site_name>/{assets,content,templates}, with placeholder content/index.md and templates/base.htmlkamote build: renders markdown into HTML and copies assets directory into _buildkamote watch: serves _build to http://localhost:8000 and watches <site_name> for changesif you have preexisting site files, you can copy them into their appropriate <site_name> subdirectories.
this SSG's error handling currently has a lot of holes, so you will quickly find out things like generate_blog() and generate_archive() are very opinionated, especially about YAML fields.
kamote init generates a dummy site.json for you to start with.
these can be accessed from any HTML template with {{ site.<key> }}.
| key | type | description |
|---|---|---|
site_name |
string | name of your site directory |
title |
string | display title for the website |
url |
string | base url where the website is hosted |
author |
object | contains name and email strings |
markdown_ext |
list | a list of extension strings; see python-markdown and pymdown-extensions |
markdown_ext_configs |
object | configuration for any markdown extensions |
extensions |
object | see extensions |
extensions_configs |
object | see extensions |
enable or disable core features. these are all booleans.
generate_blog: generates an atom and/or rss 2.0 feed from content/<blog_dir>generate_archive: generates archive.json, atom, and/or rss from content/<archive_dir>use_gallery: processes image galleries. experimental...build_tree: generates a site mapgenerate_ configurationnote
use_gallery and build_tree require no configuration.
| key | type | description |
|---|---|---|
formats |
list | a list of output formats: ["atom", "rss", "json"]. note that only generate_archive creates json |
uuid |
string | feed UUID |
title |
string | feed title |
description |
string | feed subtitle (atom) or description (rss 2.0) |
dir |
string | subdirectory under content/ |
this is a work in progress i'm dogfooding in two very different contexts. i just hate javascript and how everything is secretly called index.html. it has only been tested on alpine linux 3.23 and debian 13 with python 3.12.