24 releases (4 breaking)
Uses new Rust 2024
| new 0.5.3 | Apr 19, 2026 |
|---|---|
| 0.5.2 | Apr 19, 2026 |
| 0.4.2 | Apr 19, 2026 |
| 0.3.7 | Apr 18, 2026 |
| 0.1.2 | Feb 9, 2026 |
#445 in Command line utilities
390KB
8K
SLoC
bamboo ๐
A fast static site generator written in Rust.
Live Demo ยท cargo install bamboo-cli
Bamboo transforms markdown content with frontmatter into static HTML sites. It features syntax highlighting, Tera templating, live reload development, shortcodes, asset optimization, responsive images, and generates RSS/Atom feeds, sitemaps, and search indexes automatically.
Features
| Feature | Description |
|---|---|
| Markdown | Full CommonMark support with tables, footnotes, strikethrough, task lists |
| Frontmatter | TOML (+++) or YAML (---) metadata in content files |
| Syntax Highlighting | Built-in highlighting via syntect with configurable themes |
| Templating | Tera templates with inheritance, includes, filters, and macros |
| Shortcodes | Inline ({{</* name */>}}) and block ({{%/* name */%}}) shortcodes with Tera templates |
| Collections | Organize content beyond posts: projects, recipes, portfolios (supports nesting) |
| Data Files | Load TOML/YAML/JSON from data/ directory into templates |
| Pagination | Automatic pagination for post listings, tag pages, and category pages |
| Tags & Categories | Auto-generated tag and category index/listing pages |
| Table of Contents | Auto-generated heading-based TOC available in templates |
| Reading Time | Word count and estimated reading time for all content |
| Search | Client-side search with auto-generated JSON index and Fuse.js |
| Feeds | Automatic RSS and Atom feed generation |
| Sitemap | Automatic sitemap.xml generation |
| Redirects | redirect_from frontmatter for old URL redirects |
| Asset Pipeline | CSS/JS/HTML minification and content-hash fingerprinting |
| Responsive Images | Automatic resizing and <picture> srcset generation |
| Live Reload | Development server with automatic rebuild on file changes |
| Sass/SCSS | Automatic Sass/SCSS compilation to CSS |
| Math | LaTeX math rendering with KaTeX support ($...$ inline, $$...$$ display) |
| Custom Taxonomies | Define custom taxonomies beyond tags and categories |
| Custom Permalinks | Override output URL via permalink frontmatter field |
| Cross-References | Link between content with {{</* ref "page.md" */>}} shortcodes |
| Incremental Builds | Only rebuild changed content during development |
| Themes | Built-in default theme with light/dark mode, or use custom themes with overrides |
Quick Start
cargo install bamboo-cli
bamboo new my-site
cd my-site
bamboo serve
Open http://localhost:3000 to see your site. Edit files and watch them rebuild instantly.
Template
Use the bamboo-template for a ready-to-deploy starter with GitHub Pages CI included.
CLI Commands
bamboo new <name> # Create a new site in a new directory
bamboo init # Initialize a site in the current directory
bamboo build # Build the site to dist/
bamboo build --drafts # Include draft content
bamboo build --theme ./mytheme # Use a custom theme
bamboo build --output ./public # Custom output directory
bamboo build --base-url <url> # Override base URL
bamboo serve # Dev server with live reload at localhost:3000
bamboo serve --port 8080 # Custom port
bamboo serve --open # Open browser automatically
bamboo serve --drafts # Include drafts in dev server
Project Structure
my-site/
โโโ bamboo.toml # Site configuration
โโโ content/
โ โโโ _index.md # Home page
โ โโโ about.md # Static page โ /about/
โ โโโ docs/ # Nested pages
โ โ โโโ _index.md # โ /docs/
โ โโโ posts/ # Blog posts โ /posts/<slug>/
โ โ โโโ 2024-01-15-hello.md
โ โโโ projects/ # Collection (needs _collection.toml)
โ โโโ _collection.toml
โ โโโ my-project.md
โ โโโ archived/ # Nested subdirectories supported
โ โโโ old-project.md
โโโ data/ # Data files accessible in templates
โ โโโ nav.toml # โ {{ site.data.nav }}
โโโ static/ # Copied as-is to output
โ โโโ images/
โโโ templates/ # Site-level template overrides
โโโ shortcodes/ # Custom shortcode templates
Configuration
bamboo.toml:
title = "My Site"
base_url = "https://example.com"
description = "A site built with Bamboo"
author = "Your Name"
language = "en"
posts_per_page = 10 # Posts per page (0 = all on one page)
syntax_theme = "base16-ocean.dark" # Syntax highlighting theme
math = false # Enable LaTeX math rendering
minify = false # Minify CSS, JS, and HTML output
fingerprint = false # Content-hash asset filenames for cache busting
link_check_ignore = [] # Paths the link validator treats as external (e.g. ["/other-project"])
[taxonomies.tags] # Built-in (auto-configured)
singular = "tag"
[taxonomies.categories] # Built-in (auto-configured)
singular = "category"
[images] # Responsive image generation (optional)
widths = [320, 640, 1024, 1920]
quality = 80
formats = ["webp", "jpg"]
[extra]
github = "https://github.com/username"
All [extra] fields are available in templates as {{ site.config.extra.github }}.
Content
Frontmatter
TOML style:
+++
title = "My Post"
date = "2024-01-15"
tags = ["rust", "web"]
categories = ["tutorials"]
draft = false
weight = 10
template = "custom.html"
excerpt = "Custom excerpt text"
redirect_from = ["/old-url/"]
+++
Your content here...
YAML style:
---
title: My Post
date: 2024-01-15
tags:
- rust
- web
---
Your content here...
Frontmatter Fields
| Field | Type | Applies to | Description |
|---|---|---|---|
title |
string | all | Page/post title (defaults to filename) |
date |
date | posts | Publication date (or parsed from filename) |
draft |
bool | all | Exclude from build unless --drafts flag |
tags |
array | posts | Post tags for tag pages |
categories |
array | posts | Post categories for category pages |
weight |
number | pages, items | Sort order (lower = first) |
template |
string | all | Override default template |
excerpt |
string | posts | Custom excerpt (auto-generated from first paragraph if omitted) |
permalink |
string | all | Override the output URL (e.g. /custom-path/) |
redirect_from |
array | posts, pages | Old URLs that redirect to this content |
math |
bool | all | Enable LaTeX math for this page (when not globally enabled) |
Date from Filename
Posts can embed dates in filenames: 2024-01-15-hello-world.md extracts date 2024-01-15 and slug hello-world.
Nested Pages
Pages can be organized in subdirectories. Use _index.md for directory index pages:
content/docs/_index.mdโ/docs/content/docs/getting-started.mdโ/docs/getting-started/
Shortcodes
Shortcodes embed reusable components in markdown content.
Inline Shortcodes
{{</* youtube id="dQw4w9WgXcQ" */>}}
{{</* figure src="/images/photo.jpg" caption="A photo" */>}}
{{</* gist user="username" id="abc123" */>}}
{{</* pdf src="/resume.pdf" title="Resume" */>}}
{{</* pdf src="/resume.pdf" embed="true" height="800" */>}}
Block Shortcodes
Block shortcodes wrap markdown content:
{{%/* note type="warning" title="Heads up" */%}}
This content is rendered as **markdown** inside the shortcode.
{{%/* /note */%}}
{{%/* details summary="Click to expand" */%}}
Hidden content here.
{{%/* /details */%}}
Built-in Shortcodes
| Shortcode | Type | Parameters |
|---|---|---|
youtube |
inline | id (required), title |
figure |
inline | src (required), alt, caption, width, height, class |
gist |
inline | user (required), id (required), file |
pdf |
inline | src (required), title, embed ("true"/"false", default "false"), height (px, default 600), download ("true"/"false", default "true") |
note |
block | type (info/warning/error), title, body content |
details |
block | summary, open, body content |
Custom Shortcodes
Place Tera HTML templates in templates/shortcodes/. Parameters become template variables:
<!-- templates/shortcodes/alert.html -->
<div class="alert alert-{{ level }}">{{ body }}</div>
{{%/* alert level="danger" */%}}
Something went wrong!
{{%/* /alert */%}}
Shortcode templates also receive a base_url variable matching site.config.base_url. Use it to resolve author-provided local paths so content works correctly when deployed under a subpath:
<!-- templates/shortcodes/download.html -->
{% if src is starting_with("http") %}
{% set resolved = src %}
{% else %}
{% set resolved = base_url ~ src %}
{% endif %}
<a href="{{ resolved | safe }}" download>{{ label | default(value="Download") }}</a>
Templating
Bamboo uses Tera for templating. Templates live in your theme's templates/ directory. Site-level templates in templates/ override theme templates.
Template Context
All templates receive:
| Variable | Description |
|---|---|
site.config |
bamboo.toml contents |
site.config.title |
Site title |
site.config.base_url |
Base URL |
site.config.extra.* |
Custom fields from [extra] |
site.pages |
All pages (for navigation) |
site.data |
Data from data/ directory |
site.collections |
Map of collection name to collection |
Index template (index.html):
| Variable | Description |
|---|---|
posts |
Posts for current page (first posts_per_page) |
home / page |
Home page content (from _index.md) |
current_page |
Current page number |
total_pages |
Total number of pages |
next_page_url |
URL to next page (if exists) |
Post template (post.html):
| Variable | Description |
|---|---|
post.title |
Post title |
post.content |
Rendered HTML (use {{ post.content | safe }}) |
post.date |
Publication date |
post.tags |
Tag list |
post.categories |
Category list |
post.excerpt |
Auto-generated or custom excerpt |
post.slug |
URL slug |
post.url |
Full URL path |
post.word_count |
Word count |
post.reading_time |
Estimated minutes to read |
post.toc |
Table of contents entries |
prev_post |
Previous (older) post |
next_post |
Next (newer) post |
Page template (page.html):
| Variable | Description |
|---|---|
page.title |
Page title |
page.content |
Rendered HTML |
page.slug |
URL slug |
page.url |
Full URL path |
page.word_count |
Word count |
page.reading_time |
Estimated minutes to read |
page.toc |
Table of contents entries |
Tag/Category page templates (tag.html, category.html):
| Variable | Description |
|---|---|
tag_name / category_name |
Display name |
tag_slug / category_slug |
URL slug |
posts |
Posts with this tag/category (paginated) |
current_page, total_pages |
Pagination info |
prev_page_url, next_page_url |
Pagination links |
Collection templates (collection.html, collection_item.html):
| Variable | Description |
|---|---|
collection |
Collection with name and items |
collection_name |
Collection name |
item |
Current item (in item template) |
Custom Filters
| Filter | Description |
|---|---|
slugify |
Convert text to URL slug |
reading_time |
Estimated minutes to read content |
word_count |
Count words in content |
toc |
Render table of contents as HTML (use with | safe) |
Template Example
{% extends "base.html" %}
{% block content %}
<article>
<h1>{{ post.title }}</h1>
<time>{{ post.date | date(format="%B %d, %Y") }}</time>
<span>{{ post.reading_time }} min read</span>
<div class="tags">
{% for tag in post.tags %}
<a href="{{ site.config.base_url }}/tags/{{ tag | slugify }}/">{{ tag }}</a>
{% endfor %}
</div>
{{ post.content | safe }}
</article>
{% endblock %}
Data Files
Place TOML, YAML, or JSON files in data/. They're accessible as site.data.<filename>.
# data/social.toml
[[links]]
name = "GitHub"
url = "https://github.com/username"
[[links]]
name = "Twitter"
url = "https://twitter.com/username"
<!-- In template -->
{% for link in site.data.social.links %}
<a href="{{ link.url }}">{{ link.name }}</a>
{% endfor %}
Nested directories work: data/nav/main.toml โ site.data.nav.main
Themes
Bamboo includes a built-in default theme with light/dark mode toggle. Create custom themes by specifying a theme directory:
bamboo build --theme ./my-theme
Theme Structure
my-theme/
โโโ templates/
โ โโโ base.html
โ โโโ index.html
โ โโโ page.html
โ โโโ post.html
โ โโโ collection.html
โ โโโ collection_item.html
โ โโโ tags.html
โ โโโ tag.html
โ โโโ categories.html
โ โโโ category.html
โ โโโ pagination.html
โ โโโ search.html
โ โโโ 404.html
โ โโโ shortcodes/
โ โ โโโ *.html
โ โโโ partials/
โ โโโ header.html
โ โโโ footer.html
โ โโโ nav.html
โโโ static/
โโโ css/
Theme Overrides
Override specific templates without creating a full theme by placing templates in your site's templates/ directory. These take priority over theme templates.
Examples
The repository includes example sites:
| Example | Description | Command |
|---|---|---|
blog |
Standard blog with posts, pages, collections | just example blog |
book |
Book with chapters, sidebar navigation, prev/next | just example book |
changelog |
Software release notes and changelog | just example changelog |
docs |
Documentation site with sidebar navigation | just example docs |
landing |
Product landing page with pricing | just example landing |
portfolio |
Creative portfolio with project showcase | just example portfolio |
slideshow |
Presentation/slideshow site | just example slideshow |
Portfolio Template
Set template = "portfolio.html" in content/_index.md to use the built-in portfolio layout. Every section is optional, and each one only renders if its data source is present.
Config fields (all under [extra] in bamboo.toml):
| Field | Description |
|---|---|
avatar |
URL or local path to your photo |
tagline |
Short subtitle under the hero name |
linkedin |
LinkedIn profile URL โ shows a LinkedIn button in the hero |
github |
GitHub profile URL โ shows a GitHub button in the hero |
hero_pdf |
Path to a PDF โ shows a hero button that opens a modal viewer with a download link |
hero_pdf_label |
Text for the hero PDF button (defaults to "View PDF"; e.g. set to "Resume" for a resume) |
book_url |
URL โ shows a "Book" button in the hero |
articles_url |
URL โ shows an "Articles" link in the nav |
sponsor_url |
URL โ shows a "Sponsor" button in the nav |
source_url |
URL โ shows a GitHub source icon in the nav |
Local paths (anything not starting with http, https, or //) are automatically prefixed with site.config.base_url.
Data files (under data/):
| File | Shape | Drives |
|---|---|---|
highlights.toml |
[[items]] with title, description, image, link, optional demo_link + demo_label |
Highlights grid |
experience.toml |
[[jobs]] with title, company, period, achievements = [...] |
Experience section with Show-All/Timeline toggle |
crates.toml |
Optional title plus [[items]] with title, description, link, technologies = [...] |
Published Crates section with A-Z/Z-A sort |
projects.toml |
Optional title plus [[items]] with title, description, link, technologies = [...] |
Projects section with A-Z/Z-A sort |
education.toml |
[[degrees]] with degree, institution, period, description |
Education section |
Blog Layout (Author Profile Sidebar)
The default index.html, post.html, and page.html templates render with a sticky two-column author profile sidebar when [extra.author_profile] is set. When the field is absent the layout falls back to single-column (no breakage for existing sites).
[extra.author_profile]
name = "Jane Doe"
avatar = "/bio-photo.jpg" # local path or full URL
bio = "Writing about distributed systems and compression."
[[extra.author_profile.links]]
label = "Email"
url = "mailto:jane@example.com"
icon = "envelope"
[[extra.author_profile.links]]
label = "GitHub"
url = "https://github.com/jane"
icon = "github"
[[extra.author_profile.links]]
label = "RSS"
url = "/rss.xml"
icon = "rss"
Supported icon values: envelope / email / mail, github, linkedin, twitter / x, mastodon, rss, website / globe / link. Unknown or omitted icon falls back to a generic link glyph.
Post Features
post.html composes a set of slot partials. Each slot is opt-out via [extra] toggles (default true):
| Partial | [extra] toggle |
Renders |
|---|---|---|
partials/post_breadcrumbs.html |
post_breadcrumbs |
Home / Category / Post above the title (requires categories frontmatter) |
partials/post_header.html |
always | Title, date, author, read time, tags |
partials/post_hero_image.html |
extra.image in post frontmatter |
Banner image above the title (also used as og:image) |
partials/post_toc.html |
post_toc |
Collapsible table of contents, when the post has >= 2 headings |
partials/post_share.html |
post_share |
Share on X, LinkedIn, copy-link buttons |
partials/post_related.html |
post_related |
Top 3 posts by shared tags/categories, computed at build time |
partials/post_prev_next.html |
always | Previous / next navigation |
partials/post_edit_link.html |
extra.edit_url_base |
"Edit this post on GitHub" link |
Feature image is set per-post via frontmatter:
+++
title = "My Post"
tags = ["rust"]
[extra]
image = "/images/header.jpg"
image_alt = "A descriptive alt text"
image_caption = "Optional caption"
+++
Local paths are prefixed with site.config.base_url automatically. The image also becomes the og:image meta tag for social share cards.
Edit-on-GitHub link is enabled globally by setting extra.edit_url_base to your repo's edit URL. The link resolves to {edit_url_base}/content/posts/{slug}.md unless overridden by extra.source_path in the post frontmatter.
Social Meta Tags
Open Graph and Twitter Card meta tags are emitted on every page automatically. The og:image / twitter:image chooses, in order:
- Per-post
extra.image - Per-page
extra.image - Site-wide
extra.og_image - Author profile avatar (
extra.author_profile.avatar)
Optional: set extra.twitter_handle = "@yoursite" to attribute the card.
Posts-by-Year Archive
Create content/archive.md (or any path) with the archive template:
+++
title = "Archive"
template = "archive.html"
+++
Every post, grouped by year.
The template iterates site.posts and groups entries by year. The author-profile sidebar renders alongside if configured.
Grouped Category / Tag Archives
For a Jekyll-style "all posts grouped by tag on one page" layout, use the grouped templates:
+++
title = "Posts by Category"
template = "categories_grouped.html"
+++
Every post, grouped by category.
tags_grouped.html is the tag equivalent. They complement (not replace) the per-tag and per-category index pages generated automatically under /tags/<name>/ and /categories/<name>/.
Output
Building generates:
dist/
โโโ index.html # Home page
โโโ style.css # Theme stylesheet (built-in theme)
โโโ 404.html # Not found page
โโโ about/index.html # Static pages
โโโ posts/
โ โโโ hello/index.html # Blog posts
โโโ tags/
โ โโโ index.html # Tags listing
โ โโโ rust/index.html # Per-tag post listing
โโโ categories/
โ โโโ index.html # Categories listing
โ โโโ tutorials/index.html # Per-category post listing
โโโ page/
โ โโโ 2/index.html # Pagination pages
โโโ search/
โ โโโ index.html # Search page
โโโ projects/
โ โโโ index.html # Collection index
โ โโโ my-project/index.html # Collection items
โ โโโ archived/
โ โโโ old-project/index.html # Nested collection items
โโโ rss.xml # RSS feed
โโโ atom.xml # Atom feed
โโโ sitemap.xml # Sitemap
โโโ search-index.json # Client-side search index
As a Library
Use bamboo-ssg as a library in your own tools:
[dependencies]
bamboo-ssg = "0.5.3"
use bamboo_ssg::{SiteBuilder, ThemeEngine};
let mut builder = SiteBuilder::new("./my-site")
.base_url("https://example.com")
.include_drafts(false);
let site = builder.build()?;
let theme = ThemeEngine::new("default")?;
theme.render_site(&site, "./dist")?;
License
Dual-licensed under MIT (LICENSE-MIT) or Apache 2.0 (LICENSE-APACHE).
Dependencies
~47โ65MB
~891K SLoC