Guide 02 · Developer docs

Template languages: Smarty and Twig

Core dna renders server-side sites with Smarty or with Twig, one engine per site, and treats the two as peers. This guide is the one place both are documented: what they share, each engine's language and the platform's additions and limits, the two side by side, and translation.

L1–L2
Unit 01 · The shared model

Two engines, one platform

A Core dna site renders its templates with Smarty or with Twig, chosen by one site setting. What that setting changes (syntax, the helpers the platform registers, the security model), the much longer list of what it does not, and what happens to a template written for the other engine.

Who this is for. Every developer about to write templates for a server-rendered Core dna site, whichever engine it uses. Afterwards you will know where a site's engine is set, what the choice changes and what it leaves alone, so that you treat it as a choice of syntax rather than of architecture.

One setting per site

The engine is the site setting Globals.template.engine. Its value is Smarty, the default, or Twig. A site that sets nothing renders with Smarty. A site on Twig carries the value in the .settings.json file at the root of its site folder, beside templates/:

JSON .settings.json
{
	"Globals": {
		"template": {
			"engine": "Twig"
		}
	}
}
  • The value is case-sensitive. The platform builds the engine's class name from it, so Smarty and Twig work and twig stops the site from rendering at all.
  • The file wins. A value in .settings.json takes precedence over settings saved in the admin. The platform never serves a file whose name starts with a dot, so the file is not visible from the browser.
  • It applies to everything the site renders: page and component templates, error pages, and the template code typed into the admin for jobs, discount conditions, shipping methods and search facets (Rendering a template from a string).

To find out which engine an existing site uses without opening the settings, read any template: Tell whether a site is Smarty or Twig in thirty seconds.

What is identical in both

Everything below happens before the engine is involved, or is written once and handed to whichever engine the site uses. None of it changes with the setting.

MechanismWhere it is explained
Routing: which URL reaches which controller, and which record it loadsHow a request reaches your template
Which template renders a record: the layout of its live revision, or the controller's defaultWhich template renders a record
Where a template file is found: the site's folder, then the platform's, then virtual filesTemplate resolution order
Layouts, layout areas, components and component collectionsInput types, layouts, components and images
The variables a template receives, with the same names: page, record, _request, _query and the restGlobal template variables
What a template may call on a record: the response modelResponse models
The response cache, preventCaching() and the compiled-template cacheCompilation and caching
Forms, search, carts, checkout, members and every other module: the controllers assign the same records whichever engine renders themEach module's guide
The translation files, and translated content as linked recordsTranslation and internationalisation

A site's content model, its URLs and its admin setup can therefore move from one engine to the other untouched. Only the files under templates/ change.

What differs

SmartyTwig
Syntax{$page->getName()}, {if}, {foreach}{{ page.getName() }}, {% if %}, {% for %}
VersionSmarty 4.4Twig 3.19, with the string extension
Helpers the platform addsTranslation tags, |format, {json}, {error}, {debug_vars} (list)Coercion filters, its own empty test, json_decode, debug_vars, its own set tag (list)
Security modelA policy that lists the PHP functions a template may call and blocks the restNo sandbox: no list to check calls against
EscapingOff unless you askAlso off: the platform switches Twig's autoescaping off
A method the record does not offerAn error that names the methodEmpty output, no error
A template file changed on production without a deployRecompiled on the next requestServed from the compiled copy until the cache is cleared

The Comparing and porting unit sets the two dialects next to each other construct by construct, and covers the differences that cause visible bugs.

The same folder and the same extension

Both engines read the same templates/ folder, and both read files ending in .html. The extension never selects an engine: a site's engine parses every template the site renders, whatever its name. The admin offers files ending in .html, .tpl or .twig from the site's own templates/ folder as layout templates, so a Twig site may use either extension; most keep .html.

A few templates the platform ships exist once per engine. The Smarty version keeps the plain name and the Twig version adds -twig before the extension: the sign-in, consent and remember-me screens under o-auth/frontend/, and errors/oauth.html. The passkey screen is the exception: both versions carry a suffix, passkey-add-smarty.html and passkey-add-twig.html. To restyle one of these on a Twig site, override the -twig file, such as templates/o-auth/frontend/login-twig.html.

A template written for the other engine

A site has one engine, so a template in the other dialect is not rendered by the other engine: it is read by the site's own, with results that depend on the direction.

  • Twig syntax on a Smarty site. {% if %} tags and {# #} comments are syntax errors, so the template fails to compile and the page errors. A bare {{ value }} is printed as it stands.
  • Smarty syntax on a Twig site. Single braces mean nothing to Twig, so {$page->getName()} and {if} are printed on the page as text, with no error.

So a snippet copied from the wrong engine either breaks the page or leaks its source onto it. Choosing an engine for a new site gives the recommendation that follows: one engine per site, for good.

Go deeper

Was this page helpful?

Your answer goes to the docs team.