The Component Model

Understanding Bengal's Component Model: Identity, Mode, and Data.

11 min read 2203 words

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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
---
title: Installation Guide
description: How to install and configure Bengal
weight: 10
type: doctags:
  - 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 byweight(10) within its section
  • Uses templates fromtemplates/doc/
  • Appears in documentation navigation
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
---
title: Announcing Bengal 1.0
description: We're excited to announce the stable release
date: 2025-06-15
type: blogtags:
  - 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 bydate(newest first)
  • Uses templates fromtemplates/blog/
  • Appears in blog feed and archives
  • Date is required and prominently displayed
1
2
3
4
5
6
7
8
9
---
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 fromtemplates/page/
  • Not included in blog feeds or date-based archives
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
---
title: Bengal 0.2.0
description: Major performance improvements and new features
type: changelogdate: 2025-06-01weight: 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 fromtemplates/changelog/
  • Formatted for release note presentation

2. Mode (Variant)

The Variant defines the visual presentation. It controls:

  • CSS Classes: Adds.page-variant-[name]to the<body>.
  • 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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
---
title: "The Future of Static Sites"
description: "Why static is making a comeback"
date: 2025-06-01
type: blog
variant: editorialauthor: "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
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
---
title: "Building Beautiful Documentation"
description: "A visual guide to documentation design"
date: 2025-06-01
type: blog
variant: magazinebanner_image: "/images/hero-docs.jpg"featured: true
---

# Building Beautiful Documentation

![Hero Image](/images/hero-docs.jpg)

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
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
---
title: Documentation
description: Complete Bengal documentation
weight: 100
type: doc
variant: overviewicon: 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
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
---
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):

1
2
3
4
5
6
7
8
---
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

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
---
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-practicesreading_time: "8 min"featured: truebanner_image: "/images/posts/docs-tips.jpg"---

Lines 6-17 are highlighted: all fields aftertypeare props — custom data available in templates.

In templates:

1
2
3
4
5
<img src="{{ page.author_image }}" alt="{{ page.author }}">
<span>{{ page.reading_time }} read</span>
{% if page.featured %}
  <span class="badge">Featured</span>
{% endif %}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
---
title: "Configuration Reference"
description: "All configuration options for Bengal"
weight: 30
type: doc
icon: settingsbadge: "Updated"badge_color: "green"toc_depth: 3show_edit_link: truegithub_path: "docs/reference/configuration.md"---

Lines 6-12 are highlighted: props customize appearance — icons, badges, navigation.

In templates:

1
2
3
4
5
6
7
8
{% if page.icon %}
  <i class="icon-{{ page.icon }}"></i>
{% endif %}
{% if page.badge %}
  <span class="badge badge-{{ page.badge_color }}">
    {{ page.badge }}
  </span>
{% endif %}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
---
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  - Dockerstatus: "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:

1
2
3
4
5
6
<div class="tech-stack">
  {% for tech in page.technologies %}
    <span class="tech-badge">{{ tech }}</span>
  {% endfor %}
</div>
<a href="{{ page.project_url }}">View Live</a>
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
---
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:

1
2
3
4
5
<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>
{% endif %}

Combining Type, Variant, and Props

Here's how all three work together in real examples:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
---
title: "Migrating from WordPress to Bengal"
description: "A step-by-step guide to moving your blog"
type: blogvariant: magazinedate: 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  - tutorialreading_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 templates
  • variant: magazine— visual layout with hero image
  • Props — author info, metadata, series tracking
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
---
title: "Template Functions Reference"
description: "Complete reference for Bengal template functions"
type: docvariant: wideweight: 50
icon: functionbadge: "v0.2+"toc_depth: 4show_source_links: trueapi_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 templates
  • variant: wide— full-width for code examples
  • Props — versioning, related content links
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
---
title: "Getting Started"
description: "Everything you need to begin with Bengal"
type: docvariant: overviewweight: 10
icon: rocketshow_child_cards: truecard_columns: 2featured_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 documentation
  • variant: 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:

1
2
3
4
5
6
7
8
9
# content/docs/_index.md
---
title: Documentation
description: Complete Bengal documentation
cascade:  type: doc  variant: standardweight: 100---

Lines 5-8 are highlighted: thecascadeblock setstypeandvariantfor all child pages automatically.

Now child pages don't need to specifytype:

1
2
3
4
5
# content/docs/installation.md (inherits type: doc)
---
title: Installation
weight: 10
---

Site Skeletons

Define entire site structures using Skeleton Manifests (bengal project skeleton apply).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
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.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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

1
2
3
4
5
6
7
8
9
{# Access type and variant #}
<body class="page-type-{{ page.type }} page-variant-{{ page.variant }}">

{# Access props directly #}
<h1>{{ page.title }}</h1>
<p>By {{ page.author }}</p>
{% if page.featured %}
  <span class="badge">Featured</span>
{% endif %}

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.