Bengal uses a Component Model to organize content. This aligns the backend (how files are stored) with the frontend (how themes render them).
Think of every page as a Component Instance.
| Concept | Terminology | Schema Key | Definition | Example |
|---|---|---|---|---|
| Identity | Type | type |
What is it? Determines Logic (Sorting) & Template Family. |
blog,doc,api |
| Mode | Variant | variant |
How does it look? Determines Visual State (CSS/Hero). |
magazine,wide |
| Data | Props | props |
What data does it have? Content passed to template (Frontmatter). |
author,banner |
1. Identity (Type)
The Type defines the fundamental nature of the content. It controls:
- Sorting Logic: Blog posts sort by date; Docs sort by weight.
- Template Selection:
type: bloglooks forthemes/[theme]/templates/blog/. - URL Structure: Different types may have different URL patterns.
Available Types
| Type | Sorting | Use Case |
|---|---|---|
doc |
By weight | Technical documentation, guides |
blog |
By date (newest first) | Blog posts, news, articles |
page |
By weight | Static pages (about, contact) |
changelog |
By date | Release notes |
api |
By weight | API reference documentation |
Full Examples
---
title: Installation Guide
description: How to install and configure Bengal
weight: 10
type: doc
tags:
- getting-started
- installation
---
# Installation Guide
Follow these steps to install Bengal...
Line 5 is highlighted:type: doctells Bengal this is documentation content.
What happens:
- Page sorted by
weight(10) within its section - Uses templates from
templates/doc/ - Appears in documentation navigation
---
title: Announcing Bengal 1.0
description: We're excited to announce the stable release
date: 2025-06-15
type: blog
tags:
- announcement
- release
category: news
author: Bengal Team
---
# Announcing Bengal 1.0
We're thrilled to share that Bengal 1.0 is now available...
Line 5 is highlighted:type: blogtells Bengal this is a blog post — sorted by date.
What happens:
- Page sorted by
date(newest first) - Uses templates from
templates/blog/ - Appears in blog feed and archives
- Date is required and prominently displayed
---
title: About Us
description: Learn about our team and mission
type: page
---
# About Us
We're a team of developers passionate about documentation...
Line 4 is highlighted:type: pagetells Bengal this is a static page.
What happens:
- Page sorted by weight if specified
- Uses templates from
templates/page/ - Not included in blog feeds or date-based archives
---
title: Bengal 0.2.0
description: Major performance improvements and new features
type: changelog
date: 2025-06-01
weight: 5
---
# Bengal 0.2.0
## New Features
- Incremental builds with 10x faster rebuilds
- New shortcode system...
Lines 4-5 are highlighted:type: changelogwithdatetells Bengal this is a release note.
What happens:
- Page sorted by date within the releases section
- Uses templates from
templates/changelog/ - Formatted for release note presentation
2. Mode (Variant)
The Variant defines the visual presentation. It controls:
- Data Attributes: Sets
data-variant="[name]"on the<body>for CSS targeting. - Partials: Selects specific components (e.g.,
page-hero-magazine.html). - Layout Variations: Different visual treatments for the same content type.
Available Variants
| Variant | Effect | Best For |
|---|---|---|
standard |
Default clean layout | Most content |
editorial |
Enhanced typography, wider margins | Long-form articles |
magazine |
Visual-heavy, featured images | Blog posts with media |
overview |
Landing page style | Section index pages |
wide |
Full-width content area | Code-heavy documentation |
minimal |
Stripped-down, distraction-free | Focus content |
Full Examples
---
title: "The Future of Static Sites"
description: "Why static is making a comeback"
date: 2025-06-01
type: blog
variant: editorial
author: "Jane Smith"
---
# The Future of Static Sites
In an era of increasingly complex web applications, there's a
quiet revolution happening...
Line 6 is highlighted:variant: editorialapplies enhanced typography for long-form reading.
Visual effect:
- Larger body text with better line height
- Pull quotes styled distinctively
- Wider content margins for readability
- Optimized for long-form reading
---
title: "Building Beautiful Documentation"
description: "A visual guide to documentation design"
date: 2025-06-01
type: blog
variant: magazine
banner_image: "/images/hero-docs.jpg"
featured: true
---
# Building Beautiful Documentation

