A high-performance static site generator for Python 3.14+
pip install bengal
bengal new site mysite && cd mysite && bengal serve- Fast — Parallel builds, incremental rebuilds, Zstandard-compressed caching
- Modern — Python 3.14+ with free-threading support, fully typed
- Batteries included — Auto-generated API docs, content validation, site analysis
- Extensible — Pluggable engines for templates, Markdown, and syntax highlighting
| Command | Description |
|---|---|
bengal build |
Production build |
bengal serve |
Dev server with live reload |
bengal validate |
Health checks and validation |
bengal fix |
Auto-fix common issues |
bengal graph report |
Site structure analysis |
Aliases: b (build), s (serve), v (validate)
Interactive Wizard — Guided setup with presets
Run without arguments for a guided experience:
bengal new siteThe wizard prompts for site name, base URL, and presents preset options:
🎯 What kind of site are you building?
📝 Blog - Personal or professional blog
📚 Documentation - Technical docs or guides
💼 Portfolio - Showcase your work
🏢 Business - Company or product site
📄 Resume - Professional resume/CV site
📦 Blank - Empty site, no initial structure
⚙️ Custom - Define your own structure
Each preset creates a complete site with appropriate sections, sample content, and configuration.
Direct Template Selection — Skip prompts with explicit options
Create sites non-interactively with --template:
bengal new site my-docs --template docs
bengal new site my-blog --template blog
bengal new site portfolio --template portfolioAvailable templates:
| Template | Description | Sections Created |
|---|---|---|
default |
Minimal starter | Home page only |
blog |
Personal/professional blog | blog, about |
docs |
Technical documentation | getting-started, guides, reference |
portfolio |
Showcase work | about, projects, blog, contact |
business |
Company or product site | products, services, about, contact |
resume |
Professional CV | Single resume page |
landing |
Single-page landing | Home, privacy, terms |
Add Sections to Existing Sites — Expand without recreating
Add new content sections to an existing Bengal site:
# Add multiple sections
bengal project init --sections docs --sections tutorials
# Add sections with sample content
bengal project init --sections blog --with-content --pages-per-section 5
# Preview without creating files
bengal project init --sections api --dry-runSection type inference:
| Name Pattern | Inferred Type | Behavior |
|---|---|---|
| blog, posts, articles, news | blog |
Date-sorted, post-style |
| docs, documentation, guides, tutorials | doc |
Weight-sorted, doc-style |
| projects, portfolio | section |
Standard section |
| about, contact | section |
Standard section |
Custom Skeleton Manifests — YAML-defined site structures
For complex or repeatable scaffolding, define structures in YAML manifests:
# Preview what would be created
bengal project skeleton apply my-structure.yaml --dry-run
# Apply the skeleton
bengal project skeleton apply my-structure.yaml
# Overwrite existing files
bengal project skeleton apply my-structure.yaml --forceExample manifest (docs-skeleton.yaml):
name: Documentation Site
description: Technical docs with navigation sections
version: "1.0"
cascade:
type: doc # Applied to all pages
structure:
- path: _index.md
props:
title: Documentation
description: Project documentation
weight: 100
content: |
# Documentation
Welcome! Start with our [Quick Start](getting-started/quickstart/).
- path: getting-started/_index.md
props:
title: Getting Started
weight: 10
cascade:
type: doc
pages:
- path: installation.md
props:
title: Installation
weight: 20
content: |
# Installation
```bash
pip install your-package
```
- path: quickstart.md
props:
title: Quick Start
weight: 30
content: |
# Quick Start
Your first project in 5 minutes.
- path: api/_index.md
props:
title: API Reference
weight: 30
content: |
# API Reference
Complete API documentation.Component Model:
path— File or directory pathtype— Component identity (blog, doc, landing)variant— Visual style variantprops— Frontmatter data (title, weight, etc.)content— Markdown body contentpages— Child components (makes this a section)cascade— Values inherited by all descendants
| Feature | Description | Docs |
|---|---|---|
| Directives | Tabs, admonitions, cards, dropdowns, code blocks | Content → |
| Autodoc | Generate API docs from Python, CLI, OpenAPI | Autodoc → |
| Remote Sources | Pull content from GitHub, Notion, REST APIs | Sources → |
| Theming | Dark mode, responsive, syntax highlighting, search | Theming → |
| Validation | Health checks, broken link detection, auto-fix | Building → |
| Performance | Parallel builds, incremental rebuilds, streaming | Large Sites → |
📚 Full documentation: lbliii.github.io/bengal
Single-file — Simple projects
# bengal.toml
[site]
title = "My Site"
baseurl = "https://example.com"Directory-based — Multi-environment projects
config/
├── _default/ # Base configuration
│ ├── site.yaml
│ └── build.yaml
├── environments/ # Environment overrides
│ └── production.yaml
└── profiles/ # Build profiles
└── dev.yaml
bengal build -e production # Production environment
bengal build --profile dev # Development profile📖 Configuration guide: Configuration →
mysite/
├── content/ # Markdown pages
├── templates/ # Custom templates (optional)
├── assets/ # Static files (CSS, JS, images)
├── data/ # YAML/JSON data files
├── config/ # Configuration directory
└── public/ # Build output
Bengal ships with a modern, accessible default theme:
- Dark mode with system preference detection
- Responsive design with mobile navigation
- Syntax highlighting with copy buttons
- Table of contents with scroll spy
- Full-text search (Lunr.js)
Customize templates:
{# templates/page.html #}
{% extends "base.html" %}
{% block content %}
<article class="prose">
<h1>{{ page.title }}</h1>
{{ content | safe }}
</article>
{% endblock %}Bengal follows a "bring your own" pattern — swap engines without changing your content.
Template Engines
| Engine | Description | Install |
|---|---|---|
| Kida (default) | Bengal's native engine. 2-5x faster than Jinja2, free-threading safe, Jinja2-compatible syntax | Built-in |
| Jinja2 | Industry-standard with extensive ecosystem | Built-in |
# config/_default/site.yaml
template_engine: kida # or jinja2Markdown Parsers
| Parser | Description | Best For |
|---|---|---|
| Patitas (default) | Bengal's native parser. Typed AST, O(n) parsing, thread-safe | Python 3.14+, large sites |
| Mistune | Fast, modern parser | General use |
| Python-Markdown | Full-featured, extensive extensions | Complex edge cases |
# config/_default/content.yaml
markdown:
parser: patitas # default, or mistune (legacy), python-markdownSyntax Highlighters
| Backend | Description | Performance |
|---|---|---|
| Rosettes (default) | Lock-free, 55+ languages, O(n) guaranteed | 3.4x faster than Pygments |
# config/_default/theme.yaml
highlighting:
backend: rosettesRosettes is now a standalone package: pip install rosettes
Custom backends can be registered via register_backend().
- Python 3.14+ (uses free-threading and PEP 784 compression)
- Linux, macOS, Windows
Bengal prioritizes correctness and clarity over backwards compatibility.
Each release represents the best solution we know how to deliver. When existing behavior no longer reflects the best design, it changes. Upgrades may require reading release notes and making adjustments.
- Fail loudly — Breaking changes produce clear errors
- User control — You choose when to upgrade; we choose what changes
- No hidden layers — No compatibility shims or deprecated code paths
If you need multi-year stability, pin your version.
git clone https://github.com/lbliii/bengal.git
cd bengal
uv sync --group dev
pytestMIT