[For Developers of Custom Elements] Synchronous Instantaneous Frontend Only Template Rendering Using Nunjucks

A while back I was asked to add templating support to a couple of my Home Assistant frontend projects (Universal Remote Card and Custom Features for Home Assistant Cards). One issue I ran into while implementing was the slow speed of template rendering. Home Assistant templates in frontend cards are sent to the backend, processed using jinja2, and then sent back to the frontend. This entire process can take over a second and cause significant delays in frontend rendering or page load layout jumping and shifting.

After some additional research, I developed a new method which processes Home Assistant templates in the frontend using the hass object.

ha-nunjucks

ha-nunjucks is a wrapper for nunjucks. Nunjucks is a templating engine for JavaScript which is heavily inspired by jinja2 and shares almost all of it’s syntax. Therefore Home Assistant jinja2 templates largely work with nunjucks with little to no modification!

To use this package, install it with npm:

npm install ha-nunjucks

And then import and use the renderTemplate function:

import { renderTemplate } from 'ha-nunjucks';

const renderedString = renderTemplate(this.hass, templateString);

It’s that easy!

You can also add your own variables and functions to the render context using an optional context argument.

const context = {
  foo: 'bar',
  doThing(thing: string) {
    return `doing ${thing}!`;
  },
  config: {
    entity: 'foo.bar',
    attribute: 'baz_bah',
  },
};

const renderedString = renderTemplate(this.hass, templateString, context);

One caveat of this approach is that I had to reimplement the Home Assistant template extensions in TypeScript in order for them to be used. I have reimplemented the vast majority of the Home Assistant template extensions, including Pythonic datetimes using a separate project I forked just for ha-nunjucks - ts-py-datetime. If anyone wants to help get the last 5% implemented I’m open to contributors!

I believe that this method of template rendering is not just at parity with, but is superior to backend jinja2 template rendering for Home Assistant frontend cards. By keeping all of the render logic synchronous and in the frontend, template rendering can now all be done before render in milliseconds if not less. I hope some of y’all consider implementing it into your projects and feel the same!

2 Likes

npm is not available in HAOS.

You misunderstand. This is for developers of custom cards, elements, etc. Those are written using JavaScript/TypeScript. Backend custom integrations are written using Python (like HAOS) and should still use the built in jinja2 templating system (if they need it).