1. Introduction

ITNBlog is a powerful static site generator designed specifically for blogging. It generates a fast, SEO-friendly website from Markdown content with rich metadata support. Version 1.0.0 offers a comprehensive feature set while maintaining high performance through parallel processing and intelligent caching.

2. Installation

Requirements

  • Python 3.7 or higher
  • pip (Python package manager)

Installation Options

From source:

git clone https://brew.bsd.cafe/itnblog/itnblog_ssg.git
cd itnblog_ssg
pip install -e .

Dependencies:

ITNBlog relies on the following primary dependencies:

  • markdown: Markdown parsing
  • Jinja2: Templating
  • PyYAML: Configuration parsing
  • slugify: URL slug generation
  • tqdm: Progress bars
  • pytz: Timezone handling

Optional dependencies for enhanced functionality:

  • htmlmin: HTML minification
  • libsass: SCSS compilation
  • livereload: Live preview server

3. Project Structure

A typical ITNBlog project has the following structure:

my-blog/
├── config.yaml          # Site configuration
├── content/             # Content directory
│   ├── posts/           # Blog posts (Markdown)
│   └── pages/           # Static pages (Markdown)
├── static/              # Static files (copied as-is)
├── plugins/             # Custom plugins
├── themes/              # Theme directory
│   └── default/         # Default theme
│       ├── static/      # Theme assets (CSS, JS, images)
│       └── templates/   # Jinja2 templates
└── output/              # Generated site (created on build)

4. Configuration

ITNBlog uses a YAML configuration file (config.yaml) to control site behavior. Below is a complete reference of available options:

# Site Information
site:
  title: "My Blog"                   # Site title
  description: "Site description"    # Site description
  url: "http://localhost:8000"       # Site URL (no trailing slash)
  author: "Author Name"              # Default author name
  email: "email@example.com"         # Contact email
  language: "en"                     # Site language code
  timezone: "UTC"                    # Site timezone

# File Paths
paths:
  content: "content"                 # Content directory
  output: "output"                   # Output directory
  static: "static"                   # Static files directory
  templates: "templates"             # Custom templates directory

# Theme 
theme: "default"                     # Theme name (directory in themes/)

# Pagination
pagination:
  posts_per_page: 10                 # Posts per page on index and archives

# Feature Toggles
features:
  tags: true                         # Enable tag pages
  categories: true                   # Enable category pages
  archives: true                     # Enable archive pages
  search: true                       # Enable search functionality
  rss: true                          # Enable RSS feeds
  rss_full_content: true             # Include full content in feeds (false = summary only)
  sitemap: true                      # Generate sitemap.xml
  opengraph: true                    # Add OpenGraph metadata
  pwa: false                         # Progressive Web App support

# Sidebar Settings
sidebar:
  max_categories: 15                 # Max categories to show in sidebar
  max_tags: 30                       # Max tags to show in sidebar
  sort_by: "count"                   # Sort method: "count" or "name"

# UI Text Options
ui:
  date_format: "%d/%m/%Y %H:%M:%S"   # Date format string
  read_more_text: "Read More"        # Text for read more links
  pagination:
    prev_text: "← Previous"          # Previous page text
    next_text: "Next →"              # Next page text
    page_text: "Page {current} of {total}" # Page indicator text

# Progressive Web App Settings
pwa:
  name: "My Blog"                    # PWA name
  short_name: "Blog"                 # PWA short name
  description: "A blog created with ITNBlog" # PWA description
  start_url: "/"                     # Start URL
  display: "standalone"              # Display mode
  background_color: "#ffffff"        # Background color
  theme_color: "#AB2B28"             # Theme color
  icons:                             # PWA icons
    - src: "/assets/img/icon-192x192.png"
      sizes: "192x192"
      type: "image/png"
    - src: "/assets/img/icon-512x512.png"
      sizes: "512x512"
      type: "image/png"

# Custom Content Injection
custom_content:
  head: ""                           # Custom HTML for 
  body_start: ""                     # Custom HTML at start of 
  body_end: ""                       # Custom HTML before 
  scripts: ""                        # Custom JavaScript

# Production Settings
production:
  minify_html: true                  # Minify HTML in production

# Advanced Settings
advanced:
  gzip: false                        # Generate gzip versions of assets

# Cache Settings
cache:
  use: true                          # Use cache to speed up generation

5. Command Line Interface

