Templating & Title Rules
Title precedence
The title is chosen by these rules (highest → lowest):
- An explicit title directive inside the source file:
{{title: My Page}}
(this is removed from the rendered content and becomes the page title). - If none present, a title is generated from the filename: hyphens become spaces and each word is capitalized.
Examples:
src/my-first-post.md
→ "My First Post"src/2025-10-06-my-post.md
→ "2025 10 06 My Post" (the date prefix is not stripped) src/my_first_post.md
→ "My_first_post" (underscores kept)
Implementation caveats:
- fssg searches only the primary source file for the title directive. A
title
inside an included file will not set the page title. - The extracted title is taken as-is by the code that finds it (no extra trimming), so keep the directive line clean.
Includes
Simple include from src/includes/
:
Include-blocks with parameters
Pass named parameters and a content block to an include. Inside the include file use {{content}}
to inject the provided block. If you pass markdown="true"
(or markdown=1
), the block is converted to HTML before injection.
{{include-block: alert.html type="warning" alert_title="Attention" markdown="true"}}
This is **Markdown** content inside the block.
{{endinclude}}
If an include-block with markdown="true"
produces a full HTML document (contains a DOCTYPE or an <html>
tag), fssg treats the page as pre-rendered HTML and skips the page-level Markdown pass.
Content Processing & Assets
Markdown support
fssg includes an AWK-based Markdown parser with support for:
- Headings, paragraphs, and raw HTML passthrough
- Blockquotes, fenced code blocks and inline code
- Lists (unordered/ordered), links, images
- Bold/italic/strikethrough, horizontal rules
- Tables (pipe-style)
Static assets
Everything under src/static/
is copied to dist/static/
unchanged. Use {{BASE_URL}}
in templates to build correct deploy-time prefixes — in documentation examples encode the braces as {{BASE_URL}}
so they appear literally in the generated docs.
Style & script hoisting
fssg collects <style>...</style>
blocks and emits them immediately before the closing </head>
, and collects <script>...</script>
blocks and emits them immediately before the closing </body>
. The discovery order is preserved. fssg does not deduplicate identical blocks.
Minification
Minification is enabled by default. The minifier:
- Removes HTML comments and extra whitespace
- Cleans attribute whitespace inside tags
- Preserves
<pre>
blocks verbatim - Strips CSS and JS comments inside hoisted
<style>
and <script>
blocks
Use -m
to disable minification while debugging.
Auto-reload
When using the watcher or serving, fssg writes a timestamp into dist/.reload
and injects a small client script that polls /.reload
. If you host your built site under a subpath, ensure the dev server exposes /.reload
, or override the server with FSSG_SERVER_CMD
.
Server, Watcher & Overrides
Dev server selection
When -s
is used to serve:
- If
FSSG_SERVER_CMD
is set, fssg runs that command verbatim. - If a local
./mongoose
directory exists, fssg looks for a platform-specific executable and runs it with -d dist/ -v 0
. - If
mongoose
is in PATH it will be used. - Otherwise fssg falls back to
python3 -m http.server <port>
or python -m SimpleHTTPServer <port>
.
Watcher
The watcher computes a checksum snapshot of all files in src/
and triggers a rebuild when the snapshot changes. It is portable and doesn't require platform-specific file-watching APIs.
Open browser
Use -o
together with -s
to open the default browser automatically (open
on macOS, xdg-open
on Linux, or start
on Windows).