flea: A Minimal Static Site Generator
2025-07-31
For the following reasons, I decided to write this detailed documentation in a casual style close to a personal memo:
- Essentially, this tool is just a Python script and a CSS file.
- Probably no one else uses this tool except me.
- I don’t know what should be written and what shouldn’t.
- I’m afraid I’ll forget if I don’t write some things down.
Introduction
flea is a tool that reads structured Markdown files with frontmatter metadata and generates a static website.
flea uses no configuration files and no JavaScript. The writing area contains only Markdown; the output area contains only HTML and CSS (plus a flea icon from Icons8).
flea.py
depends on two libraries: mistune
and python-frontmatter
:
pip3 install mistune python-frontmatter
It accepts only one argument: the project directory path:
python3 flea.py /path/to/project
⚠️ Note:
- flea is deliberately designed to be very fragile. Its goal is to maintain only the minimal features I need.
Directory Structure
flea reads a specific directory structure. Here is an example:
my-blog/
└── content/ # required
├── index.md # required – site metadata & homepage
├── travel/ # category
│ ├── index.md # optional – category intro, no metadata
│ ├── a-trip-to-kyoto.md # normal post
│ └── why-i-love-nyc.md
├── recipes/
│ ├── easy-sandwich.md
│ └── quick-pasta.md
└── drafts/ # optional – drafts
└── soy-sauce-noodles.md
- The project directory must contain a folder named
content
; all Markdown files go here.content
must have anindex.md
file, used for site configuration and homepage generation.content
can have adrafts
folder, which is optional and ignored when generating the site.- Other subfolders under content act as categories containing posts.
- Categories may have an
index.md
file (optional), which is combined with the auto-generated post list as the category page. - Other Markdown files under categories are normal posts.
- Categories may have an
- flea creates an
output
folder under the project directory to store the generated website.
⚠️ Note:
- flea ignores any folders or Markdown files starting with a dot.
- Dot-starting folders (e.g.,
content/.other-drafts/
) can also serve as draft folders.
- Dot-starting folders (e.g.,
- flea does not auto-generate site navigation from content categories; navigation must be custom-defined (see next section).
- flea auto-generates a post list per category, sorted by date descending, shown on the category page.
output
is fully cleared before each generation, not incrementally updated.- flea does not copy images or verify image links during generation.
- flea does not generate a 404 page.
Configuration and Metadata
flea uses frontmatter format to store metadata inside Markdown files:
content/index.md
metadata configures the site.content/category/post.md
metadata stores the post’s title and date.
Here is an example content/index.md
:
---
lang: en-US
title: Jane's Blog
author: Jane Doe
nav:
- Home: /
- Travel: /travel
- Recipes: /recipes
footer: Generated by flea
---
Hi! This is my new blog...
All five fields above are optional:
lang
: site language, default en-UStitle
: site title, default Untitledauthor
: site author, default anonymousnav
: navigation bar, no navigation by defaultfooter
: footer content, none by default
Here is an example of a normal post:
---
title: Why I Love NYC
date: 2025-07-30
---
My first time in New York City was during a winter...
These two fields are mandatory; date
must use ISO format YYYY-MM-DD
.
⚠️ Note:
- In
content/index.md
metadata, eachnav
item isany name: any path
.- External links are allowed.
- You can put a single important post directly in the navigation.
- You can create a category with only an
index.md
and add it to nav for a standalone page effect.
content/category/index.md
cannot have metadata.- flea does not handle sorting posts with the same date in the same category.
- flea does not support tags.
- Icon and CSS configurations are hard-coded in the script.
- To change the icon, replace the 48×48 png at
static/favicon.png
in the tool’s root. - To modify CSS, edit or replace
static/style.css
in the tool’s root.
- To change the icon, replace the 48×48 png at
Markdown Syntax
flea supports only the following Markdown syntaxes:
- Headings
- Bold and italic
- Blockquotes
- Lists
- Inline code and code blocks
- Horizontal rules
- Hyperlinks
- Images
flea uses a custom syntax for images:

It renders as:
<img src="https://example.jpg" alt="title" title="title" class="class" />
Depending on the class, flea’s default CSS supports one default style and three special renderings:
- empty: default rendering
fit
: limits image height to prevent overly tall vertical images dominating the pagepano
: lets the image width exceed page width, for wide images with better visual effectpair
: places two images side by side, for comparison or parallel display
⚠️ Note:
- Each image link must be on its own line.
- Except when
pair
images must be written together in the same paragraph.
- Except when
- If
title
is not empty, flea renders the title at the image’s bottom right.- The
title
can contain<br />
for line breaks to separate title and date lines. - A pair of
pair
images can have at most onetitle
, which must be on the second image.
- The
pano
andpair
special rendering only apply when browser width is wide enough.pair
images are centered and scaled proportionally to fill a 2:3 area; overflow will be cropped.- flea reserves an anchor at the top of generated pages, so
[any text](#top)
jumps to the top .