What is glint and its use with first-class component templates?

I’m cherry picking @ef4 's comment from here.

I’m a pedestrian with curiosity I can’t shake.

  • what is glint?
  • have you played with the combination? Do you have an example to share for us to grok?

Glint is a tool which uses the TypeScript language tooling to provide autocomplete, go-to-definition, refactoring, in-editor documentation popovers, type checking, etc.—and as long as you provide the right information (whether via type annotations or via JSDoc), it can do that 100% reliably.

With first-class component templates, Glint has to do do one (hard!) thing: turn templates into something TypeScript understands. After that, it can just ask TypeScript for answers like auto-imports, go-to-definition, renaming, etc., and get it “for free”.

This is a big deal because historically all of our tooling (including the Unstable/Experimental Ember Language Servers and the IntelliJ plugin) had to basically build up all of that information themselves, and in many cases they had to do it with smart guesses, rather than being able to know reliably what they were dealing with. With first-class component templates, we can let the TS tooling which powers nearly all modern JS editor tooling do all the hard work.

Net, you can write something like this—

import Component from '@glimmer/component';
import type { TemplateOnlyComponent } from '@ember/component/template-only';
import { on } from '@ember/modifier';

interface StyledButtonSignature {
  Args: {
    text: string;
  Element: HTMLButtonElement;

const StyledButton: TemplateOnlyComponent<StyledButtonSignature> =
    <button class='fancy-button' type='button' ...attributes>

interface GreetSignature {
  Args: {
    name?: string;

export default class Greet extends Component<GreetSignature> {
  sayHello = () => {
    const { name } = this.args;
    alert(`Hello, ${name ?? "there"}!`);

      @text="Say hello!"
      {{on "click" this.sayHello}}

—and it will “just work” with all of those features. And remember, that works for JavaScript, not just TypeScript (though we need to spend some time updating our docs to cover that).

Again, for much more, check out the docs and my upcoming talk!

Now, Glint can work without first-class component templates, but in that case it needs you to tell it about with a ‘registry’ which maps the name of the component to the component itself. That looks like this:

import Component from '@glimmer/component';

export default class MyComponent extends Component {
  // ...

declare module '@glint/ember-environment-loose/registry' {
  export default interface Registry {
    // for angle-bracket invocation, `<MyComponent />`
    MyComponent: typeof MyComponent;
    // for curly-style invocation, `{{my-component}}`
    'my-component': typeof MyComponent;

This is how it can actually know, rather than just guessing, what those invocations refer to. The existing Unstable/Experimental Ember Language Servers solve this problem by adding a bunch of heuristics to try to guess—mostly correctly, but not 100%, because it literally can’t be, not through any fault of theirs!


@chriskrycho thank you for the thoughtful, ever enlightening response!

Glint’s abstraction for seamless interoperability sounds fantastic!

More so I’m hearing ahead of time compilation and static analysis goodies becoming standard in Ember.js worlds. Paradigm-shift me please.

Seeing these first-class components also whets my appetite for new-world authoring. I’m still a head-in-the-sand person with an Ember.js application. I’ll have to come up for air more frequently to adopt such fundamental improvements.

For anyone else who would like to view Chris’ talk, here is link.


@chriskrycho Thank you so much for clearing my concepts on what is Glint and how effectively it can be used with different first-class component templates. Just like always, you have written a very useful content.