Skip to main content

sssimp 🐍

The Static Site Solution In Modern Python

It's simp with 3 s!

A simple tool to generate a static website while being able to use powerful HTML templates (Jinja2), Markdown files converted to HTML, and other preprocessors.

Why?

I wanted a simple way to generate static websites and I like Jinja2. I had previous experiences working with Jekyll but it seemed like too much work to setup everytime and overkill for the job as it supports many features I don't necessarily use.

One of the main goals with sssimp is being able to generate a usable website without any configuration file or dependency. You only install the sssimp package and run it.

Installing

Requirement: Python 3.8 or later

pip install --user sssimp

How to use

Create a folder called input, it will hold the data to generate the site.

Running sssimp will generate content in the output folder.

Input and output destination can be changed:

sssimp --input ../some-other/input-dir ~/some-other/output-dir

Use python -m sssimp --help for more details.

Generators

  • Files placed in input/content will be directly copied to the output folder

    Example: input/content/favicon.png -> output/favicon.png

  • HTML files with the suffix .html placed in input/content will be parsed as Jinja2 templates, they can use templates defined in input/templates. See the Jinja2 documentation

    Example: input/content/index.html -> output/index.html Starting with content

    {% extends "base.html" %}
    
    ...
    

    Will use the template input/templates/base.html

  • CSS files in input/css will be merged together in a single file output/bundle.css

  • Markdown files with the suffix .md placed in input/content will be parsed to HTML and passed to a template with the same name as their parent folder as the parameter markdown

    Example: ./input/content/post/hello-world.md -> ./output/post/hello-world.html Using the template ./input/templates/post.html Generated with context {'markdown': 'the markdown file converted to HTML'}

    The template name can be overriden using the markdown meta argument "template"

    Example: ./input/content/post/special.md -> ./output/post/special.html Starting with content

    ---
    template: special.html
    ---
    
    ...
    

    Will use the template ./input/templates/special.html instead of post.html

  • Files placed in input/data will exposes their content in templates inside the data variable. They can be in either YAML, JSON, or Markdown. The path is part of their position in the data structure tree.

    Example: ./input/data/categories/tech.yml With content

    description: Nerdy stuff
    color: #121212
    related:
      - computers
      - dev
    

    Will populate the data variable in templates as so:

    {
      "categories": [
        {
          "tech": {
            "description": "Nerdy stuff",
            "color": "#121212",
            "related": ["computers", "dev"]
          }
        }
      ]
    }
    
  • Images placed in input/images must have a size specified in their filename using the syntax name@size.ext. They will be resized and saved to output/images/name@size.ext.

    Size must be in the format [width]x[height]. If both width and height are specified, the converter will ensure both dimensions are under the size, but aspect ratio will be preserved. For example, using size "200x200" on an image of resolution 1200x1920 will produce an image of size 125x200.

    If only one size is specified, the other size will be able to be greater than the specified size. For example, using a size 200x on an image of resolution 1200x1920 will produce an image of size 200x320.

    The following shorthands can be used:

    • thumb: 128x128
    • small: 256x256
    • medium: 512x512
    • large: 1024x1024

    You can specify multiple sizes, for example, a file named input/images/name@thumb,large,700x,1200x1200.png will create the following files in output/images/: name@thumb.png, name@large.png, name@700x.png, and name@1200x1200.png.

    Full path will be honored, so a file at input/images/1/2/3/4/name@thumb.png will be saved to output/images/1/2/3/4/name@thumb.png.

Examples

See the examples directory for per-feature examples, or my personal website https://github.com/Tina-otoge/tina-simp for a real-world example.

Additional Jinja2 filters

  • |a makes any relative path point to the top of the output folder.

    Example: input/content/blog/post/tech/2021/11/some-post.html -> output/blog/post/tech/2021/11/some-post.html With content

    <link rel="stylesheet" href="{{ "style.css"|a }}">
    

    Will be rendered as "../../../../style.css"

    See also the <base> element

  • |markdown transforms Markdown content to HTML using the same process that for Markdown files.

  • |json transforms any object to a formatted JSON.

