Skip to main
Table of Contents

Handlebars Templates

This page demonstrates how Synticore uses Handlebars templates and custom helpers. Each section below provides a short explanation, a live compiled output, and template source code.

about.hbs

This template renders each paragraph from custom.brand.about. If that array is missing, it falls back to a default message.

Live Output (Compiled Template)

This is the official example project for Synticore, a flexible and efficient static site compiler. Designed to demonstrate a wide range of layout, style, and content features, this project provides a working showcase of how Synticore can structure, render, and enhance websites with minimal setup and maximum control.

The sections in this example cover layout styling, module integration, and individual page generation. You'll find demonstrations of syntax highlighting, markdown processing, slideshows, image watermarking, blog posts, and more—all powered by Synticore’ modular and declarative configuration approach.

Whether you're just getting started or evaluating Synticore for a larger project, this example serves as a foundational reference for building powerful, maintainable static sites.

Template Code

Reference: line 1 checks data availability, line 2 starts iteration, and line 5 is the fallback branch.

{{#if custom.brand.about}}
{{#each custom.brand.about}}
<p>{{this}}</p>
{{/each}}
{{else}}
<p>No information available about the brand.</p>
{{/if}}

social-link.hbs

This template loops through custom.brand.social and builds one button link per social platform. It also uses the lowercase helper to generate class names.

Live Output (Compiled Template)

Template Code

Reference: line 1 is the main loop, and line 2 applies the lowercase helper for class naming.

{{#each custom.brand.social}}
<a class="button font-icon--color--social--{{lowercase name}}--background"
   href="{{link}}"
   title="Visit {{../require.site.title}} on {{name}}">
    <span class="font-icon--social--{{lowercase name}}"></span>
    {{name}}
    <span class="font-icon--interface--external"></span>
</a>
{{/each}}

location-embed.hbs

This template reads custom.brand.location and renders an embeddable map iframe. The map URL is generated by the googleMapsEmbed helper.

Live Output (Compiled Template)

Template Code

Reference: line 1 scopes location data, and line 4 is the helper call that builds the embed URL.

{{#with custom.brand.location}}
<iframe
    style="border: 0px none; width: 100%; height: 100%;"
    src="{{googleMapsEmbed address zoom}}"
    frameborder="0"
    allowfullscreen=""
    loading="lazy"
    referrerpolicy="no-referrer-when-downgrade">
</iframe>
{{/with}}

copyright.hbs

This template conditionally renders author copyright details, then always renders brand/site copyright details. It uses notEquals to decide whether to show an external-link icon beside the author name.

Live Output (Compiled Template)

Content © 2024-2026 Example Author , All Rights Reserved. Website © 2024-2026 Synticore Website Compiler Example, All Rights Reserved.

Template Code

Reference: line 1 gates the author block, line 7 is the notEquals condition, and line 15 starts the always-rendered site copyright block.

{{#if custom.site.author}}
<span class="copyright">
    Content ©
    <span id="copyrightyears__author">{{custom.site.author.copyright_years}}</span>
    <a href="{{custom.site.author.url}}" title="{{custom.site.author.name}}: Home">
        {{custom.site.author.name}}
        {{#if (notEquals custom.site.author.url require.site.url)}}
            <span class="font-icon--interface--external"></span>
        {{/if}}
    </a>
    <span>, All Rights Reserved.</span>
</span>
{{/if}}

<span class="copyright">
    {{#if custom.site.author}}Website {{/if}}©
    <span id="copyrightyears__brand">{{custom.brand.copyright_years}}</span>
    <a href="/" title="{{require.site.title}}: Home">{{require.site.title}}</a>
    <span>, All Rights Reserved.</span>
</span>

These templates show helper usage for transformed output: obfuscated email display, normalized phone link values, and encoded Google Maps links.

Reference: lines 4, 11, and 16 are the key helper calls: splitEmail, phoneLink, and googleMapsLink.

<!-- email.hbs -->
{{#with custom.brand}}
<a href="mailto:{{email}}?subject=Website%20Message">
    <span class="email">{{splitEmail email}}</span>
    <span class="font-icon--interface--external"></span>
</a>
{{/with}}

<!-- phone.hbs -->
{{#with custom.brand}}
<a href="tel:{{phoneLink phone}}">{{phone}} <span class="font-icon--interface--external"></span></a>
{{/with}}

<!-- location-link.hbs -->
{{#with custom.brand.location}}
<a href="{{googleMapsLink address}}">{{address}} <span class="font-icon--interface--external"></span></a>
{{/with}}

Custom Helper Registration Code (handlebars.js)

This is the helper module used by the example project. These functions are registered into Handlebars and then called by templates such as social-link.hbs, email.hbs, phone.hbs, and location-embed.hbs.

Source

Reference: line 2 defines lowercase, line 3 begins splitEmail, and line 18 begins googleMapsEmbed.

module.exports = (Handlebars) => ({
  lowercase: (text) => text.toLowerCase().replace(/\s+/g, '-'),
  splitEmail: (email) => {
      if (typeof email !== 'string') return '';
      const formattedEmail = email.replace('@', '&#8203;@');
      return new Handlebars.SafeString(formattedEmail);
  },
  phoneLink: (phone) => {
      if (typeof phone !== 'string') return '';
      const formattedPhone = phone.replace(/[^+\d]/g, '');
      return new Handlebars.SafeString(formattedPhone);
  },
  googleMapsLink: (address) => {
      if (typeof address !== 'string' || address.trim() === '') return '#';
      const encodedAddress = encodeURIComponent(address);
      return new Handlebars.SafeString(`https://www.google.com/maps?q=${encodedAddress}`);
  },
  googleMapsEmbed: (address, zoom) => {
      if (typeof address !== 'string' || address.trim() === '') return '';
      const encodedAddress = encodeURIComponent(address);
      const zoomParam = zoom ? `&z=${encodeURIComponent(zoom)}` : '';
      return new Handlebars.SafeString(
          `https://www.google.com/maps?q=${encodedAddress}&output=embed${zoomParam}`
      );
  },
  notEquals: (value1, value2) => value1 !== value2
});