ITNBlog provides a comprehensive command-line interface:

Global Options

These options work with any command:

-c, --config PATH      Path to configuration file (default: config.yaml)
-d, --debug            Enable debug mode (verbose logging)
-v, --version          Show version information
--cache                Use cache to speed up generation

Commands

Initialize a New Project

python -m itnblog init [OPTIONS]

Options:

  • -i, --interactive: Interactive setup (prompts for site details)

Generate Site

python -m itnblog generate [OPTIONS]

Options:

  • -p, --production: Enable production optimizations
  • --no-parallel: Disable parallel processing

Start Preview Server

python -m itnblog serve [OPTIONS]

Options:

  • -p, --port NUMBER: Server port (default: 8000)
  • --livereload: Enable live reload

Create a New Post

python -m itnblog new-post "Post Title"

Create a New Page

python -m itnblog new-page "Page Title"

Default Command

Running python -m itnblog without a command is equivalent to python -m itnblog generate.

6. Content Creation

Posts

Posts are Markdown files stored in the content/posts directory. Each file contains frontmatter metadata at the top, delimited by ---, followed by the content.

Creating a Post

You can create a post using the CLI:

python -m itnblog new-post "My Amazing Post"

This creates a file with default frontmatter in content/posts/my-amazing-post.md.

Pages

Pages are similar to posts but are used for static content like About or Contact pages. They're stored in content/pages.

Creating a Page

python -m itnblog new-page "About Me"

This creates a file with default frontmatter in content/pages/about-me.md.

Frontmatter Options

Post Frontmatter

Posts support the following frontmatter options:

---
title: "My Post Title"             # Post title (required)
date: 2023-12-31T12:00:00+00:00    # Publication date (ISO 8601 format)
lastMod: 2024-01-15T10:30:00+00:00 # Last modification date
slug: custom-url-slug              # URL slug (defaults to slugified title)
description: "Post summary"        # Short description (for meta tags, featured snippets)
author: "Author Name"              # Post author (overrides site default)
categories: ["Category1", "Category2"] # Post categories
tags: ["tag1", "tag2", "tag3"]     # Post tags
draft: false                       # Draft status (true = not published)
image: "/path/to/header-image.jpg" # Featured/header image
image_caption: "Image caption text" # Caption for the header image
timezone: "UTC"                    # Timezone for date parsing
---

Page Frontmatter

Pages support the following frontmatter options:

---
title: "Page Title"                # Page title (required)
slug: custom-url-slug              # URL slug (defaults to slugified title)
lastMod: 2024-01-15T10:30:00+00:00 # Last modification date
description: "Page description"    # Short description (for meta tags)
image: "/path/to/header-image.jpg" # Featured/header image
template: "custom-template.html"   # Template to use (defaults to page.html)
---

Dates and Timezones

ITNBlog supports various date formats with timezone information:

  • ISO 8601 with timezone: 2023-12-31T12:00:00+00:00
  • Standard datetime with timezone: 2023-12-31 12:00:00+00:00
  • Just date: 2023-12-31 (uses site default timezone)

7. Theming

ITNBlog uses a theme system based on Jinja2 templates. Themes are stored in the themes directory, with each theme having its own subdirectory.

Theme Structure

themes/
└── theme-name/
    ├── static/              # Theme assets
    │   ├── css/             # Stylesheets (can include .scss files)
    │   ├── js/              # JavaScript files
    │   └── img/             # Images
    └── templates/           # Jinja2 templates

Template Structure

A complete theme should include these templates:

  • base.html: Base template with common structure
  • index.html: Home page with post listings
  • post.html: Individual post page
  • page.html: Static page template
  • tag.html: Individual tag page
  • tags.html: Tags index page
  • category.html: Individual category page
  • categories.html: Categories index page
  • archive.html: Period (year/month) archive page
  • archives.html: Archives index page
  • search.html: Search results page

Template Context

ITNBlog provides a rich context to templates. Common variables available in all templates:

  • site: Site information from config
  • features: Feature toggles from config
  • pages: List of all pages
  • categories: Dictionary of categories with posts
  • filtered_categories: Limited list of categories for sidebar
  • tags: Dictionary of tags with posts
  • filtered_tags: Limited list of tags for sidebar
  • archives: Nested dictionary of posts by year and month
  • config: Complete configuration object
  • ui: UI text configuration
  • generated_at: Generation timestamp

Additional context variables for specific templates:

