Zero to Deployed
Build and deploy your first Bengal site in under an hour.
Your first Bengal journey—from zero experience to a live website. Install Bengal, create a blog, and deploy to GitHub Pages with automatic builds.
Tip
Duration: ~45 min | Prerequisite: Python 3.10+, GitHub account
Track Contents
Install Bengal
Install Bengal using pip, uv, or from source
Install Bengal
Requirements
Bengal requires Python 3.14 or later. For best performance, use Python 3.14t (free-threaded build).
Install
uv pip install bengal
Or for a one-time run:
uvx bengal --version
pip install bengal
pipx install bengal
This installs Bengal in an isolated environment while making thebengalcommand available globally.
1 2 3 | |
This installs Bengal in development mode.
Verify Installation
bengal --version
You should see output like:Bengal SSG, version X.X.X
Python Version Setup
pyenv lets you install and switch between multiple Python versions:
1 2 3 4 5 6 7 8 9 10 11 | |
Download Python 3.14 from python.org/downloads.
After installation, verify:python3 --version
Free-Threaded Python (Optional)
For best performance, use the free-threaded build (Python 3.14t):
1 2 3 4 5 6 | |
Why? The free-threaded build enables true parallel processing for 1.8-2x faster builds.
Troubleshooting
Command not found
Ensure Python's bin directory is in your PATH.
If using a virtual environment, activate it:
source .venv/bin/activate
Try reinstalling:
pip uninstall bengal && pip install bengal
Python version errors
Verify your Python version:
1 2 3 | |
Install Python 3.14+ using pyenv or the official installer.
Permission errors
Use the--userflag:
pip install --user bengal
Or use a virtual environment:
python -m venv venv && source venv/bin/activate
Next Steps
- Writer Quickstart — Start creating content
- Themer Quickstart — Customize your site's look
- Tutorials — Guided learning journeys
Writer Quickstart
Create your first site and start writing content
Writer Quickstart
Get from zero to published content in 5 minutes. This guide is for content creators who want to focus on writing.
Prerequisites
Before You Start
- Basic knowledge of Markdown
- Bengal installed
- Terminal/command line access
Create Your Site
Use the interactive wizard:
1 2 | |
Choose a preset that matches your goal (Blog, Documentation, Portfolio, etc.).
Start the Dev Server
bengal serve
Open http://localhost:5173/ in your browser. The dev server automatically rebuilds when you save changes (hot reload).
Create Your First Post
bengal new page my-first-post --section blog
Editcontent/blog/my-first-post.md:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | |
Save the file. Your new post appears automatically!
Customize Your Site
Editconfig/_default/site.yaml:
1 2 3 4 5 | |
Build for Production
bengal build
Your complete site is inpublic/, ready to deploy!
Deploy
Deploy thepublic/directory to any static hosting:
- Netlify: Build command:
bengal build, Publish:public - GitHub Pages: Use the workflow in Automate with GitHub Actions
- Vercel: Build command:
bengal build, Output:public
Frontmatter Reference
Common frontmatter fields:
| Field | Description |
|---|---|
title |
Page title (required) |
date |
Publication date |
tags |
Tags for taxonomy (e.g.,[python, web]) |
weight |
Sort order (lower = first) |
draft |
trueto hide from builds |
description |
SEO description |
Next Steps
- Build a Blog — Full tutorial
- Content Authoring — Markdown features
- Content Organization — Structure your content
- Type System — Content types and templates
- Theming — Customize appearance
Happy writing! 🎉
Build a Blog from Scratch
Create, configure, and customize a personal blog from scratch
Build a Blog in 15 Minutes
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.
Deployment
Deploy your Bengal site to production
Deploy Your Site
Bengal generates static HTML, CSS, and JavaScript files. This means you can host your site anywhere that serves static files (e.g., GitHub Pages, Netlify, Vercel, AWS S3, Nginx).
The Production Build
When you are ready to ship, run the build command:
bengal build --environment production
This command:
- Loads configuration from
config/environments/production.yaml(if it exists) - Minifies assets (if enabled)
- Generates the
public/directory with your complete site
Common Build Flags
| Flag | Description | Use Case |
|---|---|---|
--environment production |
Loads production config overrides. | Always use for shipping. |
--strict |
Fails the build on warnings (e.g., broken links). | Highly Recommended for CI/CD. |
--clean-output |
Cleans thepublic/directory before building. |
Recommended to avoid stale files. |
--verbose |
Shows detailed logs. | Useful for debugging CI failures. |
Example full command for CI:
bengal build --environment production --strict --clean-output
GitHub Pages
Deploy using GitHub Actions. Create.github/workflows/deploy.yml:
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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | |
Netlify
Create anetlify.tomlin your repository root:
1 2 3 4 5 6 | |
Vercel
Configure your project:
- Build Command:
bengal build --environment production - Output Directory:
public - Ensure your
requirements.txtincludesbengal.
Environment Variables
Bengal allows you to inject environment variables into your configuration using{{ env.VAR_NAME }}syntax in your YAML/TOML config files.
config/environments/production.yaml:
1 2 3 | |
Then setAPI_KEYandANALYTICS_IDin your hosting provider's dashboard.
Pre-Deployment Checklist
Before you merge to main or deploy:
- Run
bengal config doctor: Checks for common configuration issues. - Run
bengal build --strictlocally: Ensures no broken links or missing templates. - Check
config/environments/production.yaml: Ensure yourbaseurlis set to your production domain.
1 2 3 | |
Seealso
- Automate with GitHub Actions — Full CI/CD tutorial
- Configuration — Environment-specific settings
- Performance — Optimize build times
Automate with GitHub Actions
Set up automated builds, testing, and deployments using GitHub Actions
Automate with GitHub Actions
Set up continuous integration and deployment (CI/CD) for your Bengal site. Automate builds, run tests, and deploy to production with GitHub Actions.
When to Use This Guide
- You want automated builds on every commit
- You need to run tests before deployment
- You want to deploy to production automatically
- You're setting up preview deployments for pull requests
- You need to validate content and links before publishing
Prerequisites
- Bengal installed
- A Git repository on GitHub
- A hosting provider account (GitHub Pages, Netlify, Vercel, etc.)
- Basic knowledge of YAML
Steps
- 1
Basic Build Workflow
Create
.github/workflows/build.yml: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 29 30 31 32 33
name: Build Site on: push: branches: [main] pull_request: branches: [main] jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.14' - name: Install Bengal run: pip install bengal - name: Build site run: bengal build --environment production --strict - name: Upload artifacts uses: actions/upload-artifact@v4 with: name: site path: public/ retention-days: 1 - 2
Deploy to GitHub Pages
Create
.github/workflows/deploy.yml: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 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
name: Deploy to Production on: push: branches: [main] permissions: contents: read pages: write id-token: write jobs: build: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.14' - name: Install Bengal run: pip install bengal - name: Build site run: bengal build --environment production --strict --clean-output - name: Upload artifact uses: actions/upload-pages-artifact@v4 with: path: './public' deploy: environment: name: github-pages url: ${{ steps.deployment.outputs.page_url }} runs-on: ubuntu-latest needs: build steps: - name: Deploy to GitHub Pages id: deployment uses: actions/deploy-pages@v4 - 3
Preview Deployments
Create
.github/workflows/preview.yml: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 29 30 31 32 33 34
name: Preview Deployment on: pull_request: branches: [main] jobs: preview: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.14' - name: Install Bengal run: pip install bengal - name: Build site run: bengal build --environment preview --build-drafts - name: Comment PR with preview uses: actions/github-script@v7 with: script: | github.rest.issues.createComment({ issue_number: context.issue.number, owner: context.repo.owner, repo: context.repo.repo, body: '✅ Preview build successful! Artifacts available in workflow run.' }) - 4
Add Validation and Testing
Add health checks to your CI pipeline:
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
# .github/workflows/test.yml name: Test and Validate on: [push, pull_request] jobs: validate: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up Python uses: actions/setup-python@v5 with: python-version: '3.14' - name: Install Bengal run: pip install bengal - name: Validate configuration run: bengal config doctor - name: Check for broken links run: bengal health linkcheck - name: Build with strict mode run: bengal build --strict --verbose - 5
Caching for Faster Builds
Add caching to speed up workflows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
- name: Cache pip packages uses: actions/cache@v4 with: path: ~/.cache/pip key: ${{ runner.os }}-pip-${{ hashFiles('requirements.txt') }} restore-keys: | ${{ runner.os }}-pip- - name: Cache Bengal build cache uses: actions/cache@v4 with: path: .bengal-cache key: ${{ runner.os }}-bengal-${{ github.sha }} restore-keys: | ${{ runner.os }}-bengal- - 6
Environment-Specific Builds
Create Environment Configs
config/environments/production.yaml:1 2 3 4 5
site: baseurl: "https://example.com" params: analytics_id: "{{ env.GA_ID }}"config/environments/preview.yaml:1 2 3 4 5
site: baseurl: "https://preview.example.com" params: analytics_id: "" # Disable analytics in previewUse Environment Variables
1 2 3
env: GA_ID: ${{ secrets.GA_ID }} API_KEY: ${{ secrets.API_KEY }}
Alternative Platforms
GitLab CI
Create.gitlab-ci.yml:
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 | |
Netlify
Createnetlify.toml:
1 2 3 4 5 6 | |
Vercel
Createvercel.json:
1 2 3 4 5 | |
Troubleshooting
Build Failures
Issue: Build fails with "Command not found: bengal"
Solutions:
- Ensure Python 3.14+ is installed
- Check
pip install bengalruns before build - Verify Python path in CI environment
Issue: Build fails with strict mode errors
Solutions:
- Fix broken links:
bengal health check - Fix template errors
- Remove
--strictflag temporarily to identify issues
Deployment Issues
Issue: Files not deploying
Solutions:
- Verify output directory:
public/ - Check build artifacts are uploaded
- Verify deployment permissions
Next Steps
- Deployment Options - Explore other hosting platforms
- Configuration - Environment-specific settings
- Validation - Set up health checks