Content Definitions
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.
Plain Definitions
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.
Three Types of Definitions
YAML keys in bserver have three forms, distinguished by their prefix:
Content Definitions (plain keys)
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.
Format Definitions (^ prefix)
^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.
Merge Definitions (+ prefix)
+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.
String Values
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
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.
Maps (Inline Tags)
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"
Merge Behavior
The + prefix is powerful for composing definitions from multiple files.
Map Merge
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.
List Merge
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.
First Definition Wins
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.
File-Based Definitions
Each YAML file can contain multiple definitions. The filename determines when it's loaded:
footer.yamlis loaded when the namefooteris referenced- It can contain the
footer:content definition plus related format definitions (like^muted:) - All definitions in the file are processed when it loads
For example, navbar.yaml contains both the navbar: content structure and
all the ^navbar-* format definitions needed to render it.
Null/Empty Values
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.
Next Steps
- Format Definitions - Learn the
^prefix system - Built-in Components - See what's already defined