In this tutorial, you will build a fully functional personal blog with Bengal. We will go from an empty folder to a running website with custom content, configuration, and theming.
Note
Who is this for? This guide is for developers who want to see the full end-to-end workflow of Bengal. No prior experience with Bengal is required, but basic familiarity with the terminal is assumed.
Goal
By the end of this tutorial, you will have:
- Initialized a new Bengal project
- Created blog posts with tags and categories
- Configured site metadata and navigation
- Customized the theme (without breaking updates)
- Built the site for production
Prerequisites
- Python 3.14+ installed (3.14t recommended for best performance)
- Bengal installed (
pip install bengal)
Steps
- 1
Initialize Your Project
Set up the foundation for your blog with Bengal's CLI scaffolding.
First, let's create a new site. Open your terminal and run:
1 2 3 4 5
# Create a new Bengal site bengal new site my-blog # Enter your site directory cd my-blogYou will see a structure like this:
1 2 3 4 5 6 7 8 9 10 11
my-blog/ ├── config/ # Configuration files │ ├── _default/ # Default settings │ └── environments/ # Environment-specific config ├── content/ # Your markdown files ├── assets/ # CSS, JS, images │ ├── css/ │ ├── js/ │ └── images/ ├── templates/ # Theme overrides └── .gitignore # Git ignore fileTip
Why this structure? Bengal uses a directory-based configuration system that separates default settings from environment-specific overrides. Your content lives in
content/and custom styles inassets/. - 2
Create Your First Post
Write and configure your first blog post with frontmatter metadata.
Bengal provides a CLI to generate content with the correct frontmatter.
1 2
# Create a new blog post bengal new page "Hello World" --section blogOpen
content/blog/hello-world.mdin your editor. You'll see the Frontmatter (metadata) at the top:1 2 3 4 5 6 7 8
--- title: Hello World date: 2023-10-27T14:30:00 --- # Hello World Your content goes here.Update it to look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
--- title: "My First Bengal Post" date: 2023-10-27 draft: false tags: ["python", "bengal"] category: "tech" --- # Hello, World! This is my first post using **Bengal**, the Pythonic static site generator. ## Why Bengal? * It's fast ⚡️ * It uses Jinja2 templates 🐍 * It's easy to configure ⚙️Warning
Don't forget
draft: false! By default, new pages are drafts. They won't show up in production builds unless you setdraft: false. - 3
Configure Your Site
Personalize your blog with site metadata and navigation menus.
Now, let's give your site an identity. Open
config/_default/site.yamland update the basics.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
title: "My Awesome Blog" description: "Thoughts on code and coffee." baseurl: "https://example.com" author: "Jane Doe" language: "en" # Define navigation menu menu: main: - name: "Home" url: "/" weight: 1 - name: "Blog" url: "/blog/" weight: 2 - name: "About" url: "/about/" weight: 3title,description: Global metadata used by themes (SEO tags, header titles).menu.main: Defines the top navigation bar. Each item is an object in themainmenu list.weight: Controls the sort order (lower numbers appear first).
- 4
Preview Your Site
Launch the dev server and see your blog come to life.
Let's see what we have so far. Start the development server:
bengal serveOpen http://localhost:5173 in your browser.
- Navigate to "Blog" to see your "Hello World" post.
- Notice the site title and menu matches your configuration.
Note
Live Reload Try editing
hello-world.mdwhile the server is running. Save the file, and the browser will automatically refresh with your changes! - 5
Customize the Theme
Make your blog unique with custom styles and template overrides.
You want your blog to stand out. Instead of forking the entire theme, we'll use Theme Inheritance to override just the parts we want to change.
Let's change the header color and add a custom footer.
Create a Custom CSS File
Create
assets/css/custom.css:1 2 3 4 5 6 7 8 9 10 11 12
/* assets/css/custom.css */ :root { --primary-color: #6c5ce7; /* Purple header */ --font-family: 'Helvetica Neue', sans-serif; } .custom-footer { text-align: center; padding: 2rem; background: #f1f2f6; margin-top: 4rem; }Override the Base Template
Create
templates/base.html. We will extend the default theme and inject our changes.1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
<!-- templates/base.html --> {% extends "default::base.html" %} {# Inject our custom CSS into the head #} {% block extra_head %} <link rel="stylesheet" href="{{ asset_url('css/custom.css') }}"> {% endblock %} {# Add a custom footer after the main content #} {% block footer %} <footer class="custom-footer"> <p> © {{ now.year }} {{ site.author }}. Built with <a href="https://bengal.dev">Bengal</a>. </p> </footer> {% endblock %}Check your browser. The header color should change (if the theme uses the
--primary-colorvariable), and your custom footer should appear.How does this work?
Bengal looks for templates in your
templates/folder first.{% extends "default::base.html" %}tells Bengal to load the original theme template first.{% block %}allows you to replace specific sections without copy-pasting the whole file.
- 6
Build for Production
Generate optimized static files ready for deployment.
When you're ready to publish, build the static files.
bengal buildThis creates a
public/directory containing your complete website: HTML, CSS, and optimized images.Review Build Output
1 2 3 4 5 6 7 8 9
public/ ├── index.html ├── blog/ │ ├── index.html │ └── hello-world/ │ └── index.html └── assets/ └── css/ └── custom.a1b2c3d4.css # Fingerprinted for caching
Next Steps
Congratulations! You've built a custom blog. Here is where to go next:
- Deployment Guide: Learn how to host on GitHub Pages or Netlify.
- Theme Customization: Deep dive into template overrides.
- Configuration Reference: Explore all available settings.