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:
- Reads each content file in a collection
- Processes the template with that content's data
- Generates a page at the output path you specified
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:
- Publishing & Scheduling to control content visibility
- Advanced Features for more template capabilities
- Workflow Examples to see templates in action