Index template:

  • posts: List of posts for current page
  • current_page: Current page number
  • total_pages: Total number of pages
  • is_index: True for index page

Post template:

  • post: Current post object
  • prev_post: Previous post or None
  • next_post: Next post or None
  • related_posts: List of related posts

Page template:

  • page: Current page object

Tag template:

  • tag: Current tag name
  • posts: List of posts with this tag

Category template:

  • category: Current category name
  • posts: List of posts in this category

Archive template:

  • year: Current year (for year archives)
  • month: Current month (for month archives)
  • month_name: Month name (for month archives)
  • posts: List of posts in this archive
  • is_year: True for year archives
  • is_month: True for month archives

Jinja2 Filters

ITNBlog provides several custom Jinja2 filters:

  • slugify: Convert a string to a URL-friendly slug
  • format_date: Format a datetime object (e.g., {{ post.date|format_date('%B %d, %Y') }})

Custom Templates

You can override theme templates by creating files with the same name in the project's templates directory. This allows for customization without modifying the theme files directly.

8. Static Files

Static files are stored in the static directory at the project root and in theme-specific static directories. These files are copied to the output directory during site generation.

The following static file structure is recommended:

static/
├── css/      # Custom CSS files
├── js/       # Custom JavaScript files
├── img/      # Images
└── fonts/    # Web fonts

9. Features

Taxonomy System

ITNBlog provides a robust taxonomy system with categories and tags.

Categories

Categories are broad groupings of content. A post can belong to multiple categories. Category pages are generated at /categories/category-slug/.

Tags

Tags are more specific descriptors. A post can have multiple tags. Tag pages are generated at /tags/tag-slug/.

Archives

Archives organize posts chronologically. Archives are accessible at:

  • /archives/: Main archives page
  • /archives/YYYY/: Year archive
  • /archives/YYYY/MM/: Month archive

RSS Feeds

ITNBlog generates RSS feeds for your site:

  • /feed.xml: Main feed with recent posts
  • /index.xml: Alias for the main feed
  • /categories/category-slug/feed.xml: Category-specific feed
  • /categories/category-slug/index.xml: Alias for category feed

Feeds include full content by default but can be configured to include summaries only via the features.rss_full_content setting.

Sitemap

ITNBlog generates a sitemap.xml file with all pages, posts, and taxonomy pages for better SEO.

OpenGraph

ITNBlog adds OpenGraph metadata to pages and posts for better social media sharing.

PWA Support

Progressive Web App support allows your site to work offline and be installable on mobile devices. PWA features include:

  • Web App Manifest
  • Theme color
  • Icons
  • Offline support (when configured)

10. Plugin System

ITNBlog has an extensible plugin system that allows you to add custom functionality.

Creating a Plugin

Plugins are Python classes that inherit from the Plugin base class. To create a plugin:

  1. Create a plugins directory in your project root
  2. Add your plugin file (e.g., my_plugin.py)

Example plugin:

from itnblog.plugins.plugin_manager import Plugin

class MyPlugin(Plugin):
    def __init__(self, name):
        super().__init__(name)
        
    def initialize(self):
        """Called when the plugin is loaded"""
        print("MyPlugin initialized")
        
    def pre_render(self):
        """Called before the rendering process starts"""
        print("About to start rendering")
        
    def post_render(self):
        """Called after the rendering process finishes"""
        print("Rendering complete")

Available Hooks

Plugins can implement these hooks:

  • initialize(): Called when the plugin is loaded
  • cleanup(): Called when the plugin is unloaded
  • pre_render(): Before site rendering begins
  • post_render(): After site rendering completes
  • setup_jinja(env): When Jinja environment is initialized
  • create_context(context): When template context is created
  • pre_render_post(post, context): Before a post is rendered
  • post_render_post(post, html): After a post is rendered
  • pre_render_page(page, context): Before a page is rendered
  • post_render_page(page, html): After a page is rendered
  • pre_render_index(context, page_num): Before index page is rendered
  • post_render_index(html, page_num): After index page is rendered
  • pre_render_tags_index(context): Before tags index is rendered
  • post_render_tags_index(html): After tags index is rendered
  • pre_render_tag(tag, context): Before a tag page is rendered
  • post_render_tag(tag, html): After a tag page is rendered
  • pre_render_categories_index(context): Before categories index is rendered
  • post_render_categories_index(html): After categories index is rendered
  • pre_render_category(category, context): Before a category page is rendered
  • post_render_category(category, html): After a category page is rendered
  • pre_render_archives_index(context): Before archives index is rendered
  • post_render_archives_index(html): After archives index is rendered
  • pre_render_year_archive(year, context): Before a year archive is rendered
  • post_render_year_archive(year, html): After a year archive is rendered
  • pre_render_month_archive(year, month, context): Before a month archive is rendered
  • post_render_month_archive(year, month, html): After a month archive is rendered
  • pre_render_sitemap(root): Before sitemap is generated
  • pre_render_manifest(manifest): Before PWA manifest is generated
  • post_copy_static(): After static files are copied
  • production_optimizations(output_dir): During production optimizations

