Build a Blog from Scratch

Create, configure, and customize a personal blog from scratch

5 min read 978 words

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:

  1. Initialized a new Bengal project
  2. Created blog posts with tags and categories
  3. Configured site metadata and navigation
  4. Customized the theme (without breaking updates)
  5. Built the site for production

Prerequisites

  • Python 3.14+ installed (3.14t recommended for best performance)
  • Bengal installed (pip install bengal)

Steps

  1. 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-blog
    

    You 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 file
    

    Tip

    Why this structure? Bengal uses a directory-based configuration system that separates default settings from environment-specific overrides. Your content lives incontent/and custom styles inassets/.

  2. 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 blog
    

    Opencontent/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 forgetdraft: false! By default, new pages are drafts. They won't show up in production builds unless you setdraft: false.

  3. 3

    Configure Your Site

    Personalize your blog with site metadata and navigation menus.

    Now, let's give your site an identity. Openconfig/_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: 3
    
    • title,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. 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 serve
    

    Open 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 editinghello-world.mdwhile the server is running. Save the file, and the browser will automatically refresh with your changes!

  5. 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

    Createassets/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

    Createtemplates/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>
            &copy; {{ 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.

  6. 6

    Build for Production

    Generate optimized static files ready for deployment.

    When you're ready to publish, build the static files.

    bengal build
    

    This creates apublic/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: