Reference
Front matter keys, TT variables, configuration keys, and file locations.
Front matter keys
All keys are optional unless noted.
title-
Page title. Used in the
<title>tag and page header. Required for most pages. subtitle- Short description shown below the title.
ttl-
Cache TTL in seconds. The page regenerates after this interval rather
than on
.mdfile edit. Example:ttl: 300 register-
List of registry files this page should appear in. Values match
template filenames under
lazysite/templates/registries/without the.ttextension. Common values:sitemap.xml,llms.txt,feed.rss,feed.atom. tt_page_var-
Page-scoped Template Toolkit variables. Supports
url:,scan:,${ENV}, and literal values. Page variables override site variables of the same name. raw-
Set
raw: trueto output the converted content body without the view template wrapper. TT variables still resolve. Useful for content fragments, AJAX partials, or API-style endpoints. api-
Set
api: trueto serve the rendered content as an API endpoint. Default content type:application/json; charset=utf-8. Combine withtt_page_var(especiallyscan:) andquery_paramsfor dynamic JSON. content_type-
Custom
Content-typeheader. Used withraw: trueorapi: true. Example:content_type: text/html; charset=utf-8 date-
Publication date in
YYYY-MM-DDformat. Used in feed entries. Falls back to file mtime if not set. layout-
Named layout for this page, overriding the site-wide
layout:key. The processor resolves it tolazysite/layouts/NAME/layout.tt. May also be a remote URL (see remote layouts). auth-
Authentication requirement. Values:
required,optional,none(default). See Authentication. auth_groups- List of group names. User must be authenticated AND in at least one listed group to view the page.
payment- Payment requirement for the x402 payment flow. See Payment.
query_params-
List of accepted URL query parameter names. Declared parameters are
available as
[% query.param_name %]. Requests with matching parameters bypass the cache. tags- Tags for page scan results. YAML list, comma-separated, or single value.
search-
Set
search: trueorsearch: falseto control whether the page appears in the search index. Defaults to the site-widesearch_defaultsetting. form-
Enables form processing for the page and names the form. Name must be
alphanumeric with hyphens and underscores. A matching
lazysite/forms/NAME.confmust exist. See Forms.
See Authoring for full usage details and examples.
lazysite.conf keys
Site-wide configuration in public_html/lazysite/lazysite.conf. One
key-value pair per line.
Value types
- Literal string
-
key: value- used as-is. - Environment variable
-
key: ${ENV_VAR}- interpolated from the CGI environment. Multiple vars and mixed text supported:${REQUEST_SCHEME}://${SERVER_NAME} - Remote URL
-
key: url:https://...- fetched, trimmed, and cached with the page. - Directory scan
-
key: scan:/path/*.md sort=field dir- returns array of page objects.
Recognised keys
site_name- Site name. Used in the layout template title and header.
site_url-
Site URL. Typically
${REQUEST_SCHEME}://${SERVER_NAME}so the same config works on staging and production. layout-
Active layout name. The processor resolves it to
lazysite/layouts/NAME/layout.tt. May also be a remote URL. theme-
Active theme name. The processor resolves it to
lazysite/layouts/LAYOUT/themes/THEME/theme.json. The theme'slayouts[]array must contain the active layout or the theme is skipped with a warning. layouts_repo- GitHub OWNER/REPO path for the manager's "Install from Releases" theme browser. Default unset hides the browser.
nav_file-
Navigation file path, docroot-relative. Default:
lazysite/nav.conf. search_default-
Site-wide default for the
search:front matter key. Set totrue(default) orfalse. Pages without an explicitsearch:key inherit this value. manager-
enabledordisabled. Controls the built-in manager UI at/manager. manager_path-
URL path for the manager. Default:
/manager. manager_groups- Comma-separated group names. Only users in one of these groups can access the manager.
log_level-
One of
ERROR,WARN,INFO,DEBUG. Default:INFO. log_format-
text(default) orjson. plugins- List of plugin script paths to pre-enable without going through the manager.
auth_default-
Site-wide default for the
auth:front matter key. Set torequired,optional, ornone(default). auth_header_user,auth_header_name,auth_header_email,auth_header_groups-
Override the HTTP headers used by an external auth proxy. Defaults:
X-Remote-User,X-Remote-Name,X-Remote-Email,X-Remote-Groups.
All other keys are available as TT variables in page content and the layout template.
See Configuration for full details.
TT variables
Automatic variables (always available in layout.tt)
page_title-
From front matter
title:. page_subtitle-
From front matter
subtitle:. page_modified- Human-readable file mtime, e.g. "3 April 2026".
page_modified_iso- ISO 8601 file mtime, e.g. "2026-04-03".
content- Rendered page body HTML. Available in the layout template.
request_uri-
Current request path, e.g.
/about. Set fromREDIRECT_URLorREQUEST_URI. page_source-
Docroot-relative path of the source
.mdfile, e.g./about.md. Useful for admin bar and edit links. nav-
Navigation array from
nav.conf. Each item haslabel,url,children(array oflabel/urlhashes). query,params-
Query parameter hash. Only populated when
query_params:is declared in front matter.paramsis an alias forquery. year-
Current year as a 4-digit string, e.g.
2026. search_enabled-
1if asearch-results.md(or.url) page exists in the docroot,0otherwise. site_name,site_url-
From
lazysite.conf. layout_name- Active layout name, as sanitised by the processor.
theme-
Parsed
theme.json(hash) when a compatible theme is active. Access config values as[% theme.config.GROUP.KEY %]. Empty hash when no theme is active. theme_name- Active theme name. Unset when no compatible theme is active.
theme_assets-
URL prefix for active-theme assets.
/lazysite-assets/LAYOUT/THEME/for local themes (nested per D013);/lazysite-assets/CACHE_KEY/for remote layouts (flat). Unset when no theme is active. theme_css-
Pre-rendered
<style>:root { ... }block of CSS custom properties derived fromtheme.config. Empty string when no theme is active. Naming convention:--theme-GROUP-KEY.
Auth variables
authenticated-
1if the request carries valid auth headers,0otherwise. auth_user- Username, or empty string if not authenticated.
auth_name- Display name from the proxy header (or built-in auth). May be empty.
auth_email- Email address from the proxy header. May be empty.
auth_groups- Array of group names the user belongs to.
editor-
1if the authenticated user is inmanager_groups(i.e. has manager access),0otherwise. Use in layouts to gate admin UI.
Variable precedence
Site variables (from lazysite.conf) are loaded first. Page variables
(from tt_page_var) override site variables of the same name. Automatic
variables (page_title, page_subtitle, content, etc.) override both.
Environment variable allowlist
Only these CGI variables may be interpolated via ${VAR} in
lazysite.conf:
SERVER_NAME- server hostnameSERVER_PORT- server portREQUEST_SCHEME-httporhttpsHTTPS-onif HTTPSREQUEST_URI- full request URIREDIRECT_URL- requested page path (e.g./about)DOCUMENT_ROOT- filesystem docroot pathSERVER_ADMIN- server admin email
HTTP_HOST is intentionally excluded - it is request-supplied and
untrusted. Use SERVER_NAME for host-based URL construction.
Security
Path traversal
sanitise_uri rejects null bytes, .. path segments, and suspicious
characters before constructing filesystem paths. After construction, each
path is verified with realpath to confirm it resolves within $DOCROOT.
Symlinks pointing outside the docroot are rejected.
The same check is applied inside write_html before any file is written,
guarding against symlink-based overwrite attacks on the cache output path.
Template Toolkit injection
All values extracted from YAML front matter - including title, subtitle,
and tt_page_var entries - have TT directive markers ([% and %]) stripped
before entering the template context. register list items are stripped at
parse time. This prevents authored content from injecting TT directives into
the rendering pipeline.
Fenced div class names
The class name following ::: is validated against /\A[\w][\w-]*\z/ before
use. Blocks with class names containing characters outside word characters and
hyphens are rejected - the content renders without a wrapper div and a warning
is written to the error log.
oEmbed JSON parsing
oEmbed provider responses are parsed with JSON::PP (Perl core module) rather
than regex extraction. The html field from the parsed response is injected
into the page. Provider responses are trusted as-is - restrict %OEMBED_PROVIDERS
in lazysite-processor.pl to known hosts if untrusted providers are a concern in
your deployment.
File locations
DOCROOT/
lazysite/
lazysite.conf <- site configuration
nav.conf <- navigation
layouts/
NAME/layout.tt <- layout template
NAME/layout.json <- layout metadata (optional)
NAME/themes/THEME/
theme.json <- theme manifest
main.css <- theme-scoped CSS
assets/ <- theme assets (images, fonts)
manager/
layout.tt <- manager UI chrome (internal)
assets/manager.css <- manager CSS source
templates/
registries/ <- registry templates (.tt)
auth/
users <- user credentials
groups <- group memberships
forms/
FORMNAME.conf <- per-form target config
handlers.conf <- named dispatch handlers
smtp.conf <- SMTP connection settings
cache/
layouts/ <- remote-layout cache
tt/ <- TT compile cache
logs/ <- log files
lazysite-assets/
LAYOUT/THEME/ <- web-served theme assets (nested)
manager/
assets/
manager.css <- manager CSS (mirrored from source)
cm/ <- CodeMirror assets
404.md
index.md
[content pages]
Scripts (repo root, copied to site by the installer):
lazysite-processor.pl <- main processor
lazysite-auth.pl <- built-in auth
plugins/form-handler.pl <- form dispatch
plugins/form-smtp.pl <- SMTP helper
lazysite-manager-api.pl <- manager JSON API
plugins/payment-demo.pl <- payment demo helper
Source files:
*.md <- Markdown pages
*.url <- remote page pointers
*.html <- generated cache (auto-created)
Registry output (generated at DOCROOT):
sitemap.xml <- generated from sitemap.xml.tt
llms.txt <- generated from llms.txt.tt
feed.rss <- generated from feed.rss.tt
feed.atom <- generated from feed.atom.tt