Templates
When a blog gets a request, first, we match its path to a Route (let’s assume the route post for /hello-world). Then, we fetch required data from our database, then we call the Twig template file defined in that route (post.twig).
Inside this file, you can include other files or even use inheritance. You can even call our Data API to fetch more data (More on that below)!
Twig
We use Twig 3.0 for templating. It is a powerful language with plenty of in-built tags, filters, and functions. Twig also has nice, easy-to-follow documentation, which was one reason we chose Twig over other template languages. If you haven’t used it ever, go through the Twig for Template Designers page, and you will get an idea of how it works. Basically, it’s HTML with superpowers.
Templates
This folder contains templates files. There are several types of template files
index.twig post.twig_)_footer.twigroute-. See custom routes belowroute-authors.twigcomponent-rich-link.twigTheme Variables
- The theme developer (you) creates the theme
- The blogger creates the content (data)
- HB combines the theme and data and generates the blog
When rendering the twig templates, we send data into your template file as objects. You will use this data to generate a beautiful UI.
There are 4 main objects in HB: Blog , Post , Tag , and Author. These objects are explained in the Data API page.
_blog_lang<html lang="{{ _lang.code }}">_configconfig.yaml) as an object_featured_post_post_tag_author_brandingEach Route gets different variables. We prefix each variable with _ so that it won’t conflict with the variables you define inside the theme files (Obviously, you shouldn’t prefix _ your variables inside the Twig template)
Placeholders
You are required to put some placeholders in your theme to make a few things work.
_head</head>. We automatically add SEO tags, styles.css link, and
code_head set by the blogger_foot</body>. We place the code_foot set by the blogger_comments_comment_count (optional)_newsletterSending all placeholders (except _lang) through the template filter is absolutely required to make them render as templates.
{{ _head | template }}{{ _head | template }} is equal to {{ include(template_from_string(_head)) }} in Twig. We defined the custom template filter to make it easier for you to write it,
as it is used frequently in HB templates.
Twig Helpers
We provide a few custom Twig functions and filters to make writing templates easier.
Functions
data- a function to call the Data API. See Fetching data below.
{% set posts = data(endpoint="posts", filter="author.slug=user") %}icon- a function to get an icon.
{{ icon('bootstrap', 'arrow-down', 20, 20) }}Function definition: icon(iconLibrary, iconName, width, height)
- All icon names are lowercase, and words are separated by
-(arrow-down). - These icon libraries are supported
- bootstrap
- fontawesomeFree icons only
- append
-regularto regular icons (calendar-regular) - append
-solidto solid icons (calendar-solid) - Do not append anything for brand icons (
github) - ionicons
- heroicons
- append
-solidto solid icons (archive-solid) - append
-outlineto outline icons (archive-outline) - octicons
- css.gg
Under the hood, we use the php-svg-icons open-source library. If you need to add more icon libraries, please send a PR there.
Filters
asset_url- a filter to link assets- Turns an asset filename into its absolute URL.
- Adds last updated timestamp as a query param (to bypass browser cache on updates)
asset- a filter to directly print assets (only for text assets like SVGs)pagination_page_url- a filter to convert a page number to full URLlang- a filter for translations. Learn more in internationalization.lang_by_number- See conditional strings based on a number.language_variant_url- See language switchertoc- a filter to generate a table of contents from a HTML string.{{ _post.content | toc }}By default, all headings are included in the table of contents. You can set which levels to include as follows:
{{ _post.content | toc('2,3') }}
{{ 'script.js' | asset_url }}<script src="{{ 'script.js' | asset_url }}"></script>
// changes to:
<script src="https://subdomain.hyvorblogs.io/assets/script.js?v=12931923993"></script>{{ 'beauty.svg' | asset }}<a href="{{ _pagination.page_prev | pagination_page_url }}">Previous Page</a>The difference between functions and filters can be quite confusing in Twig. Our general rule is
to use functions to compute things (data and icon) and use filters
when apply a transformation (asset_url, asset, etc.).
Fetching Data
Use the data function to fetch data from our Data API.
<!-- Fetch data -->
{% set recent_posts = data(endpoint="posts", sort="published_at DESC", limit="5") %}
<!-- Render UI -->
<div id="recent-posts">
{% for post in recent_posts.data %} {% include '_recent-post-card.twig' with post %} {% endfor %}
</div>Use the endpoint named argument to set the API endpoint. You can set all other parameters by just sending them as named arguments to the data Twig function (Ex: sort="published_at DESC").
Custom Routes
There are two ways to add custom routes:
- The blogger can add custom routes from the console (See docs).
- Theme developers can define custom routes by adding files named
route-{route}.twigto thetemplatesfolder.
The first option is more robust, and it providers easier way to automatically set input variables _posts (by filtering), _tag, _author, etc so you can access them without calling the Data API. But, as a theme developer, you will need to use the second option.
For example, let’s say you decide that your theme want a page to list all authors of the blog. You can add a route-authors.twig to the templates folder. If the blog gets a request to /authors, this template will be rendered automatically.