11. Production Optimizations

When building for production with -p or --production, ITNBlog applies several optimizations:

HTML Minification

Reduces HTML file size by removing whitespace, comments, and other unnecessary content.

SCSS Compilation

SCSS files in the theme's CSS directory are compiled to CSS with compression in production mode.

Gzip Compression

When enabled with advanced.gzip: true, ITNBlog creates pre-compressed .gz versions of text files for servers that support gzip content encoding.

Resource Fingerprinting

ITNBlog tracks content hashes to avoid unnecessary rebuilds of unchanged files.

12. Advanced Usage

Caching

ITNBlog uses a cache system to avoid regenerating unchanged content:

  • Enable with --cache flag or cache.use: true in config
  • Cache is stored in cache.json in the project root
  • Clear cache by running without --cache or by deleting the file

SCSS Compilation

ITNBlog can automatically compile SCSS files to CSS:

  1. Place .scss files in your theme's static/css directory
  2. Files starting with _ are considered partials and won't be compiled directly
  3. In production mode, files are compressed

Custom Content Injection

You can inject custom HTML and JavaScript using the custom_content configuration settings:

custom_content:
  head: |
    
    
  body_start: |
    
    
  body_end: |
    
    
  scripts: |
    document.addEventListener('DOMContentLoaded', function() {
      // Custom JavaScript
    });

13. Troubleshooting

Common Issues

Missing Templates

Error: jinja2.exceptions.TemplateNotFound

Solution: Make sure your theme has all required templates or create custom ones in the templates directory.

Metadata Parsing Issues

Error: Error parsing date or missing metadata

Solution: Check your frontmatter format. Dates should be in ISO 8601 format or one of the supported formats.

Build Performance

Issue: Site generation is slow

Solutions:

  • Enable caching with --cache
  • Use parallel processing (enabled by default)
  • Optimize images and reduce the number of files

Content Not Updating

Issue: Changes not reflected in the output

Solutions:

  • Clear the cache by deleting cache.json
  • Run without the --cache flag

14. API Reference

Content Classes

Post

Represents a blog post and provides these attributes:

  • title: Post title
  • slug: URL slug
  • date: Publication datetime
  • lastMod: Last modification datetime
  • tags: List of tags
  • categories: List of categories
  • image: Featured/header image path
  • image_caption: Caption for the image
  • description: Post description/summary
  • author: Post author
  • draft: Draft status
  • content: Rendered HTML content
  • metadata: Raw metadata dictionary
  • file_path: Source file path

Methods:

  • get_url(site_url): Get the full URL
  • get_output_path(output_dir): Get the output file path
  • get_related_posts(all_posts, num_posts=3): Get related posts based on tags

Page

Represents a static page and provides these attributes:

  • title: Page title
  • slug: URL slug
  • lastMod: Last modification datetime
  • description: Page description
  • image: Featured/header image path
  • template: Template name
  • content: Rendered HTML content
  • metadata: Raw metadata dictionary
  • file_path: Source file path

Methods:

  • get_url(site_url): Get the full URL
  • get_output_path(output_dir): Get the output file path

Site Class

Manages site content and provides:

  • posts: List of all posts
  • pages: List of all pages
  • tags: Dictionary of tags with posts
  • categories: Dictionary of categories with posts
  • archives: Nested dictionary of posts by year and month

Methods:

  • load_content(): Load all content
  • get_filtered_categories(limit=None, sort_by=None): Get limited categories list
  • get_filtered_tags(limit=None, sort_by=None): Get limited tags list
  • get_recent_posts(count=5): Get most recent posts
  • find_post_by_slug(slug): Find a post by slug
  • find_page_by_slug(slug): Find a page by slug