Skip to main content

Simple Jinja-based static site generator

Project description

Stapler

A simple static site generator built with Jinja and Markdown.

Installation

Clone the repo:

git clone https://github.com/gijs6/stapler.git
cd stapler

Create a virtual environment (recommended):

python -m venv .venv
source .venv/bin/activate

Install:

pip install -e .

Or with dev dependencies:

pip install -e ".[dev]"

Quick start

  1. Create a stapler.toml in your project root:
[site]
url = "https://yoursite.com"
title = "Your site"
  1. Put your content in a site/ directory (the default). Templates go in site/templates/.

  2. Run:

stapler serve   # local dev server on port 8000
stapler build   # production build

Configuration

Required

[site]
url = "https://yoursite.com"
title = "Your site"

Optional

Site metadata

[site]
description = "About your site"
base_path = "/blog"                # Deploy to example.com/blog instead of the root

Author info

Used in RSS/Atom feeds.

[site.author]
name = "Your name"
email = "you@example.com"

Directories

All paths are relative to where you run stapler.

[directories]
site = "site"                      # Content directory (default: "site")
build = "build"                    # Production output (default: "build")
build_dev = "build-dev"            # Dev server output (default: "build-dev")
templates = "templates"            # Templates folder inside the site directory (default: "templates")
blog = "blog"                      # Blog posts folder inside the site directory (default: "blog")

Default template

The template used for HTML pages that have front matter but no template field.

[templates]
default = "base.html"

Blog

[features.blog]
enabled = true                     # Enable blog functionality (default: false)
template = "blog_post.html"        # Template for individual posts
index_template = "blog_index.html" # Template for the blog index page

Sitemap and feeds

[features]
sitemap = true                     # Generate sitemap.xml (default: true)

[features.feeds]
rss = true                         # Generate rss.xml (default: true)
atom = true                        # Generate atom.xml (default: true)

Feeds are only generated when the blog feature is enabled.

Markdown extensions

[markdown]
extensions = ["meta", "tables", "fenced_code"]  # Python-Markdown extensions

How it works

Pages

Any .html or .md file in your site directory (excluding the templates and blog folders) becomes a page.

Markdown files

Markdown files are always rendered to HTML. If the front matter includes a template field, the result is passed to that template as page.content. Without a template field (or without front matter entirely), the raw HTML is written directly.

---
template: base.html
title: My page
---

# Content

Regular markdown here

HTML files

HTML files with front matter are rendered through a template. The template field in front matter takes precedence; if omitted, the default template from [templates].default is used.

---
title: My page
---
<h1>Content here</h1>

HTML files without front matter are treated as Jinja templates directly:

{% extends "base.html" %}
{% block content %}
<h1>Hello</h1>
{% endblock %}

Front matter is YAML. All fields are available as page.metadata.<field> in your templates.

Static files

Anything that's not a .html or .md file (and not in your templates or blog folder) is copied as-is to the output directory.

Blog

Enable the blog feature in your config, then put .md files in your blog directory.

---
title: My post
date: 2025-01-15
---

Post content here

The date field is optional. If omitted, stapler tries to infer it from the file's git history.

Templates

Templates live in the directory you configured (default: site/templates/).

Available in all templates

  • data: build info
    • data.now: current build time
      • data.now.date.long: date as %B %d, %Y (e.g. April 12, 2026)
      • data.now.date.short: date as %Y-%m-%d (e.g. 2026-04-12)
      • data.now.time: time as %H:%M:%S
      • data.now.iso: datetime as ISO 8601
    • data.last_commit: last git commit info (None if not in a git repo)
      • data.last_commit.hash.short: short 7-character commit hash
      • data.last_commit.hash.long: full commit hash
      • data.last_commit.dt.date.long: date as %B %d, %Y (e.g. April 12, 2026)
      • data.last_commit.dt.date.short: date as %Y-%m-%d (e.g. 2026-04-12)
      • data.last_commit.dt.time: time as %H:%M:%S
      • data.last_commit.dt.iso: datetime as ISO 8601

Regular page templates

  • page: the current page
    • page.active_page: identifier derived from the filename (e.g. about for about.html, home for index.html), useful for highlighting the active nav item
    • page.canonical_path: URL path of the page (e.g. /about)
    • page.content: page content as HTML (only present if the page has front matter)
    • page.metadata.<field>: any front matter field (e.g. page.metadata.title)

Blog post template

  • page: navigation info
    • page.active_page: name of the blog directory (e.g. blog)
    • page.canonical_path: URL path of the post (e.g. /blog/my-post)
  • post: the current blog post
    • post.title: post title (from front matter, or derived from the filename)
    • post.slug: URL slug (filename without .md)
    • post.content: post content as HTML
    • post.date: date as %Y-%m-%d (e.g. 2026-04-12), only set if a date is available
    • post.date_iso: date as ISO 8601, only set if a date is available
  • data: same as above

Blog index template

  • page: navigation info
    • page.active_page: name of the blog directory (e.g. blog)
    • page.canonical_path: URL path of the blog index (e.g. /blog)
  • posts: list of all blog posts sorted newest first; each item has the same fields as post above
  • data: same as above

CLI

# Build with default config (stapler.toml)
stapler build

# Build with custom config
stapler build -c myconfig.toml

# Serve on default port (8000)
stapler serve

# Serve on custom port
stapler serve -p 3000

# Serve with custom config and port
stapler serve -c myconfig.toml -p 3000

# Show version
stapler --version

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

stapler_ssg-0.1.2.tar.gz (12.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

stapler_ssg-0.1.2-py3-none-any.whl (13.9 kB view details)

Uploaded Python 3

File details

Details for the file stapler_ssg-0.1.2.tar.gz.

File metadata

  • Download URL: stapler_ssg-0.1.2.tar.gz
  • Upload date:
  • Size: 12.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for stapler_ssg-0.1.2.tar.gz
Algorithm Hash digest
SHA256 a146d961183284e10e671177ecc652511dfaebaf08d8bb481f14c7358fb73c22
MD5 4171228fb559cde067f8cd33d9563778
BLAKE2b-256 28adcf112042e76de036510457db1960d556ac7d8a7163ffb5fe3fc9f28514b7

See more details on using hashes here.

Provenance

The following attestation bundles were made for stapler_ssg-0.1.2.tar.gz:

Publisher: publish.yml on Gijs6/stapler

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file stapler_ssg-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: stapler_ssg-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 13.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for stapler_ssg-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 3a676e2c99df3dc40472795235b6ef62187232a42ee2ad157fe3d90f8dae8f01
MD5 08e91810b01cf801ee10cbc97ef305e7
BLAKE2b-256 3a84037042d13703223f9c0edf95d1472b36b26437f027eb452b706a3ac3abca

See more details on using hashes here.

Provenance

The following attestation bundles were made for stapler_ssg-0.1.2-py3-none-any.whl:

Publisher: publish.yml on Gijs6/stapler

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page