Skip to main content

Post Frontmatter

Frontmatter is YAML metadata at the top of markdown files that controls how posts are rendered, organized, and displayed.

Format

Frontmatter must be enclosed in triple-dashes (---) at the start of the file:
---
title: "My Post Title"
description: "A brief summary"
date: "2026-03-01"
tags: ["golang", "performance"]
pinned: false
draft: false
weight: 0
image: "/static/images/custom-card.jpg"
---

# Post content starts here

Your markdown content...

Required Fields

title
string
required
Post title displayed in <h1>, page title, search results, and RSS feed.
title: "Getting Started with Kosh"
Best Practices:
  • Use descriptive, unique titles
  • Aim for 40-60 characters for SEO
  • Avoid special characters that break URLs
date
string
required
Publication date in YYYY-MM-DD format. Used for sorting and RSS pubDate.
date: "2026-03-01"
Note: Future dates don’t prevent publication (no scheduling feature).

Optional Fields

description
string
Brief summary for meta descriptions, social cards, and post previews.
description: "Learn how to build high-performance static sites with Kosh"
Best Practices:
  • Keep under 160 characters for SEO
  • Write compelling copy for social shares
  • Avoid duplicating the title
tags
array
Array of tag strings for categorization. Tags are:
  • Displayed on post pages
  • Linked to tag index pages
  • Used in search filtering (tag:golang)
  • Visualized in knowledge graph
tags: ["golang", "static-site-generator", "performance"]
Formatting:
# Inline array (preferred)
tags: ["ai", "machine-learning"]

# Multi-line array
tags:
  - "ai"
  - "machine-learning"
Best Practices:
  • Use 2-5 tags per post
  • Use lowercase with hyphens for multi-word tags
  • Be consistent across posts
pinned
boolean
default:false
Pin post to the top of index pages. Pinned posts appear before regular posts regardless of date.
pinned: true
Use Cases:
  • Important announcements
  • “Start here” guides
  • Featured content
Note: Multiple pinned posts are sorted by date.
draft
boolean
default:false
Mark post as draft. Excluded from builds unless -drafts flag is used.
draft: true
Preview Drafts:
kosh build -drafts
kosh serve --dev -drafts
Note: Drafts are:
  • Excluded from sitemap and RSS
  • Not indexed in search
  • Not counted in build metrics
weight
number
default:0
Custom sort order for documentation sites. Higher weight = appears first.
weight: 10
Use Cases:
  • Control sidebar order in docs theme
  • Override chronological sorting
  • Group related pages together
Example Weighting:
# Introduction (appears first)
weight: 100

# Core concepts (appears second)
weight: 50

# Advanced topics (appears last)
weight: 10
Note: Posts with equal weight are sorted by date.
image
string
Custom social card image path. Overrides auto-generated social card.
image: "/static/images/hero/my-post.jpg"
Path Formats:
  • Relative to outputDir: /static/images/card.jpg
  • Absolute URL: https://example.com/card.jpg
Recommended Specs:
  • Size: 1200x630px (Open Graph standard)
  • Format: JPG or PNG (WebP not widely supported)
  • File size: <200KB for fast loading
Fallback: If omitted, Kosh auto-generates a card using socialCards config.

Auto-Generated Fields

These fields are computed during build and cannot be overridden:
readingTime
number
Estimated reading time in minutes, calculated from word count.Algorithm: wordCount / 200 words per minute (rounded up)Access in Templates:
<span>{{ .ReadingTime }} min read</span>
Generated URL path for the post, derived from filename.Slugification:
  • content/my-post.md/my-post.html
  • content/getting-started.md/getting-started.html
  • content/v2.0/api.md/v2.0/api.html
Access in Templates:
<a href="{{ .Link }}">{{ .Title }}</a>
version
string
Version path for versioned documentation (empty string for latest).Example:
  • content/intro.mdversion: ""
  • content/v3.0/intro.mdversion: "v3.0"
Access in Templates:
{{ if .Version }}
  <span>Version: {{ .Version }}</span>
{{ end }}

Complete Example

content/blog/kosh-performance-guide.md
---
title: "Kosh Performance Optimization Guide"
description: "Learn how to build sites with sub-second build times using Kosh's caching and parallelization features"
date: "2026-03-01"
tags: ["performance", "optimization", "golang"]
pinned: true
draft: false
weight: 50
image: "/static/images/performance-hero.jpg"
---