Additional Jinja2 variables

  • page is a sssimp.generators.html.Page, it contains many information about the current document. Markdown files are an instance of sssimp.generators.markdown.MarkdownPage instead, which inherits from Page

    This variable itself contains many useful variables:

    • page.modified_at and page.created_at (modified_at forcibly set to None if same as created_at)

    • page.href: The path to the file relative to the output folder

    • page.src: A pathlib.Path object of the source file in the input folder

    • page.target A pathlib.Path object of the target file in the output folder

    • page.name: Shortcut for page.target.name, the filename of the outputed file

    • page.parent: Shortcut for page.target.parent, the name of the parent directory in the output folder file

    • page.meta: The Markdown meta variables, prefixing a var with = will interpret it as raw JSON Example

      ---
      some_var: some value
      something_else: 42
      some_tags:= ["tag1", "tag2"]
      ---
      
      My cool blog post
      ...
      

      The meta variable will always contain a template which will resolve to the parent directory name with .html appended if none is set in the meta fields.

      The page.meta variable is None for raw HTML pages, this avoids KeyErrors when trying to filter pages by a specific meta variable.

  • plain_text1: A plain text representation of the Markdown file

  • markdown1: The Markdown content converted to HTML

  • meta1: A shortcut for page.meta

  • title1: Returns page.meta.title if it exists, else the filename with the characters - and _ replaced by whitespaces, the suffix removed and the first letter capitalized.

    Example: input/content/some-cool-page.md's title is "Some cool page"

  • BUNDLE_FILE always evaluates to "bundle.css" for now

  • BUNDLE_TIME modification time of the latest updated file in input/css, very useful to make the browser refresh the file only if any of the CSS files changed.

    Example:

    <link rel="stylesheet" href="{{ BUNDLE_FILE}}?{{ BUNDLE_TIME }}">
    
  • PAGES a list of sssimp.generators.html.Page objects containing every HTML and Markdown files sourced by the site. You can loop over it to generate an index. In conjunction with looking up meta values it can be used to filter by content type.

    Example:

    {% for page in PAGES if page.meta.template == 'post.html' %}
    <a href="{{ page.href }}">{{ page.title }}</a>
    <div class="tags">
      {% for tag in page.meta.tags %}
      <span class="tag">{{ tag }}</span>
      {% endfor %}
    </div>
    Posted on <time>{{ page.created_at }}</time>
    {% endfor %}
    
  1. Markdown only 2 3 4

Release files for sssimp 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sssimp 0.2.0
File Size Uploaded
sssimp-0.2.0.tar.gz 138.1 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for sssimp 0.2.0
File Interpreter ABI Platform
sssimp-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 154.1 kB

Release files / sssimp-0.2.0.tar.gz

Download URL sssimp-0.2.0.tar.gz
Size 138.1 kB
Tags Source
SHA-256 checksum
How to use checksums
fdf9aca87ee5083ba075aa97f8bfa948acf4d907ef6450a62076d83bbfc4be96
BLAKE2b-256 checksum
How to use checksums
dd7aa2ccae6b4567c7d5f0e573df3b0a40cea6d21d3786fb34475dbe4c7122aa
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 8, 2026.

Transparency log

Release files / sssimp-0.2.0-py3-none-any.whl

Download URL sssimp-0.2.0-py3-none-any.whl
Size 16.0 kB
Tags Python 3
SHA-256 checksum
How to use checksums
1972d313806a15a11c1a3d05297ac8f5c42653aa83fc5357cde44a27a60b37cc
BLAKE2b-256 checksum
How to use checksums
a7e4b8ce4202fd80f1c6d6ac56ac586d43295c79fe1a94deee4c57772f19546a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.12

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 8, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.13

2 release files

0.0.10

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.7

2 release files

0.0.6

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page