Content definitions are the foundation of bserver. Every piece of content on a page comes from a YAML definition that maps a name to its content.
The simplest form maps a name to content:
main:
- h1: "Page Title"
- p: "Some content here."
When bserver encounters the name main, it looks up this definition and
renders it as HTML.
YAML keys in bserver have three forms, distinguished by their prefix:
footer:
muted: This is the footer text
Plain keys define content. The first definition loaded wins - so your page-level definition overrides inherited ones from parent directories.
^muted:
tag: div
params:
class: text-muted small
content: '$*'
The caret ^ prefix registers a format definition that controls how a name
renders as HTML. See Format Definitions for details.
+headlink:
- rel: stylesheet
href: https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css
The + prefix merges into an existing definition rather than replacing it.
This is how Bootstrap adds its stylesheet to the head section without
overwriting other stylesheets.
A string value can be either literal text or a name reference:
# Name reference - resolved to another definition
body:
- header
- main
- footer
# Literal text - rendered as-is
title: My Website Title
Name references must start with a letter and contain only letters, digits, hyphens, and underscores. Anything else is treated as literal text:
| String | Type | Why |
|---|---|---|
header |
Name reference | Letters only |
nav-links |
Name reference | Letters, hyphens |
col2 |
Name reference | Letters, digits |
/about |
Literal text | Starts with / |
http://example.com |
Literal text | Contains : and / |
#333 |
Literal text | Starts with # |
logo.png |
Literal text | Contains . |
hello world |
Literal text | Contains space |
Lists define ordered content. Each item is rendered in sequence:
body:
- header
- main
- footer
List items can be strings (name references or literal text), maps (inline tags), or nested lists.
When a map key matches an HTML tag or has a format definition, the value becomes the content inside that tag:
main:
- h1: "Welcome"
- p: "Hello world"
- div: "A div with text"
Renders as:
<h1>Welcome</h1>
<p>Hello world</p>
<div>A div with text</div>
Maps can also nest:
main:
- div:
h1: "Title"
p: "Paragraph inside the div"
The + prefix is powerful for composing definitions from multiple files.
For map definitions, new keys are added and existing keys are overridden:
# In base file:
meta:
viewport: width=device-width, initial-scale=1
# In page file with +meta:
+meta:
description: My page description
Result: meta has both viewport and description.
For list definitions, items are appended:
# In base file:
headlink:
- rel: stylesheet
href: base.css
# In component file with +headlink:
+headlink:
- rel: stylesheet
href: bootstrap.min.css
Result: headlink has both stylesheet entries.
For plain content definitions (without +), the first definition loaded takes
precedence:
# In your page's index.yaml:
title: My Page Title
# In a parent directory's title.yaml:
title: Default Title
Since bserver loads page-local files first, your page's title definition
wins. This is how page-specific content overrides site-wide defaults.
Each YAML file can contain multiple definitions. The filename determines when it's loaded:
footer.yaml is loaded when the name footer is referencedfooter: content definition plus related format
definitions (like ^muted:)For example, navbar.yaml contains both the navbar: content structure and
all the ^navbar-* format definitions needed to render it.
A key with no value (or explicit null) produces an empty element:
main:
- hr: # Self-closing <hr> tag
- br: # Self-closing <br> tag
- div: # Empty <div></div>
Void elements (like hr, br, img, meta, link) are automatically
self-closing and never produce a closing tag.
^ prefix system