Skip to content
Back to skills

Ember

ASecurity

Ember.js is an opinionated JavaScript framework for large single-page web apps, built on convention over configuration: Glimmer components, tracked state, nested routing, services, Ember Data (WarpDrive) and the ember-cli build tool. Use when someone asks to "build an Ember app", "create an Ember component or route", "upgrade Ember", "use Ember Data", or "convert Ember templates to .gjs/.gts".

  • 142 stars
  • 0 votes
  • 0 copies
  • 13 views
  • Added May 27, 2026
developmentjavascripttypescriptgojavabashreactnodegitapifrontend

Works with

  • terminal
  • cli
  • api

Security analysis

A96/100
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro scans all 2 files and shows the line behind each finding

Scanned October 4, 2026

npx -y skills add TerminalSkills/skills --skill ember --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Ember?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Ember
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/terminalskills-ember/badge)](https://www.skillsdirectory.com/skills/terminalskills-ember)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: ember
description: >-
  Ember.js is an opinionated JavaScript framework for large single-page web apps, built on
  convention over configuration: Glimmer components, tracked state, nested routing, services,
  Ember Data (WarpDrive) and the ember-cli build tool. Use when someone asks to "build an Ember app",
  "create an Ember component or route", "upgrade Ember", "use Ember Data", or "convert Ember
  templates to .gjs/.gts".
license: Apache-2.0
compatibility: "Node.js 20.19+ and npm; Ember 6/7 with ember-cli 7, TypeScript optional"
metadata:
  author: terminal-skills
  version: "1.1.0"
  category: development
  tags: ["javascript", "ember", "framework", "spa", "typescript"]
  repository: https://github.com/emberjs/ember.js
---

# Ember.js — Convention-Over-Configuration Frontend Framework

## Overview

Ember is a batteries-included framework for ambitious web applications: file layout and naming drive behaviour, so teams share one structure. New apps (ember-cli 7.x, Ember 7.x at the time of writing, with a major release roughly every 18 months and a minor every six weeks) use:

- **Vite** as the build tool (`npm start` runs `vite`, `npm run build` runs `vite build`); the older ember-cli/Broccoli build with `ember serve` is the legacy path.
- **Template-tag components** (`.gjs` / `.gts`): the `<template>` block sits in the JavaScript or TypeScript file. Separate `.hbs` files still work in older apps.
- **Ember Data** now ships as **WarpDrive** (`@warp-drive/*` packages; models import from `@warp-drive/legacy/model`), with the store in `app/services/store.ts`.
- Octane idioms only: Glimmer components, `@tracked`, `@action`, `{{on}}` modifiers, `this.args`. Classic components, `this.get()`, `mut` and computed properties are legacy.

## Instructions

### Create and run an app

```bash
npm install -g ember-cli        # or: npx ember-cli new ...
ember new todo-app --lang en --typescript --strict
cd todo-app
npm start                       # Vite dev server on http://localhost:4200
npm test                        # builds in development mode and runs the QUnit suite via testem
npm run build                   # production build into dist/
npm run lint:types              # type-check .gts files (ember-tsc)
```

`--strict` (template-tag format) is what the official quick start uses; drop `--typescript` for plain JavaScript. Generators: `ember generate component todo-list`, `ember generate route todos`, `ember generate service session`. In a TypeScript app `ember generate model` may still emit a `.js` file with untyped fields; rename it to `.ts` and add `declare`.

### Components (template tag)

```typescript
// app/components/todo-list.gts
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { action } from '@ember/object';
import { on } from '@ember/modifier';
import { service } from '@ember/service';
import type Store from 'todo-app/services/store';
import type Todo from 'todo-app/models/todo';

interface Signature {
  Args: { title: string };
}

export default class TodoList extends Component<Signature> {
  @service declare store: Store;
  @tracked newText = '';

  get todos() {
    return this.store.peekAll('todo') as Todo[];
  }

  get remaining() {
    return this.todos.filter((t) => !t.completed).length;
  }

  @action updateText(event: Event) {
    this.newText = (event.target as HTMLInputElement).value;
  }

  @action async addTodo(event: SubmitEvent) {
    event.preventDefault();
    if (!this.newText.trim()) return;
    const todo = this.store.createRecord('todo', { text: this.newText, completed: false }) as Todo;
    await todo.save();
    this.newText = '';
  }

  <template>
    <h2>{{@title}} ({{this.remaining}} left)</h2>
    <form {{on "submit" this.addTodo}}>
      <input value={{this.newText}} {{on "input" this.updateText}} placeholder="Add todo" />
      <button type="submit">Add</button>
    </form>
    <ul>
      {{#each this.todos as |todo|}}<li>{{todo.text}}</li>{{/each}}
    </ul>
  </template>
}
```

In `.gjs`/`.gts` files every component, helper and modifier used in the template must be imported (`on` from `@ember/modifier`, `fn` from `@ember/helper`, other components by path). Built-ins such as `{{#if}}`, `{{#each}}` and `{{yield}}` need no import. A form submit handler must call `event.preventDefault()` itself.

### Model, route and router

```typescript
// app/models/todo.ts
import Model, { attr } from '@warp-drive/legacy/model';

export default class Todo extends Model {
  @attr('string') declare text: string;
  @attr('boolean') declare completed: boolean;
}
```

```typescript
// app/routes/todos.ts
import Route from '@ember/routing/route';
import { service } from '@ember/service';
import type Store from 'todo-app/services/store';

export default class TodosRoute extends Route {
  @service declare store: Store;

  model() {
    return this.store.findAll('todo');
  }
}
```

```typescript
// app/router.ts
Router.map(function () {
  this.route('todos');
  this.route('user', { path: '/users/:user_id' }, function () {
    this.route('posts');
  });
});
```

```typescript
// app/templates/todos.gts
import TodoList from 'todo-app/components/todo-list';

<template><TodoList @title="Sprint 42" /></template>
```

The route's `model()` result is available as `@model` in the route template; pass it down as arguments. The store needs a data source for `findAll`/`save`: a legacy adapter in `app/adapters/application.ts` or request handlers configured in `app/services/store.ts`. Check the Ember Data (WarpDrive) guide for the setup that fits your API.

## Examples

### Example 1: Add a route with a nested page

User: "Add a /users/:id/settings page to my Ember app."

Run `ember generate route user/settings`, add `this.route('settings')` inside the `user` route in `app/router.ts`, load data in the `model()` hook and render it in `app/templates/user/settings.gts`. Result: `npm start` serves `http://localhost:4200/users/42/settings`.

### Example 2: Convert a classic component

User: "Convert this classic component with `this.get('count')` and `actions: {}` to modern Ember."

Make it a `@glimmer/component` class, turn `count` into `@tracked count = 0`, turn each entry in `actions` into an `@action` method, replace `{{action "inc"}}` with `{{on "click" this.inc}}`, and read arguments as `@title` or `this.args.title`. Result: the component renders identically, with no `this.get`/`this.set` calls left.

## Guidelines

- Use `@tracked` for reactive state; assign to it, do not mutate in place when the value is an array or object (replace it, or use `tracked-built-ins`).
- Load data in the route `model()` hook, not in component constructors.
- Put shared state (session, notifications, feature flags) in services, injected with `@service`.
- Follow file naming conventions; the resolver depends on them.
- Upgrade one minor at a time and fix deprecation warnings before moving to the next major; deprecated APIs are removed in majors. `npx ember-cli-update` applies blueprint changes.
- Keep application tests in `tests/` (unit, integration, acceptance); `npm test` runs them.
- Ember suits long-lived, large apps; for a small static site a lighter tool is easier.

Files in this skill

  • SKILL.md4.8 KB
  • _scores.json1.5 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…