Getting Started
This guide covers everything you need to know to create, customize, and deploy your first Bliki site.
What is Bliki?
Bliki is a static site generator that combines two content paradigms: blogs and wikis.
Blogs organize content chronologically. Posts have dates, tags, and draft states. Readers browse the timeline or filter by tags.
Wikis organize content topically. Pages are linked together, forming a network of information. Readers follow links between related topics.
Bliki does both. You write Markdown files in a content/ folder. Bliki renders them as a complete static website. Each file can be a blog post, a wiki page, or anything in between.
The pages you visit are statically generated — fast, portable, cacheable. But behind the scenes, JavaScript bridges the gap between static and dynamic: SSE pushes rebuild notifications from the server to the browser, and the browser fetches API data to show your auth status, trigger the inline editor, and update UI. Static files for speed, dynamic features where they matter.
Why Bliki?
- Simple — a single binary, a config file, and Markdown
- Portable — no database, no external services. Your site is just files
- Git-native — content is versioned, editable via the web or from the CLI
- Fast — static HTML served from any web server or CDN
- Flexible — customize layouts, themes, and templates to your needs
Install
go install git.mittelab.org/proj/bliki@latest
Verify the installation:
bliki --help
Create a Site
bliki new site ./myblog
cd myblog
This scaffolds the project structure:
myblog/
bliki.toml ← configuration
content/ ← your Markdown files
theme/ ← templates, CSS, JS
Build & Preview
Build the site:
bliki build
This renders all Markdown files from content/ into public/.
Preview locally:
bliki build --serve
Open http://localhost:3000 in your browser. The server watches for file changes and rebuilds automatically.
To watch and build in one step:
bliki build --watch
You can also skip the --watch flag to serve without auto-rebuild:
bliki build --serve
Add Content
Create a new content file:
bliki new content blog/my-first-post.md
This creates the file at content/blog/my-first-post.md with YAML frontmatter pre-filled:
---
title: "My First Post"
date: 2026-06-02T10:00:00Z
draft: false
layout: "default.tmpl"
---
# My First Post
Hello, world!
Edit the file, save it, and rebuild. Your site updates.
Frontmatter Reference
Every Markdown file in Bliki can include YAML frontmatter between --- delimiters at the top of the file.
Fields
| Field | Type | Required | Description |
|---|---|---|---|
title |
string | Yes | Page title |
date |
time | Yes | Publication date/time (RFC 3339) |
description |
string | No | Page description / summary |
tags |
[]string | No | List of tags for filtering |
draft |
bool | No | If true, page is excluded from the build |
layout |
string | No | Template filename from theme/templates/ |
Example
---
title: "My Post"
date: 2026-01-01T10:00:00Z
description: "A guide to Bliki frontmatter"
tags: [guide, reference]
draft: false
layout: "default.tmpl"
---
Custom Variables
Any YAML key not listed in the standard fields becomes a custom variable. These are accessible in templates via the get function:
---
title: "My Post"
date: 2026-01-01T10:00:00Z
author: "Jane Doe"
category: "tutorial"
featured: true
---
In your template:
{{ if get . "featured" }}<span>★ Featured</span>{{ end }}
Author: {{ get . "author" }}
Category: {{ get . "category" }}
Custom variables preserve their YAML types:
- Strings — rendered as-is
- Booleans — work with
{{ if }}for truthy/falsy checks - Slices — work with
{{ range }}for iteration - Numbers — rendered as strings via
%vformatting
Markdown Body
Content after the closing --- is rendered as HTML using Goldmark (a CommonMark 0.31.2 compliant Markdown parser):
---
title: "Hello"
date: 2026-01-01T00:00:00Z
---
# Hello World
This is **bold** and this is *italic*.
Theme System
Bliki uses Go's html/template for rendering. Templates live in the theme/templates/ directory and are referenced by name in frontmatter or configuration.
Layouts
Each page specifies a layout in frontmatter:
layout: "default.tmpl"
Layouts define the HTML structure around the rendered content. If no layout is specified in frontmatter, Bliki falls back to default_layout in bliki.toml.
Template Structure
theme/
templates/
default.tmpl ← base layout with {{ define "content" }}
blog.tmpl ← overrides "content", adds sidebar
partials/
header.tmpl ← shared nav/header
footer.tmpl ← shared footer
post-meta.tmpl ← date, tags, author
css/
style.css
js/
editor.js
All templates are parsed into a single shared template set, so they can reference each other:
{{ template "partials/header.tmpl" . }}
<main>
{{ content .Current.Content }}
</main>
{{ template "partials/footer.tmpl" . }}
Template Data
Every template receives *site.Site, giving access to:
.Current— the page currently being rendered.Current.Title,.Current.Content,.Current.Date, etc.
.Pages— all published pages (useful for index/listing templates).Config— site configuration frombliki.toml
<title>{{ .Current.Title }}</title>
<nav>
<a href="/">Home</a>
{{ range .Pages }}
<a href="{{ url .FilePath }}">{{ .Title }}</a>
{{ end }}
</nav>
CSS Customization
Override PicoCSS variables in theme/css/style.css:
:root {
--pico-primary: #bd3c13;
--pico-border-radius: 2rem;
}
Everything else is handled by PicoCSS classes — .card, .container, .nav, etc.
Deploy
Bliki generates static HTML — deploy public/ to any web server, CDN, or hosting service. The output directory is self-contained and requires no build step on the hosting side.