Templates

Learn how to create templates that render your content using Hammer's template syntax and context variables.

Template Basics

Templates are HTML files located in the templates/ directory that define how your content is rendered.

What are Templates?

Templates use Hammer's template syntax to render content dynamically. One template can generate multiple pages—one for each content file in a collection.

Template Rendering

During build, Hammer:

  1. Reads each content file in a collection
  2. Processes the template with that content's data
  3. Generates a page at the output path you specified
Tip: Templates can use all standard Hammer tags (includes, variables, conditionals, loops) in addition to Content Mode-specific features.

Template Context

Templates have access to several variables that provide data and functionality:

doc (Current Document)

The doc variable represents the current document being rendered. It includes:

  • Standard properties: doc.title, doc.date, doc.body
  • System properties: doc.slug, doc.filePath, doc.collection
  • Publishing: doc.published, doc.scheduledDate
  • Custom fields: Any fields from your front matter (e.g., doc.author, doc.tags)
  • Nested properties: doc.author.name, doc.author.bio (for relations)

collections (All Collections)

The collections variable provides access to all content collections:

  • collections.posts - Array of all posts
  • collections.authors - Array of all authors
  • collections.posts[0] - Access specific items
  • collections.posts.length - Get collection size

site (Site Configuration)

The site variable provides site-wide configuration from hammer.json:

  • site.title - Site title
  • site.url - Site URL

helpers (Helper Functions)

The helpers variable provides utility functions:

  • helpers.formatDate(date, format?) - Format dates
  • helpers.slugify(text) - Generate slugs
  • helpers.markdown(text) - Convert Markdown to HTML
  • helpers.relativePath(from, to) - Calculate relative paths
  • helpers.join(array, separator) - Join array elements
  • helpers.default(value, fallback) - Provide fallback values

Template Tags

Output Expressions

Output content using escaped or raw HTML:

<!-- Escaped HTML (safe for user content) -->
<h1><!-- $doc.title --></h1>
<p>By <!-- $doc.author.name --></p>

<!-- Raw HTML (for trusted content) -->
<div><!-- $!doc.body --></div>

Use $ for escaped output (safe) and $! for raw HTML (trusted content only).

Variables

Set variables for reuse in your template:

<!-- Set a variable -->
<!-- @var pageTitle = $doc.title -->
<!-- @var authorName = $doc.author.name -->

<!-- Use the variable -->
<h1><!-- $pageTitle --></h1>
<p>By <!-- $authorName --></p>

Conditionals

Conditionally show or hide content:

<!-- @if doc.author -->
  <p>By <!-- $doc.author.name --></p>
<!-- @else -->
  <p>Anonymous</p>
<!-- @endif -->

Loops

Iterate over collections or arrays:

<!-- @loop post in collections.posts -->
  <article>
    <h2><!-- $post.title --></h2>
    <p><!-- $post.summary --></p>
  </article>
<!-- @endloop -->

Loop Variables

Access loop metadata:

  • loop.index - Current index (0-based)
  • loop.first - True if first item
  • loop.last - True if last item
  • loop.length - Total items

Example Templates

Detail Template

A template for rendering individual content items (e.g., a blog post):

<!DOCTYPE html>
<html>
<head>
  <title><!-- $doc.title --></title>
</head>
<body>
  <article>
    <h1><!-- $doc.title --></h1>
    <p>Published: <!-- $helpers.formatDate(doc.date, "dd MMM yyyy") --></p>
    <!-- @if doc.author -->
      <p>By <!-- $doc.author.name --></p>
    <!-- @endif -->
    <div><!-- $!doc.body --></div>
  </article>
</body>
</html>

List Template

An optional template for rendering collection listing pages:

<!DOCTYPE html>
<html>
<body>
  <h1>All Posts</h1>
  <!-- @loop post in collections.posts -->
    <article>
      <h2><a href="/blog/<!-- $post.slug -->/"><!-- $post.title --></a></h2>
      <p><!-- $post.summary --></p>
    </article>
  <!-- @endloop -->
</body>
</html>

Best Practices

Output Safety

  • Use escaped output ($) for user content to prevent XSS attacks
  • Use raw output ($!) only for trusted HTML (like rendered Markdown)
  • Always escape user-generated content

Error Handling

  • Check for existence before accessing nested properties
  • Use conditionals to handle missing data gracefully
  • Use helpers.default() for fallback values

Template Organization

  • Use includes for reusable components (headers, footers, etc.)
  • Keep templates DRY (Don't Repeat Yourself)
  • Use variables to simplify complex expressions
  • Use helpers for formatting instead of manual manipulation

Performance

  • Keep template logic simple and efficient
  • Avoid deeply nested loops when possible
  • Use conditionals to skip unnecessary processing

Next Steps

Now that you understand templates, learn about: