we like simple. A minimal static site generator for blogs built with Python 3 and Jinja2 https://picopaper.com
Find a file
2025-10-13 01:27:39 +02:00
images init 2025-10-09 15:59:47 +02:00
items CHANGE examples for headers + ADD information to features list 2025-10-13 01:27:39 +02:00
output init 2025-10-09 15:59:47 +02:00
static CHANGE example for static file and add new post for documentation 2025-10-09 19:50:00 +02:00
theme/default #11 ADD page creation for SHORT and links in main feed 2025-10-13 01:09:57 +02:00
.gitignore init 2025-10-09 15:59:47 +02:00
config.py init 2025-10-09 15:59:47 +02:00
Dockerfile init 2025-10-09 15:59:47 +02:00
LICENSE init 2025-10-09 15:59:47 +02:00
picopaper.py #9 - ADD automated anchors for headers - toc module for IDs and slugified header with python + ADD dummy content for display 2025-10-13 01:23:29 +02:00
README.md CHANGE examples for headers + ADD information to features list 2025-10-13 01:27:39 +02:00
requirements.txt init 2025-10-09 15:59:47 +02:00

picopaper

A minimal static site generator for blogs built with Python 3 and Jinja2

  • Status: alpha - expect many changes
  • Goals: keeping it simple and easy to understand
  • Demo: picopaper.com

Show cases:


Features

Available:

  • Simple use, easy to understand and modify
  • config file for settings
  • Themes
  • Long- and short form content
  • Pages
  • Static files
  • separate feeds (used for categories, tagging, etc) /feed/{tag}
  • exclusion of feeds from main feed (drafts or system notes)
  • HTML anchors for headers

Ideas:

  • RSS
  • Dark mode
  • logo
  • custom error pages (404, etc)

Not planned:


Usage

Creating a new page or article

Put markdown file into items dir. Important naming convention:

2025-10-03_long_building-a-static-site-generator.md
2025-10-05_short_quick-update_draft.md

Format: YYYY-MM-DD_type_slug[_feed].md

  • 2025-10-03 - date of the article
  • _long_ - type of content: long, short, or page
  • building-a-static-site-generator - slug/path for the URL
  • _draft (optional) - feed tag for categorization

The first # header is the title of the article - no frontmatter needed.

Types of content:

  • long - only title with link to articles will be displayed in feed
  • short - title and all content will be displayed
  • page - won't be displayed in feed at all

Feeds

Posts can be tagged with an optional feed category (e.g., _python, _webdev). Posts with feed tags:

  • Appear on the main page (unless excluded in config)
  • Have their own feed page at /feed/{tag}/

Configuration in config.py:

# Exclude specific feeds from main page (they'll still have /feed/name/ pages)
EXCLUDE_FEEDS_FROM_MAIN = ['draft', 'private']

This is useful for draft posts or topic-specific content you want separated from the main feed.


Installation

  1. Create and activate virtual environment:
python3 -m venv venv
source venv/bin/activate  # On Linux/Mac
# or: venv\Scripts\activate  # On Windows
  1. Install dependencies:
pip install -r requirements.txt
  1. Configure your blog in config.py:
BLOG_TITLE = "My Blog"
BLOG_DESCRIPTION = "A simple blog built with picopaper"
THEME = "default"
  1. Generate the site:
venv/bin/python picopaper.py
  1. Serve locally for testing:
cd output
python3 -m http.server 8000

Visit http://localhost:8000

Docker

Build and run with Docker:

# Build the image
docker build -t picopaper .

# Run the container
docker run --rm -v $(pwd):/app picopaper

For Podman (recommended for rootless):

# Build the image
podman build -t picopaper .

# Run with user namespace mapping
podman run --rm --userns=keep-id -v $(pwd):/app picopaper

The generated site will be available in the output/ directory.


Directory Structure

  • items/ - Markdown content files
  • theme/ - Theme directory containing templates and assets
    • default/ - Default theme
      • templates/ - Jinja2 templates
      • assets/ - CSS and static assets
  • images/ - Image files (copied to output)
  • static/ - Static files copied as-is (GPG keys, .well-known, etc.)
  • output/ - Generated site (do not edit)
  • config.py - Blog configuration

Themes

Themes are organized in the theme/ directory. Each theme has its own subdirectory containing:

  • templates/ - Jinja2 template files
  • assets/ - CSS, JavaScript, and other static assets

To switch themes, change the THEME setting in config.py


Security

For security concerns or reports, please contact via hello a t uphillsecurity d o t com gpg.


License

Apache License

Version 2.0, January 2004

http://www.apache.org/licenses/

  • Commercial use
  • Modification
  • Distribution
  • Patent use
  • Private use
  • Limitations
  • Trademark use
  • Liability
  • Warranty