I'm writing a plugin where I need to render some semi-complex HTML clientside at runtime (all inside the CP).

Does Garnish (or any other library/framework/JS-thingamabob shipped with Craft) offer any built-in JS templating functionality a'la Handlebars or Underscore?

  • Is the HTML you need to render in Twig templates? Commented Apr 27, 2015 at 21:34
  • Not really, rendering serverside doesn't really make sense in this case as all of the data will be clientside. The plan is to use craft()->templates->includeJs() to inject the raw HTML template on pageload, before compiling it in my plugin's JS without $.html()'ing myself to death :) Just wondering if Craft ships with any JS templating functionality, or if I'd need to include Handlebars, Underscore or the like with my plugin. Commented Apr 27, 2015 at 22:15

3 Answers 3


The only JS library that ships with Craft (besides the Craft-specific Garnish) is jQuery. Of course, jQuery is a helpful JS library, but by no means a full-fledged framework. Fortunately, adding a separate JS library is painfully easy!

How to CDN from a Twig template...

{% includeJsFile '//full/path/to/cdn.js' %}

How to CDN from PHP...


When you use includeJsFile, it wraps your path in a standard <script> tag... It doesn't matter where the file is, as long as the path is valid.

Keep in mind, a PHP call will take effect in both the back-end and front-end of your site. So to keep the file loaded only in your CP, make sure to wrap a conditional around it:

if (craft()->request->isCpRequest()) {

Don't want to CDN? No problem! The best place to store local JS files would be in a resources folder:


In that case, you can use includeJsResource instead of includeJsFile.

  • Crazy good answer, Lindsey. I don't want to edit because I rarely get which word to use right, but I'm pretty sure it's "will take affect" instead of "will take effect".
    – Brad Bell
    Commented Apr 28, 2015 at 5:58
  • Thanks Brad! If that's your biggest complaint, I can work with that. Also, I actually nailed the grammar too. :)
    – Lindsey D
    Commented Apr 28, 2015 at 6:17
  • Thanks for the thorough reply, Lindsey. I feel Mustache/Handlebars is a pretty good fit for Craft, so CDN'ing that would be a good solution. Also, there is actually a JS port for Twig, though I haven't tried it yet. Commented Apr 28, 2015 at 7:21

There is no built in client side/JS templating available out of the box that I know of. You can always render Twig templates via Ajax by calling a plugin controller and returning a rendered HTML string, but that doesn't seem to fit your use case.

  • In most cases, this would definitely be the answer. However, the trip server side to compile a template seems a bit redundant when all the data is on the client side, and there are no interactions w/ Craft services etc. Commented Apr 28, 2015 at 7:13

There's also Swig. We've successfully been able to share JS templating with Craft templates, and it's worked pretty well. Not without it's caveats, though. Mostly coming from slight syntax differences and available filters.

  • Sweet, I'll check out Swig – thanks! Have you tested the Twig.js subset? Curious how the two compare. Commented Apr 28, 2015 at 12:55
  • 1
    Twig.js is meant as a port, Swig just happens to use a pretty much identical syntax.I've used both
    – Tim Kelty
    Commented Apr 28, 2015 at 16:55
  • 1
    Twig.js is probably more easily interoperable with Craft templates as it's meant to be a port. One thing I plan to do eventually is make a craft extension for twig.js and/or swig, that would give you all the filters and template functionality you would have in craft, so that you can truly use 1 template for php and js rendered templates.
    – Tim Kelty
    Commented Apr 28, 2015 at 17:04
  • Cool, thanks for your input, Tim! There's also a Grunt plugin which uses Twig.js – a Craft extension for the latter would open up some interesting possibilities. Commented Apr 28, 2015 at 17:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.