Documentation doesn't have to be boring...
Lines 6-7 are highlighted:variant: magazinewithbanner_imagecreates a visual-first layout.
Visual effect:
- Large hero image at top
- Title overlaid on image or positioned dramatically
- Visual-first layout
- Cards and media prominently featured
---
title: Documentation
description: Complete Bengal documentation
weight: 100
type: doc
variant: overview
icon: book-open
---
# Documentation
Welcome to Bengal documentation! Choose a section to get started.
:::{child-cards}
:::
Line 6 is highlighted:variant: overviewcreates a landing page style with card navigation.
Visual effect:
- Section-style header
- Card grid for child pages
- Navigation-focused layout
- Less text, more visual navigation
---
title: API Reference
description: Complete API documentation
type: doc
variant: wide
---
# API Reference
## `bengal.core.Page`
\`\`\`python
@dataclass
class Page:
"""Represents a single content page."""
source_path: Path
content: str
metadata: dict[str, Any]
rendered_html: str = ""
# ... many more fields
\`\`\`
Line 5 is highlighted:variant: wideprovides full-width content area for code-heavy docs.
Visual effect:
- No sidebar or narrow margins
- Code blocks have maximum width
- Tables can be wider
- Ideal for API reference with large code samples
3. Data (Props)
Props are the data you pass to the component. Any frontmatter field that isn'ttypeorvariantbecomes a prop.
In Markdown Files
Use flat frontmatter (all fields at top level):
---
title: "My Post"
description: "A description for SEO and previews"
author: "Jane Doe"
banner_image: "/images/hero.jpg"
featured: true
custom_field: "Any value you need"
---
Full Examples by Content Type
---
title: "10 Tips for Better Documentation"
description: "Practical advice from years of writing docs"
date: 2025-06-01
type: blog
author: "Jane Doe"
author_image: "/images/authors/jane.jpg"
author_bio: "Technical writer with 10 years of experience"
category: "Writing"
tags:
- documentation
- writing
- best-practices
reading_time: "8 min"
featured: true
banner_image: "/images/posts/docs-tips.jpg"
---
Lines 6-17 are highlighted: all fields aftertypeare props — custom data available in templates.
In templates:
<img src="{{ page.author_image }}" alt="{{ page.author }}">
<span>{{ page.reading_time }} read</span>
{% if page.featured %}
<span class="badge">Featured</span>
{% end %}
---
title: "Configuration Reference"
description: "All configuration options for Bengal"
weight: 30
type: doc
icon: settings
badge: "Updated"
badge_color: "green"
toc_depth: 3
show_edit_link: true
github_path: "docs/reference/configuration.md"
---
Lines 6-12 are highlighted: props customize appearance — icons, badges, navigation.
In templates:
{% if page.icon %}
<i class="icon-{{ page.icon }}"></i>
{% end %}
{% if page.badge %}
<span class="badge badge-{{ page.badge_color }}">
{{ page.badge }}
</span>
{% end %}
---
title: "E-Commerce Platform"
description: "Full-stack e-commerce solution"
date: 2025-03-15
type: page
project_url: "https://example.com"
github_url: "https://github.com/user/project"
technologies:
- React
- Node.js
- PostgreSQL
- Docker
status: "Production"
client: "Acme Corp"
thumbnail: "/images/projects/ecommerce-thumb.jpg"
gallery:
- "/images/projects/ecommerce-1.jpg"
- "/images/projects/ecommerce-2.jpg"
---
Lines 6-19 are highlighted: rich props for portfolio pages — URLs, arrays, any structure you need.
In templates:
<div class="tech-stack">
{% for tech in page.technologies %}
<span class="tech-badge">{{ tech }}</span>
{% end %}
</div>
<a href="{{ page.project_url }}">View Live</a>
---
title: "Building Fast Static Sites"
description: "Conference talk about Bengal SSG"
date: 2025-09-15
type: page
event_name: "PyCon 2025"
event_url: "https://pycon.org/2025"
location: "San Francisco, CA"
slides_url: "/slides/building-fast-static-sites.pdf"
video_url: "https://youtube.com/watch?v=..."
duration: "45 minutes"
audience_level: "Intermediate"
topics:
- Static Site Generation
- Performance
- Python
---
Lines 6-17 are highlighted: props for event/talk pages — links to slides, videos, event details.
In templates:
<p>Presented at <a href="{{ page.event_url }}">{{ page.event_name }}</a></p>
<p>Duration: {{ page.duration }}</p>
{% if page.video_url %}
<a href="{{ page.video_url }}">Watch Recording</a>
{% end %}
Combining Type, Variant, and Props
Here's how all three work together in real examples:
---
title: "Migrating from WordPress to Bengal"
description: "A step-by-step guide to moving your blog"
type: blog
variant: magazine
date: 2025-06-01
author: "Alex Chen"
author_image: "/images/authors/alex.jpg"
banner_image: "/images/posts/wp-migration.jpg"
banner_alt: "WordPress to Bengal migration diagram"
category: "Tutorials"
tags:
- migration
- wordpress
- tutorial
reading_time: "15 min"
difficulty: "Intermediate"
series: "Migration Guides"
series_order: 1
---
Lines 4-5 aretypeandvariant; lines 7-20 are props. All three working together:
type: blog— sorted by date, uses blog templatesvariant: magazine— visual layout with hero image- Props — author info, metadata, series tracking
---
title: "Template Functions Reference"
description: "Complete reference for Bengal template functions"
type: doc
variant: wide
weight: 50
icon: function
badge: "v0.2+"
toc_depth: 4
show_source_links: true
api_version: "0.2.0"
related_pages:
- /docs/reference/template-variables/
- /docs/tutorials/custom-templates/
---
Lines 4-5 aretypeandvariant; lines 7-15 are props. All three working together:
type: doc— sorted by weight, uses doc templatesvariant: wide— full-width for code examples- Props — versioning, related content links
---
title: "Getting Started"
description: "Everything you need to begin with Bengal"
type: doc
variant: overview
weight: 10
icon: rocket
show_child_cards: true
card_columns: 2
featured_page: "/docs/get-started/quickstart/"
section_color: "blue"
---
# Getting Started
Welcome! Choose where to begin based on your experience.
:::{child-cards}
:columns: 2
:::
Lines 4-5 aretypeandvariant; lines 7-12 are props. All three working together:
type: doc— this section contains documentationvariant: overview— landing page with card navigation- Props — card layout, section appearance
Cascading from Sections
Settypeandvariantonce in a section's_index.mdand all child pages inherit them:
# content/docs/_index.md
---
title: Documentation
description: Complete Bengal documentation
cascade:
type: doc
variant: standard
weight: 100
---
Lines 5-8 are highlighted: thecascadeblock setstypeandvariantfor all child pages automatically.
Now child pages don't need to specifytype:
# content/docs/installation.md (inherits type: doc)
---
title: Installation
weight: 10
---
Site Skeletons
Define entire site structures using Skeleton Manifests (bengal project skeleton apply).
name: blog
description: A blog with posts, tags, and categories
version: "1.0"
structure:
- path: index.md
type: blog
variant: magazine
props:
title: My Blog
description: Welcome to my blog
- path: posts/first-post.md
type: blog
props:
title: My First Blog Post
date: "2025-06-01"
tags:
- welcome
- introduction
category: meta
- path: about.md
type: page
variant: standard
props:
title: About
description: Learn more about me
Highlighted lines: Index and posts usetype: blog(lines 7-8, 14); About page usestype: page(lines 24-25) — different template family.
name: docs
description: Technical documentation
version: "1.0"
structure:
- path: _index.md
type: doc
cascade:
type: doc
variant: standard
props:
title: Documentation
weight: 100
- path: getting-started/_index.md
type: doc
variant: overview
props:
title: Getting Started
weight: 10
icon: rocket
Highlighted lines: Root setstype: docwith cascade (lines 7-10); Getting started overridesvariant: overview(line 17) for landing page style.
name: portfolio
description: Portfolio site with projects showcase
version: "1.0"
structure:
- path: index.md
type: page
variant: home
props:
title: Portfolio
description: Welcome to my portfolio
- path: projects/_index.md
props:
title: Projects
- path: projects/project-1.md
type: page
variant: project
props:
title: E-Commerce Platform
featured: true
technologies:
- React
- Node.js
demo_url: https://example.com
Highlighted lines: Home page usesvariant: home(lines 7-8); Projects usevariant: project(lines 18-19) with rich props (lines 21-26).
Quick Reference
| Field | Purpose | Examples |
|---|---|---|
type |
What it is (logic + templates) | doc,blog,page,changelog |
variant |
How it looks (CSS + partials) | standard,editorial,magazine,wide,overview |
props |
Custom data for templates | author,banner_image,featured, anything else |
In Templates
{# Body tag uses data attributes and kind-based classes #}
<body data-type="{{ page.type }}" data-variant="{{ page.variant or '' }}"
class="page-kind-{{ page.kind or 'page' }}">
{# Access props directly #}
<h1>{{ page.title }}</h1>
<p>By {{ page.author }}</p>
{% if page.featured %}
<span class="badge">Featured</span>
{% end %}
CSS Targeting:
/* Target by variant */
body[data-variant="editorial"] { /* editorial styles */ }
body[data-variant="magazine"] { /* magazine styles */ }
/* Target by type */
body[data-type="blog"] { /* blog-specific styles */ }
Legacy Migration
If you are coming from older Bengal versions:
| Old Field | New Field | Notes |
|---|---|---|
layout |
variant |
Automatic normalization |
hero_style |
variant |
Automatic normalization |
metadatadict |
flat props | Move fields to top level |
The system automatically normalizes these for you—no changes required to existing content.