# Introduction

Kosh achieves blazing-fast build times through several key optimizations...

## BLAKE3 Hashing

Content-addressed caching using BLAKE3...

Versioned Documentation

For versioned docs (using docs theme), place files in version subdirectories:
content/v4.0/getting-started.md
---
title: "Getting Started"
description: "Quick start guide for v4.0"
date: "2026-03-01"
weight: 100
---

# Getting Started with v4.0

New features in this version...
URL Structure:
  • content/v4.0/getting-started.md/v4.0/getting-started.html
  • content/getting-started.md/getting-started.html (latest)
Sparse Versioning: Only create versioned copies of changed pages. Unchanged pages fall back to latest version.

Template Access

Frontmatter fields are available in templates via the PageData struct:
templates/post.html
<article>
  <h1>{{ .Title }}</h1>
  <p class="meta">
    {{ .DateObj.Format "January 2, 2006" }} · {{ .ReadingTime }} min read
  </p>
  
  {{ if .Pinned }}
    <span class="badge">Pinned</span>
  {{ end }}
  
  <div class="tags">
    {{ range .Meta.Tags }}
      <a href="/tags/{{ . }}.html">{{ . }}</a>
    {{ end }}
  </div>
  
  <div class="content">
    {{ .Content }}
  </div>
</article>

Search Integration

Frontmatter is indexed for search:
  • title - Full-text search with BM25 scoring
  • description - Included in search snippets
  • tags - Filterable with tag: prefix
  • content - Body text searchable with stemming
Example Search Queries:
performance                    # Search title, description, content
"blake3 hashing"               # Phrase search
tag:golang performance         # Tag filter + term search

Blog Post

title: "Understanding Go Generics"
description: "A practical guide to type parameters in Go 1.18+"
date: "2026-03-01"
tags: ["golang", "generics", "tutorial"]
pinned: false
draft: false

Pinned Announcement

title: "Important: Site Migration Notice"
description: "We're moving to a new domain next week"
date: "2026-03-01"
tags: ["announcement"]
pinned: true
draft: false

Work-in-Progress Draft

title: "Advanced Kubernetes Patterns (WIP)"
description: "Deep dive into CRDs and operators"
date: "2026-03-15"
tags: ["kubernetes", "devops"]
draft: true

Documentation Page (Weighted)

title: "Installation"
description: "Install Kosh on macOS, Linux, and Windows"
date: "2026-03-01"
weight: 90
tags: ["getting-started"]

Custom Social Card

title: "Announcing Kosh 2.0"
description: "10x faster builds with incremental caching"
date: "2026-03-01"
image: "/static/images/kosh-2.0-launch.jpg"
tags: ["announcement", "release"]
pinned: true

Versioned Doc Page

title: "API Reference"
description: "Complete API documentation for v4.0"
date: "2026-03-01"
weight: 50
tags: ["api", "reference"]
File: content/v4.0/api-reference.md
URL: /v4.0/api-reference.html

Validation

Kosh validates frontmatter at build time: Missing Required Fields:
❌ content/my-post.md: missing required field 'title'
Invalid Date Format:
❌ content/my-post.md: invalid date '03/01/2026' (use YYYY-MM-DD)
Invalid Types:
❌ content/my-post.md: 'weight' must be a number, got string

YAML Tips

Quotes

Quote strings containing special characters:
# Required quotes
title: "Understanding Go's Error Handling"
description: "A post about: errors, nil, and panic"

# Optional quotes (no special chars)
title: Understanding Go Errors

Multi-line Strings

# Literal block (preserves newlines)
description: |
  This is a long description
  that spans multiple lines.
  
  It preserves newlines.

# Folded block (newlines become spaces)
description: >
  This is a long description
  that will be folded into
  a single line.

Boolean Values

# All equivalent
draft: true
draft: True
draft: yes

# All equivalent
draft: false
draft: False
draft: no

Arrays

# Inline (recommended for short lists)
tags: ["golang", "performance"]

# Block style (recommended for long lists)
tags:
  - "golang"
  - "performance"
  - "optimization"
  - "caching"

Metadata in Templates

Access raw frontmatter via .Meta map:
{{ if index .Meta "custom_field" }}
  <div>{{ index .Meta "custom_field" }}</div>
{{ end }}
Note: Custom fields are preserved but not validated. Use for theme-specific data.

Build docs developers (and LLMs) love