https://github.com/jdeanwallace/jinjabread
A Python-based static site generator using Jinja templates.
https://github.com/jdeanwallace/jinjabread
jinja jinja2 jinjabread markdown python static-site-generator
Last synced: 4 months ago
JSON representation
A Python-based static site generator using Jinja templates.
- Host: GitHub
- URL: https://github.com/jdeanwallace/jinjabread
- Owner: jdeanwallace
- License: mit
- Created: 2024-03-18T11:39:27.000Z (over 2 years ago)
- Default Branch: master
- Last Pushed: 2025-07-15T20:53:53.000Z (12 months ago)
- Last Synced: 2025-09-23T17:44:06.995Z (10 months ago)
- Topics: jinja, jinja2, jinjabread, markdown, python, static-site-generator
- Language: Python
- Homepage: http://jinjabread.com
- Size: 60.5 KB
- Stars: 95
- Watchers: 2
- Forks: 1
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Jinjabread
[](https://circleci.com/gh/jdeanwallace/jinjabread)
[](https://github.com/jdeanwallace/jinjabread/releases)
[](https://pypi.org/project/jinjabread/)
[](LICENSE)
A Python-based static site generator using Jinja templates.
Inspired by [`staticjinja`](https://github.com/staticjinja/staticjinja), [`jekyll`](https://github.com/jekyll/jekyll), and [`hugo`](https://github.com/gohugoio/hugo).
## Install
```bash
pip install jinjabread
```
## Usage
### Create new site project
```bash
python -m jinjabread new mysite
```
### Build site
```bash
python -m jinjabread build mysite
```
### Preview site locally
```bash
python -m jinjabread serve mysite
# Visit http://127.0.0.1:8000 in your browser.
```
## Features
- Write pages in Markdown, HTML, or text.
- Use Jinja2 templating language in Markdown, HTML, or text.
- Supports YAML metadata in Markdown pages.
- Keep static media alongside static pages.
- Index pages (i.e., `index.html`) can list all other pages in the same directory.
- Preview your static site locally with a built-in web server.
- Prettify all generated HTML (because why not?)
## File structure
### Important files and directories
| Name | Description | Example path |
| --- | --- | --- |
| Project directory | The project root | `mysite` |
| Content directory | Contains site content where each file becomes a site page | `mysite/content` |
| Layouts directory | Contains page layouts that gets used by the site content | `mysite/layouts` |
| Static directory | Contains static media that gets copied to the output directory | `mysite/static` |
| Output directory | The complete generated site, ready to be hosted | `mysite/public` |
| Config file | Custom site configurations in TOML format | `mysite/jinjabread.toml` |
### Example: Site project structure
```
mysite/
├── content
│ ├── about.html
│ ├── index.html
│ └── posts
│ ├── index.html
│ ├── my-journey
│ │ ├── index.html
│ │ └── profile-photo.jpg
│ └── my-story.html
├── jinjabread.toml
├── layouts
│ └── markdown.html
├── public
│ ├── about.html
│ ├── index.html
│ ├── posts
│ │ ├── index.html
│ │ ├── my-journey
│ │ │ ├── index.html
│ │ │ └── profile-photo.jpg
│ │ └── my-story.html
│ └── static
│ └── style.css
└── static
└── style.css
```
### Example: File to URL translation
| File path | URL path |
| --- |----------|
| `public/index.html` | `/` |
| `public/about.html` | `/about` |
| `public/posts/index.html` | `/posts/` |
| `public/posts/my-story.html` | `/posts/my-story` |
| `public/posts/my-journey/index.html` | `/posts/my-journey/` |
| `public/posts/my-journey/profile-photo.jpg` | `/posts/my-journey/profile-photo.jpg` |
| `public/static/style.css` | `/static/style.css` |
## Site config
### Default config
```toml
content_dir = "content"
layouts_dir = "layouts"
static_dir = "static"
output_dir = "public"
prettify_html = true
[context]
[[pages]]
type = "jinjabread.MarkdownPage"
glob_pattern = "**/*.md"
layout_name = "markdown.html"
[[pages]]
type = "jinjabread.Page"
glob_pattern = "**/*"
```
### Custom config
#### Change output directory
```toml
# jinjabread.toml
output_dir = "dist"
```
#### Add global Jinja context variables
```toml
# jinjabread.toml
[context]
site_name = "My site"
url_origin = "https://mysite.com"
```
#### Change Markdown layout file
```toml
# jinjabread.toml
[[pages]]
type = "jinjabread.MarkdownPage"
glob_pattern = "**/*.md"
layout_name = "post.html"
[[pages]]
type = "jinjabread.Page"
glob_pattern = "**/*"
```
#### Add page-specific Jinja context variables
```toml
# jinjabread.toml
[[pages]]
type = "jinjabread.MarkdownPage"
glob_pattern = "**/*.md"
layout_name = "markdown.html"
[[pages]]
type = "jinjabread.Page"
glob_pattern = "**/*.txt"
[pages.context]
foo = "bar"
[[pages]]
type = "jinjabread.Page"
glob_pattern = "**/*"
```
## Pages types
| Page type | Keyword arguments |
| --- | --- |
| [`jinjabread.Page`](jinjabread/base.py#L71) | - `glob_pattern` |
| [`jinjabread.MarkdownPage`](jinjabread/base.py#L136) | - `glob_pattern`
- `layout_name` |
### Markdown pages
Markdown content supports [full YAML metadata](https://github.com/sivakov512/python-markdown-full-yaml-metadata).
For example, given the following content and layout:
```yaml
---
# content/my-blog-post.md
title: My blog post
author: John Smith
description: A very nice story.
keywords:
- thrilling
- must-read
---
It was a cold stormy night...
```
```html
{{ title }}
{{ description }}
Written by {{ author }}
{{ content }}
```
Results in the following output:
```html
My blog post
A very nice story.
Written by John Smith
It was a cold stormy night...
```
## Context variables
### Default variables
All pages have these context variables:
| Name | Description | Example value |
| --- | --- | --- |
| `url_path` | The URL path of the current page | `/` |
| `file_path` | The file path of the current page, relative to the output directory | `index.html` |
### Variable precedence
Page-specific context variables override global site context variables.
For example:
```toml
# jinjabread.toml
[context]
fee = "fie"
foe = "fum"
[[pages]]
type = "jinjabread.Page"
glob_pattern = "**/*.txt"
[pages.context]
foe = "foo"
[[pages]]
type = "jinjabread.Page"
glob_pattern = "**/*.html"
[pages.context]
foe = "bar"
```
* `.txt` pages will have the following extra context variables:
```toml
fee = "fie"
foe = "foo"
```
* `.html` pages have the following extra context variables:
```toml
fee = "fie"
foe = "bar"
```
### Index pages
All index pages (i.e., `index.*`) has an extra context variable named `pages` which is list of dictionaries of context variables from its sibling files.
For example, given the following file structure:
```
mysite/content/posts/
├── index.html
├── post1.md
└── post2.md
```
You can list all the pages in the `posts` directory using:
```html
{% for page in pages %}
{{ page.url_path.split('/') | last | title }}
{% endfor %}
```
Resulting in:
```html
## Contributing
### Setup
```bash
python -m venv venv && \
. venv/bin/activate && \
pip install pip pip-tools --upgrade && \
pip-sync requirements.txt
```
### Test
```bash
python -m unittest discover .
```
### Build
```bash
python -m build
```
### Release
```bash
export TWINE_USERNAME='__token__'
export TWINE_PASSWORD='secret-token'
python -m twine upload dist/*
```