Glimmer.js Formatter Online — Format Ember Templates

Beautify Glimmer.js and Handlebars-style Ember templates with block helpers ({{#each}}, {{#if}}), Octane angle-bracket components, and modifiers — 100% in your browser.

What is a Glimmer.js Formatter?

A Glimmer.js formatter reindents a Glimmer / Handlebars template — the templating language used by Ember.js — by tracking two kinds of nesting at once: ordinary HTML tags and Handlebars block helpers ({{#each}}...{{/each}}, {{#if}}...{{/if}}, {{#let}}...{{/let}}). Each opens a new indent level; each closing form pops back. Octane angle-bracket components (<MyComponent />) and named blocks (<:title>) follow the same HTML rules.

The OpenFormatter Glimmer tool is a pretty printer — it preserves attribute values, helper invocations, and modifier syntax exactly, and only adjusts whitespace between elements and blocks. It runs entirely in your browser; nothing is uploaded.

How to format Glimmer templates — 4 steps

  1. Paste your template. Drop a .hbs file body or the contents of a <template> tag from a .gjs/.gts file into the Input panel. Click Load Sample to try a real Octane component.
  2. Click Format. The formatter walks tags and Handlebars blocks together and indents them in your browser.
  3. Review the output. Confirm {{#each}} bodies and {{#if}}/{{else}} branches are indented correctly under their host element.
  4. Copy the result. Click Copy to paste back into your .hbs file, the <template> tag of your .gjs component, or a code review.

Side-by-side: compact input vs formatted output

Compact Glimmer

<ul>{{#each this.users as |user|}}<li>{{user.name}}</li>{{/each}}</ul>

Formatted Glimmer

<ul>
  {{#each this.users as |user|}}
    <li>{{user.name}}</li>
  {{/each}}
</ul>

Block-Helper Aware

Tracks {{#each}}, {{#if}}, {{#let}}, {{#unless}} and their {{else}} branches alongside HTML tags.

Octane-Compatible

Angle-bracket components <MyComp @arg={{x}} />, named blocks <:title>, and modifiers {{on "click" ...}} are preserved.

Browser-Only

Templates run through JavaScript on your machine. Internal route names and component arguments never leave the device.

Common use cases

  • check_circleFormat an Ember .hbs route or component template before committing
  • check_circleBeautify a Glimmer template copied from a Stack Overflow answer or GitHub issue
  • check_circleReformat a one-line minified template extracted from an Ember addon build
  • check_circleFormat the <template>...</template> body of a .gjs / .gts Glimmer file
  • check_circleClean up a template that uses Octane angle-bracket components and modifiers
  • check_circleIndent a deeply nested {{#each}}-of-{{#each}} table component
  • check_circleFormat a third-party Ember component template you want to fork or audit
  • check_circleBeautify a Handlebars-rendered email template (Mailgun, Customer.io)

Glimmer formatter vs ember-template-lint vs Prettier plugin

A pretty printer is the lightweight option — it preserves token order and only adjusts whitespace between elements and blocks. ember-template-lint is a different tool entirely — it lints templates against Ember-style rules (no-implicit-this, no-action, no-curly-component-invocation, require-button-type) and can autofix many. prettier-plugin-ember-template-tag formats the <template> tag inside .gjs/.gts files; with prettier-plugin-ember-html-template-tag it formats the same templates with Handlebars-aware printing. Use this online tool for a one-off readability fix; use the lint and Prettier tools for project-wide enforcement.

More than Glimmer formatting

Format Vue, Angular, or LWC templates, or pretty-print HTML — all browser-side, all free.

Frequently Asked Questions

What is Glimmer.js?

Glimmer is the rendering engine that powers Ember.js templates since Ember 2.10. It compiles Handlebars-flavoured templates to a binary "wire format" and a stream of opcodes that run on a virtual machine — the result is fast, fine-grained DOM updates with autotracking. Glimmer templates are .hbs files that look like HTML extended with {{...}} expressions and {{#block}}...{{/block}} helpers; Octane introduced Angle Bracket Invocation (<MyComponent @arg={{value}} />) as the modern way to call components.

Is Ember still relevant?

Yes — Ember 5 ships in 2023, the project has a defined six-week release cycle, and Ember 6 is in development. The framework powers production applications at LinkedIn, Square, Apple Music, Tilde (Skylight), Intercom, and many others. The community is smaller than React or Vue but the framework is mature and the conventions are stable. If you maintain an Ember app you need a Glimmer template formatter; if you are picking a new framework, Ember remains a strong choice for opinionated full-stack apps.

What is the difference between Handlebars and Glimmer templates?

Handlebars is the original templating language (Mustache-derived). Glimmer is a superset — it parses the same Handlebars syntax ({{value}}, {{#each}}...{{/each}}, {{!-- comment --}}) but adds component-level features: angle-bracket invocation (<MyComp @arg={{x}} />), named blocks (<:default>), modifiers ({{on "click" ...}}), helpers as first-class expressions, and template-only components (.hbs files without a backing class). The formatter handles both because syntactically they are similar at the brace-matching level.

How are {{#if}}...{{else}}...{{/if}} blocks indented?

The opening {{#if condition}} and closing {{/if}} match like a brace pair — content between them indents one level. The {{else}} branch (or {{else if other}}) sits at the same level as the {{#if}} keyword, with its own body indented one level. This matches the Ember community convention used by ember-template-lint and prettier-plugin-ember-template-tag.

Does it handle Octane angle-bracket components?

Yes. <MyComponent @prop={{value}} @click={{this.handle}} /> self-closes and emits inline. <UserCard @user={{this.user}}>...</UserCard> opens a block and indents children one level until </UserCard>. Named blocks (<:title>...</:title>, <:body>...</:body>) inside an angle-bracket component indent under the component, with their own children indented further. Helpers in arguments (@on={{fn this.handle "save"}}) are preserved as-is.

Does it preserve modifiers like {{on "click" this.handler}}?

Yes. Element modifiers attached with {{ }} on an HTML tag — {{on "click" this.handler}}, {{did-insert this.setup}}, {{did-update this.refresh @value}} — are kept in the same line as their host element. The formatter does not split them across lines or modify the helper invocation; it only adjusts indentation around HTML tags and Handlebars blocks.

Will it format my .hbs file or my <template> tag in a .gjs file?

Both work. A standalone .hbs file is plain Glimmer and pastes directly. For a .gjs (or .gts) file using the new <template>...</template> tag syntax, copy the contents between the <template> and </template> tags into the formatter. The surrounding JavaScript imports and class declarations should be formatted with the JavaScript or TypeScript pretty printer instead.

Is the Glimmer template I paste sent to your servers?

No. Formatting runs entirely in your browser using JavaScript. Templates referencing internal route names, action handlers, or proprietary component arguments never leave your device. Open DevTools → Network and click Format to verify no requests are made.

Glimmer.js Formatter — Ember Template Format