Built-in Components

bserver includes a set of pre-defined YAML files that provide common HTML patterns. These live in the content root directory (www/) and are inherited by all sites through the name resolution system.

Page Structure

html.yaml

The root of every page. Defines the HTML element with lang="en" and includes head and body:

html:
  - head
  - body

^html:
  tag: html
  params:
    lang: en

head.yaml

Sets up the <head> section with meta tags, stylesheets, and styles:

head:
  - title
  - meta
  - headlink
  - style

meta:
  viewport: width=device-width, initial-scale=1
  description: This should be replaced

^meta:
  tag: meta
  params:
    name: '$key'
    content: '$value'

^headlink:
  tag: link
  params: '$*'

The ^meta format iterates over the meta: map, producing one <meta> tag per entry. The ^headlink format uses wildcard params ($*), so each headlink entry's keys become HTML attributes directly.

Override title: and meta: in your site to customize the page title and meta description.

body.yaml

Defines the page body structure:

body:
  - header
  - main
  - footer

This is why your pages define main: — it fills the middle section between the header and footer.

main.yaml

Wraps the main content in a Bootstrap container:

^main:
  tag: div
  params:
    class: container mt-4

main is also a known HTML5 tag, but the ^main format overrides the default <main> rendering with a <div> carrying Bootstrap classes. The base body.yaml also defines a simpler ^main for sites that don't load main.yaml — whichever file is loaded first wins. To customize, define ^main in your own site's YAML.

Bootstrap Integration

bootstrap5.yaml

Loads Bootstrap 5 CSS from the jsDelivr CDN:

bootstrap5:

+headlink:
  - rel: stylesheet
    href: https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css
    integrity: sha384-QWTKZyjpPEjISv5WaRU9OFeRpok6YctnYmDr5pNlyT2bRjXh0JMhjY6hW+ALEwIH
    crossorigin: anonymous

The bootstrap5: key is intentionally empty — it exists only to be referenced so the file gets loaded. The real work is in +headlink:, which merges the Bootstrap CSS link into the head section.

The navbar component references bootstrap5: to ensure it's loaded.

fontawesome.yaml

Similarly loads Font Awesome icons:

fontawesome:

+headlink:
  - rel: stylesheet
    href: https://cdnjs.cloudflare.com/ajax/libs/font-awesome/7.0.1/css/all.min.css

Reference fontawesome in your content to include icon support.

Navigation

navbar.yaml

A complete Bootstrap 5 responsive navbar with collapsible menu. The structure is built from several interconnected format definitions:

navbar:
  bootstrap5:
  navbar-cf:
    navbar-toggler:
      - navbar-toggler-icon
      - brand
    navbar-collapse:
      - navbar-nav:
          - navlinks
      - navform
      - navbar-nav-right:
          - navlinksright

The key formats:

navlinks (script-based)

The ^navlinks format is an embedded-JavaScript format script that generates a <li> per entry, adds an active class to the link matching the current request URI, and renders nested maps as Bootstrap dropdown menus. The relevant excerpt:

^navlinks:
  script: javascript
  code: |
    var page = env.REQUEST_URI || '/';
    var key = record.key || '';
    var value = record.value;
    var isObj = value && typeof value === 'object' && !Array.isArray(value);
    if (isObj) {
      // nested map → Bootstrap dropdown
      print('<li class="nav-item dropdown">');
      // ... emit dropdown items ...
      print('</li>');
    } else {
      var active = (key === page) ? ' active bg-primary bg-opacity-10' : '';
      print('<li class="nav-item"><a class="nav-link' + active + '" href="' + esc(key) + '">' + esc(value) + '</a></li>');
    }

The JavaScript runs inside an embedded interpreter and has access to env.REQUEST_URI (the current URL), print() for output, and a small set of file-system helpers. See Server-Side Scripts for the full helper list.

The navbar's link list is the name navlinks. You have two ways to supply it:

# Option 1: hand-written
navlinks:
  "/": Home
  "/about": About
  "/contact": Contact
# Option 2: auto-discovered (the default, via $navlinks)
# Drop pages into the vhost directory and they appear in the navbar.

The default $navlinks data source scans the vhost directory and emits an entry for every .md file and every .yaml file that defines main:. See Data Sources for how this works.

navlinksright (with dropdown support)

The ^navlinksright format renders right-side navigation items and supports Bootstrap 5 dropdown menus. When a YAML value is a nested map, it renders as a dropdown; simple key-value pairs render as regular links. Dropdown items can themselves contain nested content — including icons:

navlinksright:
  Info:
    https://github.com/stgnet/bserver/:
      - fa-brands-github
      - Repo
    "mailto:scott@stg.net":
      - fa-regular-envelope
      - Author
  "/settings": Settings

The nested map under Info produces a Bootstrap 5 dropdown menu with the toggle label "Info" and the child entries as dropdown items. Each child value is a list that combines a Font Awesome icon (rendered as <i class="...">) and the link text. The flat /settings entry renders as a regular nav link.

Content Elements

link.yaml

A single link with named variable substitution:

^link:
  tag: a
  params:
    href: '$url'
  content: '$contents'

Usage:

- link:
    url: /about
    contents: About Us

Renders: <a href="/about">About Us</a>

links.yaml

Multiple links from a map, using $key/$value iteration:

^links:
  tag: a
  params:
    href: '$key'
  contents: '$value'

Usage:

links:
  /about: About Us
  /contact: Contact

Renders:

<a href="/about">About Us</a>
<a href="/contact">Contact</a>

image.yaml

Image tag with pass-through source:

^image:
  tag: img
  params:
    src: '$*'

Usage: image: photos/hero.jpg renders <img src="photos/hero.jpg">

ulist.yaml

Unordered list that wraps each item in <li>:

^ulist:
  tag: ul
  contents:
    li: '$*'

Usage:

ulist:
  - First item
  - Second item
  - Third item

Renders:

<ul>
  <li>First item</li>
  <li>Second item</li>
  <li>Third item</li>
</ul>

The contents: (plural) is key here — it wraps each list item individually.

ulinks.yaml

Unordered list of links, combining ulist and link patterns:

^ulinks:
  tag: ul
  contents:
    li:
      link: '$*'

Layout Components

row.yaml

Bootstrap grid row:

^row:
  tag: div
  params:
    class: row

col.yaml

Bootstrap grid column:

^col:
  tag: div
  params:
    class: col

Usage:

main:
  container:
    row:
      - col: "Column 1 content"
      - col: "Column 2 content"

card.yaml

Bootstrap card:

^card:
  tag: div
  params:
    class: card

section.yaml

HTML section element:

^section:
  tag: section

muted.yaml

Muted text with small styling:

^muted:
  tag: div
  params:
    class: text-muted small
  content: '$*'

Used in the default footer to display subtle text.

Creating Your Own Components

To create a custom component, add a .yaml file in your site directory or the content root:

# alert.yaml
^alert:
  tag: div
  params:
    class: alert alert-warning
  content: '$*'

Then use it in your pages:

main:
  - alert: "Warning: This is important!"

Components in your site directory override same-named components in parent directories.

Next Steps