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…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.