Every Statik project is driven by a config.json file located at the project root. This document describes each configuration option available.
Example config.json
{
"siteName": "My Website",
"description": "A website built with Statik",
"baseUrl": "https://mysite.com",
"author": "Your Name",
"theme": {
"templates": "templates",
"assets": "static",
"output": "build"
},
"paths": {
"posts": "posts",
"pages": "content"
},
"devServer": {
"port": 3000
},
"staticDatasource": {
"enabled": true,
"outputDir": "datasource",
"collectAttribute": "data-collect",
"imagesFileName": "images.json",
"configFile": "datasource-config.json"
},
"rss": {
"enabled": true,
"fileName": "feed.xml",
"title": "My Website RSS Feed",
"description": "Latest posts from my website",
"language": "en-us",
"maxItems": 20,
"includeFullContent": true
}
}
Configuration Options
core
description required
Default site description applied to templates, meta tags, and RSS feeds when individual pages don't provide their own.
, metadata={title=description, type=string, required=true, default=null, category=core, order=3}, source=DatasourceItemSource(type=api, id=api-description, path=/api/description/, title=description))siteName required
Display name used across templates and metadata. This appears in page titles, RSS feeds, and anywhere {{siteName}} is referenced.
author required
Author attribution used in templates and metadata. Can be referenced via {{author}} in Handlebars templates.
baseUrl required
Fully qualified site URL (e.g., https://mysite.com). Statik uses this for canonical links, RSS feed URLs, and absolute path generation.
theme
theme.output
Build directory that receives generated HTML, copied assets, and datasource JSON files.
, metadata={title=theme.output, type=string, required=false, default=build, category=theme, order=3}, source=DatasourceItemSource(type=api, id=api-theme.output, path=/api/theme.output/, title=theme.output))theme.assets
Directory for static files (CSS, JS, images) copied verbatim to the build output.
, metadata={title=theme.assets, type=string, required=false, default=static, category=theme, order=2}, source=DatasourceItemSource(type=api, id=api-theme.assets, path=/api/theme.assets/, title=theme.assets))theme.templates
Directory containing Handlebars templates and layouts. See Layouts documentation for template structure and organization.
, metadata={title=theme.templates, type=string, required=false, default=templates, category=theme, order=1, link=/layouts}, source=DatasourceItemSource(type=api, id=api-theme.templates, path=/api/theme.templates/, title=theme.templates))paths
paths.pages
Location of standalone pages. Pages support navigation ordering via nav_order frontmatter field.
paths.posts
Location of blog post content. Supports Markdown (.md), HTML (.html), and Handlebars (.hbs) files with YAML frontmatter.
devServer
devServer.port
Port for the development server launched with --watch mode. Change if port 3000 conflicts with another service.
staticDatasource
staticDatasource.collectAttribute
HTML attribute marking custom collectable elements in content. See Static Datasources for collection patterns.
, metadata={title=staticDatasource.collectAttribute, type=string, required=false, default=data-collect, category=staticDatasource, order=3, link=/static-datasources}, source=DatasourceItemSource(type=api, id=api-staticDatasource.collectAttribute, path=/api/staticDatasource.collectAttribute/, title=staticDatasource.collectAttribute))staticDatasource.configFile
Location of dataset definitions for entity folders and metadata-tagged content. See Static Datasources for configuration schema.
, metadata={title=staticDatasource.configFile, type=string, required=false, default=datasource-config.json, category=staticDatasource, order=5, link=/static-datasources}, source=DatasourceItemSource(type=api, id=api-staticDatasource.configFile, path=/api/staticDatasource.configFile/, title=staticDatasource.configFile))staticDatasource.outputDir
Folder inside the build directory where datasource JSON files are written. See Static Datasources.
, metadata={title=staticDatasource.outputDir, type=string, required=false, default=datasource, category=staticDatasource, order=2, link=/static-datasources}, source=DatasourceItemSource(type=api, id=api-staticDatasource.outputDir, path=/api/staticDatasource.outputDir/, title=staticDatasource.outputDir))staticDatasource.enabled
Enable or disable static datasource generation. See Static Datasources for usage patterns.
, metadata={title=staticDatasource.enabled, type=boolean, required=false, default=true, category=staticDatasource, order=1, link=/static-datasources}, source=DatasourceItemSource(type=api, id=api-staticDatasource.enabled, path=/api/staticDatasource.enabled/, title=staticDatasource.enabled))staticDatasource.imagesFileName
Filename for the auto-generated images datasource. See Static Datasources for image collection details.
, metadata={title=staticDatasource.imagesFileName, type=string, required=false, default=images.json, category=staticDatasource, order=4, link=/static-datasources}, source=DatasourceItemSource(type=api, id=api-staticDatasource.imagesFileName, path=/api/staticDatasource.imagesFileName/, title=staticDatasource.imagesFileName))rss
rss.includeFullContent
When true, embeds full HTML post content in feed items. Set to false for excerpt-only feeds.
rss.enabled
Toggle RSS feed generation. When enabled, creates an RSS 2.0 feed of recent posts.
, metadata={title=rss.enabled, type=boolean, required=false, default=true, category=rss, order=1}, source=DatasourceItemSource(type=api, id=api-rss.enabled, path=/api/rss.enabled/, title=rss.enabled))rss.maxItems
Maximum number of recent posts to include in the RSS feed.
, metadata={title=rss.maxItems, type=number, required=false, default=20, category=rss, order=6}, source=DatasourceItemSource(type=api, id=api-rss.maxItems, path=/api/rss.maxItems/, title=rss.maxItems))rss.description
Feed description. Defaults to site description if not provided.
rss.fileName
Output filename for the RSS feed, placed in the build root directory.
, metadata={title=rss.fileName, type=string, required=false, default=feed.xml, category=rss, order=2}, source=DatasourceItemSource(type=api, id=api-rss.fileName, path=/api/rss.fileName/, title=rss.fileName))rss.title
Feed title. Defaults to siteName if not provided.
rss.language
RSS language code (e.g., en-us, fr-fr). Used in the feed's <language> element.
Debug Helper
Debug Helper
The {{debug}} helper is a powerful debugging tool that displays all available template variables and their nested properties in your Handlebars templates.
Usage
Simply add {{debug}} anywhere in your template:
<h1>{{title}}</h1>
{{debug}}
<p>{{content}}</p>
Output
The debug helper will render a styled <pre> block showing:
- All available variables in the current template context
- Nested properties up to 3 levels deep
- Lists with their first 3 items
- Object properties and their types
Example output:
Debug: Template Variables
════════════════════════════════════════════════════════════
count: 42
enabled: true
post: {3 properties}
date: "2025-11-22"
tags: [3 items]
[0]: "kotlin"
[1]: "handlebars"
[2]: "debug"
title: "Post Title"
title: "My Post"
════════════════════════════════════════════════════════════
Features
- Automatic nesting: Shows nested objects and their properties up to 3 levels deep
- List inspection: Displays the first 3 items of any list/array
- Type information: Shows the type of complex objects
- Truncation: Long strings (>100 chars) are truncated with "..." for readability
- Sorted keys: Variables are displayed alphabetically for easy scanning
- Styled output: Renders in a fixed-width, scrollable box with a max height of 600px
Use Cases
- Template debugging: See what data is available in your template context
- Development: Understand the structure of posts, pages, and custom data
- Troubleshooting: Verify that expected variables are present and have correct values
Common Issues Revealed by Debug
Tags Not Rendering Correctly
If you see strange output when iterating over tags (like isEmpty, hashCode, byte arrays, etc.), you're likely iterating over page.metadata.tags or post.metadata.tags, which are strings, not arrays.
Wrong:
{{#each page.metadata.tags}} <!-- This is a string! -->
<span>{{this}}</span>
{{/each}}
Correct:
{{#each page.tags}} <!-- This is a proper array -->
<span>{{this}}</span>
{{/each}}
Both BlogPost and SitePage have a tags property that automatically parses the comma-separated string from metadata into a list.
Notes
- The debug helper is safe to use in production, but you should remove it before deploying
- The output is HTML-formatted and won't be escaped by Handlebars
- Variables starting with
__(internal variables) may be present in the context
Metadata Properties
Metadata Properties
Both BlogPost and SitePage objects automatically parse common metadata fields into convenient properties that you can use directly in your templates.
Tags
Tags are automatically parsed from comma-separated values in the frontmatter into a list.
Frontmatter:
---
title: "My Post"
tags: "kotlin, web, tutorial"
---
Template usage:
{{#if post.tags}}
<div class="tags">
{{#each post.tags}}
<span class="tag">{{this}}</span>
{{/each}}
</div>
{{/if}}
Important: Always use post.tags or page.tags, NOT post.metadata.tags or page.metadata.tags. The metadata value is a string, which will cause issues when iterating with {{#each}}.
Summary
The summary property is the primary field for content summaries.
For BlogPost
<p class="post-summary">{{post.summary}}</p>
Priority:
metadata["summary"]- Custom summary from frontmatter- First 160 characters of post content (auto-generated)
Frontmatter:
---
title: "My Post"
summary: "A brief summary of this post"
---
For SitePage
{{#if page.summary}}
<p class="page-summary">{{page.summary}}</p>
{{/if}}
Priority:
metadata["summary"]- Custom summary from frontmatternullif not set
Description
The description property is used for SEO meta descriptions and falls back to summary.
For BlogPost
{{! Description from metadata, or summary, or first 160 chars of content }}
<meta name="description" content="{{post.description}}">
Priority:
metadata["description"]- Custom description for SEO from frontmattermetadata["summary"]- Falls back to summary- First 160 characters of post content (auto-generated)
Frontmatter:
---
title: "My Post"
summary: "A brief summary for listings"
description: "A different description optimized for search engines"
---
For SitePage
{{! Description from metadata, or summary }}
{{#if page.description}}
<meta name="description" content="{{page.description}}">
{{/if}}
Priority:
metadata["description"]- Custom description for SEO from frontmattermetadata["summary"]- Falls back to summarynullif neither is set
Example: Complete Post Card
<article class="post-card">
<h2><a href="{{post.path}}">{{post.title}}</a></h2>
{{#if post.summary}}
<p class="summary">{{post.summary}}</p>
{{/if}}
<div class="meta">
<time>{{post.date}}</time>
{{#if post.tags}}
<div class="tags">
{{#each post.tags}}
<span class="tag">{{this}}</span>
{{/each}}
</div>
{{/if}}
</div>
</article>
Direct Metadata Access
You can still access raw metadata values directly:
{{! Access raw metadata string }}
{{post.metadata.tags}} <!-- "kotlin, web, tutorial" -->
{{! Access parsed list }}
{{#each post.tags}}{{this}}{{/each}} <!-- kotlin web tutorial -->
However, it's recommended to use the convenience properties (tags, description, summary) instead of accessing metadata directly.
Tips
- Keep
baseUrlconsistent with the published site to avoid broken canonical links. - Commit
config.jsonto version control so environments stay in sync. - When experimenting, the JSON serializer ignores unknown keys, so adding future settings is safe.
With a configured config.json, the rest of Statik (content folders, templates, and assets) falls naturally into place.