KS
Killer-Skills

javascript-ember — how to use javascript-ember how to use javascript-ember, what is javascript-ember, javascript-ember alternative, javascript-ember vs ember-cli, javascript-ember install, javascript-ember setup guide, ember octane conventions, context7 MCP, freshbooks website speed optimization

v1.0.0
GitHub

About this Skill

Perfect for Frontend Agents needing advanced Ember.js development capabilities with Ember Octane conventions. javascript-ember is a Chrome extension skill that provides expert Ember.js development following Ember Octane conventions and current best practices.

Features

Writes modern, performant Ember.js applications following Ember Octane conventions
Uses context7 MCP to check for relevant documentation and project-specific conventions
Follows current best practices for Ember.js development
Checks for relevant documentation before generating, modifying, or reviewing Ember code
Provides project-specific architectural patterns and coding standards
Enables use of context7 MCP for consistent Ember code development

# Core Topics

jaredlander jaredlander
[0]
[0]
Updated: 3/6/2026

Quality Score

Top 5%
60
Excellent
Based on code quality & docs
Installation
SYS Universal Install (Auto-Detect)
Cursor IDE Windsurf IDE VS Code IDE
> npx killer-skills add jaredlander/freshbooks-speed/javascript-ember

Agent Capability Analysis

The javascript-ember MCP Server by jaredlander is an open-source Categories.community integration for Claude and other AI agents, enabling seamless task automation and capability expansion. Optimized for how to use javascript-ember, what is javascript-ember, javascript-ember alternative.

Ideal Agent Persona

Perfect for Frontend Agents needing advanced Ember.js development capabilities with Ember Octane conventions.

Core Value

Empowers agents to write modern, performant Ember.js applications following current best practices and utilizing context7 MCP for project-specific conventions and technical decisions, ensuring adherence to Ember Octane standards and resolving speed issues.

Capabilities Granted for javascript-ember MCP Server

Generating performant Ember.js applications with Ember Octane
Debugging speed issues in existing Ember.js codebases
Implementing context7 MCP for consistent coding standards

! Prerequisites & Limits

  • Requires context7 MCP for project-specific documentation
  • Ember.js and Ember Octane specific
Project
SKILL.md
23.2 KB
.cursorrules
1.2 KB
package.json
240 B
Ready
UTF-8

# Tags

[No tags]
SKILL.md
Readonly

Expert Ember.js Development

Write modern, performant Ember.js applications following Ember Octane conventions and current best practices.

Critical First Step: Use context7 MCP

ALWAYS use context7 MCP before writing or editing ANY Ember code - Before generating, modifying, or reviewing any Ember code, you MUST use the context7 MCP to check for relevant documentation. Context7 provides project-specific conventions, architectural patterns, coding standards, and technical decisions that override these general guidelines.

When to Use context7

Use context7 MCP in these situations:

  • Before writing any new Ember component, route, service, or model
  • Before modifying existing Ember code
  • When implementing features that might have project-specific patterns
  • When unsure about architectural decisions
  • Before suggesting refactors or improvements

How to Use context7

javascript
1// Example: Check for Ember component patterns before creating a component 2// Use the context7 MCP to search for relevant documentation 3// Query examples: 4// - "ember component patterns" 5// - "ember routing conventions" 6// - "ember data models" 7// - "ember testing standards" 8// - "glimmer component lifecycle" 9 10// Apply the documentation from context7 to your implementation

If context7 returns relevant documentation, follow it EXACTLY even if it conflicts with this skill's general guidance. Project-specific conventions always take precedence.

Core Principles

  1. Embrace Ember Octane - Use Glimmer components, tracked properties, and native classes
  2. Convention over configuration - Follow Ember's resolver patterns and file structure
  3. Use the platform - Prefer native JavaScript features over framework-specific abstractions when possible
  4. Composition through services and modifiers - Extract reusable logic into services and UI behavior into modifiers
  5. Data down, actions up (DDAU) - Maintain clear data flow patterns

Context7 MCP Workflow

Before implementing any Ember code, follow this workflow:

  1. Query context7 - Search for relevant documentation using specific terms:

    • Component type (e.g., "ember glimmer component")
    • Feature area (e.g., "ember routing", "ember data")
    • Specific pattern (e.g., "form validation", "authentication")
  2. Review results - Read any returned documentation carefully

    • Note project-specific naming conventions
    • Identify required patterns or abstractions
    • Check for mandatory testing requirements
    • Look for deprecated approaches to avoid
  3. Apply documentation - Implement code following context7 guidance

    • Use project-specific utilities and helpers
    • Follow established architectural patterns
    • Match existing code style and structure
    • Include required metadata or annotations
  4. Fall back to general patterns - If context7 has no relevant docs, use this skill's patterns

    • Apply standard Ember Octane conventions
    • Follow community best practices
    • Use examples from this skill as templates

Remember: context7 documentation always overrides this skill's general guidance.

Context7 Query Examples

When implementing different types of Ember code, use these query patterns:

For Components:

- "ember component patterns"
- "ember component architecture"
- "glimmer component conventions"
- "[specific component type]" (e.g., "button component", "form component")
- "component props" or "component arguments"
- "component lifecycle"
- "component testing"

For Routes:

- "ember routing patterns"
- "ember route conventions"
- "route data loading"
- "route guards" or "route authentication"
- "nested routes"
- "query parameters"

For Ember Data:

- "ember data models"
- "ember data adapters"
- "ember data serializers"
- "api integration"
- "data relationships"
- "data layer patterns"

For Services:

- "ember services"
- "service patterns"
- "shared state management"
- "[specific service]" (e.g., "authentication service", "api service")

For Testing:

- "ember testing"
- "component testing"
- "integration tests"
- "acceptance tests"
- "test patterns"
- "test data" or "fixtures"

For Styling:

- "ember styling"
- "css conventions"
- "component styles"
- "tailwind" or "[css framework]"

When Editing Existing Code:

- Search for the specific feature: "user profile", "login form", etc.
- Search for the pattern you're implementing: "form validation", "dropdown menu"
- Search for utilities you might need: "validation utilities", "date helpers"

Modern Ember Patterns (Octane+)

Glimmer Components

javascript
1// app/components/user-profile.js 2import Component from '@glimmer/component'; 3import { tracked } from '@glimmer/tracking'; 4import { action } from '@ember/object'; 5import { inject as service } from '@ember/service'; 6 7export default class UserProfileComponent extends Component { 8 @service currentUser; 9 @service router; 10 11 @tracked isEditing = false; 12 @tracked formData = null; 13 14 constructor(owner, args) { 15 super(owner, args); 16 // Use constructor for one-time setup 17 this.formData = { ...this.args.user }; 18 } 19 20 @action 21 toggleEdit() { 22 this.isEditing = !this.isEditing; 23 if (this.isEditing) { 24 this.formData = { ...this.args.user }; 25 } 26 } 27 28 @action 29 async saveUser(event) { 30 event.preventDefault(); 31 32 try { 33 await this.args.onSave(this.formData); 34 this.isEditing = false; 35 } catch (error) { 36 // Handle error 37 console.error('Save failed:', error); 38 } 39 } 40 41 @action 42 updateField(field, event) { 43 this.formData = { 44 ...this.formData, 45 [field]: event.target.value 46 }; 47 } 48}
handlebars
1{{! app/components/user-profile.hbs }} 2<div class="user-profile"> 3 {{#if this.isEditing}} 4 <form {{on "submit" this.saveUser}}> 5 <label> 6 Name: 7 <input 8 type="text" 9 value={{this.formData.name}} 10 {{on "input" (fn this.updateField "name")}} 11 /> 12 </label> 13 14 <label> 15 Email: 16 <input 17 type="email" 18 value={{this.formData.email}} 19 {{on "input" (fn this.updateField "email")}} 20 /> 21 </label> 22 23 <button type="submit">Save</button> 24 <button type="button" {{on "click" this.toggleEdit}}>Cancel</button> 25 </form> 26 {{else}} 27 <div class="profile-display"> 28 <h2>{{@user.name}}</h2> 29 <p>{{@user.email}}</p> 30 31 {{#if this.currentUser.canEdit}} 32 <button {{on "click" this.toggleEdit}}>Edit Profile</button> 33 {{/if}} 34 </div> 35 {{/if}} 36</div>

Tracked Properties and Getters

javascript
1import Component from '@glimmer/component'; 2import { tracked } from '@glimmer/tracking'; 3import { cached } from '@glimmer/tracking'; 4 5export default class DataGridComponent extends Component { 6 @tracked sortColumn = 'name'; 7 @tracked sortDirection = 'asc'; 8 @tracked filterText = ''; 9 10 // Use @cached for expensive computations that depend on tracked properties 11 @cached 12 get filteredData() { 13 const { filterText } = this; 14 if (!filterText) return this.args.data; 15 16 const lower = filterText.toLowerCase(); 17 return this.args.data.filter(item => 18 item.name.toLowerCase().includes(lower) || 19 item.email.toLowerCase().includes(lower) 20 ); 21 } 22 23 @cached 24 get sortedData() { 25 const data = [...this.filteredData]; 26 const { sortColumn, sortDirection } = this; 27 28 return data.sort((a, b) => { 29 const aVal = a[sortColumn]; 30 const bVal = b[sortColumn]; 31 const result = aVal < bVal ? -1 : aVal > bVal ? 1 : 0; 32 return sortDirection === 'asc' ? result : -result; 33 }); 34 } 35}

Services

javascript
1// app/services/notification.js 2import Service from '@ember/service'; 3import { tracked } from '@glimmer/tracking'; 4import { action } from '@ember/object'; 5 6export default class NotificationService extends Service { 7 @tracked notifications = []; 8 9 @action 10 add(message, type = 'info', duration = 5000) { 11 const id = Date.now() + Math.random(); 12 const notification = { id, message, type }; 13 14 this.notifications = [...this.notifications, notification]; 15 16 if (duration > 0) { 17 setTimeout(() => this.remove(id), duration); 18 } 19 20 return id; 21 } 22 23 @action 24 remove(id) { 25 this.notifications = this.notifications.filter(n => n.id !== id); 26 } 27 28 @action 29 success(message, duration) { 30 return this.add(message, 'success', duration); 31 } 32 33 @action 34 error(message, duration = 10000) { 35 return this.add(message, 'error', duration); 36 } 37 38 @action 39 clear() { 40 this.notifications = []; 41 } 42}

Custom Modifiers

javascript
1// app/modifiers/click-outside.js 2import { modifier } from 'ember-modifier'; 3 4export default modifier((element, [callback]) => { 5 function handleClick(event) { 6 if (!element.contains(event.target)) { 7 callback(event); 8 } 9 } 10 11 document.addEventListener('click', handleClick, true); 12 13 return () => { 14 document.removeEventListener('click', handleClick, true); 15 }; 16});
handlebars
1{{! Usage }} 2<div {{click-outside this.closeDropdown}} class="dropdown"> 3 {{! dropdown content }} 4</div>

Routing

Route Definitions

javascript
1// app/router.js 2import EmberRouter from '@ember/routing/router'; 3import config from 'my-app/config/environment'; 4 5export default class Router extends EmberRouter { 6 location = config.locationType; 7 rootURL = config.rootURL; 8} 9 10Router.map(function () { 11 this.route('dashboard', { path: '/' }); 12 13 this.route('users', function () { 14 this.route('index', { path: '/' }); 15 this.route('new'); 16 this.route('user', { path: '/:user_id' }, function () { 17 this.route('edit'); 18 this.route('settings'); 19 }); 20 }); 21 22 this.route('not-found', { path: '/*path' }); 23});

Route Class

javascript
1// app/routes/users/user.js 2import Route from '@ember/routing/route'; 3import { inject as service } from '@ember/service'; 4 5export default class UsersUserRoute extends Route { 6 @service store; 7 @service router; 8 9 async model(params) { 10 try { 11 return await this.store.findRecord('user', params.user_id, { 12 include: 'profile,settings' 13 }); 14 } catch (error) { 15 if (error.errors?.[0]?.status === '404') { 16 this.router.transitionTo('not-found'); 17 } 18 throw error; 19 } 20 } 21 22 // Redirect if user doesn't have permission 23 afterModel(model) { 24 if (!this.currentUser.canViewUser(model)) { 25 this.router.transitionTo('dashboard'); 26 } 27 } 28 29 // Reset controller state on exit 30 resetController(controller, isExiting) { 31 if (isExiting) { 32 controller.setProperties({ 33 queryParams: {}, 34 isEditing: false 35 }); 36 } 37 } 38}

Loading and Error States

javascript
1// app/routes/users/user/loading.js 2import Route from '@ember/routing/route'; 3 4export default class UsersUserLoadingRoute extends Route {}
handlebars
1{{! app/templates/users/user/loading.hbs }} 2<div class="loading-spinner"> 3 <p>Loading user...</p> 4</div>

Ember Data

Models

javascript
1// app/models/user.js 2import Model, { attr, hasMany, belongsTo } from '@ember-data/model'; 3 4export default class UserModel extends Model { 5 @attr('string') name; 6 @attr('string') email; 7 @attr('date') createdAt; 8 @attr('boolean', { defaultValue: true }) isActive; 9 @attr('number') loginCount; 10 11 @belongsTo('profile', { async: true, inverse: 'user' }) profile; 12 @hasMany('post', { async: true, inverse: 'author' }) posts; 13 14 // Computed properties still work but use native getters 15 get displayName() { 16 return this.name || this.email?.split('@')[0] || 'Anonymous'; 17 } 18 19 get isNewUser() { 20 const daysSinceCreation = (Date.now() - this.createdAt) / (1000 * 60 * 60 * 24); 21 return daysSinceCreation < 7; 22 } 23}

Custom Adapters

javascript
1// app/adapters/application.js 2import JSONAPIAdapter from '@ember-data/adapter/json-api'; 3import { inject as service } from '@ember/service'; 4 5export default class ApplicationAdapter extends JSONAPIAdapter { 6 @service session; 7 8 host = 'https://api.example.com'; 9 namespace = 'v1'; 10 11 get headers() { 12 const headers = {}; 13 14 if (this.session.isAuthenticated) { 15 headers['Authorization'] = `Bearer ${this.session.data.authenticated.token}`; 16 } 17 18 return headers; 19 } 20 21 handleResponse(status, headers, payload, requestData) { 22 if (status === 401) { 23 this.session.invalidate(); 24 } 25 26 return super.handleResponse(status, headers, payload, requestData); 27 } 28}

Custom Serializers

javascript
1// app/serializers/application.js 2import JSONAPISerializer from '@ember-data/serializer/json-api'; 3 4export default class ApplicationSerializer extends JSONAPISerializer { 5 // Normalize date strings to Date objects 6 normalizeDateFields(hash) { 7 const dateFields = ['createdAt', 'updatedAt', 'publishedAt']; 8 9 dateFields.forEach(field => { 10 if (hash[field]) { 11 hash[field] = new Date(hash[field]); 12 } 13 }); 14 15 return hash; 16 } 17 18 normalize(modelClass, resourceHash) { 19 this.normalizeDateFields(resourceHash.attributes || {}); 20 return super.normalize(modelClass, resourceHash); 21 } 22}

Testing

Component Integration Tests

javascript
1// tests/integration/components/user-profile-test.js 2import { module, test } from 'qunit'; 3import { setupRenderingTest } from 'ember-qunit'; 4import { render, click, fillIn } from '@ember/test-helpers'; 5import { hbs } from 'ember-cli-htmlbars'; 6 7module('Integration | Component | user-profile', function (hooks) { 8 setupRenderingTest(hooks); 9 10 test('it displays user information', async function (assert) { 11 this.set('user', { 12 name: 'Jane Doe', 13 email: 'jane@example.com' 14 }); 15 16 await render(hbs`<UserProfile @user={{this.user}} />`); 17 18 assert.dom('h2').hasText('Jane Doe'); 19 assert.dom('p').hasText('jane@example.com'); 20 }); 21 22 test('it allows editing when canEdit is true', async function (assert) { 23 this.owner.lookup('service:current-user').canEdit = true; 24 this.set('user', { 25 name: 'Jane Doe', 26 email: 'jane@example.com' 27 }); 28 this.set('onSave', () => {}); 29 30 await render(hbs` 31 <UserProfile @user={{this.user}} @onSave={{this.onSave}} /> 32 `); 33 34 await click('button:contains("Edit Profile")'); 35 36 assert.dom('form').exists(); 37 assert.dom('input[type="text"]').hasValue('Jane Doe'); 38 39 await fillIn('input[type="text"]', 'Jane Smith'); 40 await click('button[type="submit"]'); 41 42 assert.dom('form').doesNotExist(); 43 }); 44});

Route/Acceptance Tests

javascript
1// tests/acceptance/user-flow-test.js 2import { module, test } from 'qunit'; 3import { visit, currentURL, click, fillIn } from '@ember/test-helpers'; 4import { setupApplicationTest } from 'ember-qunit'; 5import { setupMirage } from 'ember-cli-mirage/test-support'; 6 7module('Acceptance | user flow', function (hooks) { 8 setupApplicationTest(hooks); 9 setupMirage(hooks); 10 11 test('visiting /users and creating a new user', async function (assert) { 12 await visit('/users'); 13 14 assert.strictEqual(currentURL(), '/users'); 15 assert.dom('h1').hasText('Users'); 16 17 await click('a:contains("New User")'); 18 assert.strictEqual(currentURL(), '/users/new'); 19 20 await fillIn('[data-test-name-input]', 'John Doe'); 21 await fillIn('[data-test-email-input]', 'john@example.com'); 22 await click('[data-test-submit]'); 23 24 assert.strictEqual(currentURL(), '/users/1'); 25 assert.dom('[data-test-user-name]').hasText('John Doe'); 26 }); 27});

Performance Optimization

See references/performance.md for comprehensive optimization strategies.

Quick Reference

ProblemSolution
Unnecessary component re-rendersUse @cached for expensive getters
Large listsUse ember-collection or virtual scrolling
Slow Ember Data queriesOptimize includes, use custom serializers
Bundle sizeUse route-based code splitting, lazy engines
Memory leaksProperly clean up in willDestroy, cancel timers

Critical Anti-patterns

javascript
1// ❌ Mutating tracked properties directly 2this.items.push(newItem); // Won't trigger reactivity 3 4// ✅ Replace the entire array 5this.items = [...this.items, newItem]; 6 7// ❌ Creating new functions in templates 8{{on "click" (fn this.handleClick item)}} 9 10// ✅ Use actions or stable references 11@action handleItemClick(item) { /* ... */ } 12{{on "click" (fn this.handleItemClick item)}} 13 14// ❌ Not using @cached for expensive computations 15get expensiveComputation() { 16 return this.data.filter(/* complex logic */); 17} 18 19// ✅ Use @cached 20@cached 21get expensiveComputation() { 22 return this.data.filter(/* complex logic */); 23}

Project Structure

app/
├── components/           # Glimmer components
│   └── user-profile/
│       ├── component.js
│       ├── index.hbs
│       └── styles.css
├── controllers/          # Controllers (use sparingly in Octane)
├── helpers/             # Template helpers
├── modifiers/           # Custom modifiers
├── models/              # Ember Data models
├── routes/              # Route classes
├── services/            # Services
├── templates/           # Route templates
├── adapters/            # Ember Data adapters
├── serializers/         # Ember Data serializers
├── styles/              # Global styles
└── app.js

tests/
├── integration/         # Component tests
├── unit/               # Unit tests (models, services, etc.)
└── acceptance/         # Full application tests

Tooling Recommendations

CategoryToolNotes
CLIember-cliOfficial tooling
TestingQUnit + ember-qunitBuilt-in, well integrated
LintingESLint + ember-template-lintCatch template issues
FormattingPrettierUse with ember-template-lint
Mockingember-cli-mirageAPI mocking for tests
State managementServices + trackedBuilt-in, no extra deps
HTTPfetch or ember-fetchNative or polyfilled

Common Patterns

Form Handling with Validation

javascript
1// app/components/registration-form.js 2import Component from '@glimmer/component'; 3import { tracked } from '@glimmer/tracking'; 4import { action } from '@ember/object'; 5import { inject as service } from '@ember/service'; 6 7export default class RegistrationFormComponent extends Component { 8 @service notification; 9 10 @tracked email = ''; 11 @tracked password = ''; 12 @tracked confirmPassword = ''; 13 @tracked errors = {}; 14 @tracked isSubmitting = false; 15 16 get isValid() { 17 return ( 18 this.email && 19 this.password.length >= 8 && 20 this.password === this.confirmPassword && 21 Object.keys(this.errors).length === 0 22 ); 23 } 24 25 @action 26 updateEmail(event) { 27 this.email = event.target.value; 28 this.validateEmail(); 29 } 30 31 @action 32 updatePassword(event) { 33 this.password = event.target.value; 34 this.validatePassword(); 35 } 36 37 @action 38 updateConfirmPassword(event) { 39 this.confirmPassword = event.target.value; 40 this.validateConfirmPassword(); 41 } 42 43 validateEmail() { 44 const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; 45 46 if (!this.email) { 47 this.errors = { ...this.errors, email: 'Email is required' }; 48 } else if (!emailRegex.test(this.email)) { 49 this.errors = { ...this.errors, email: 'Invalid email format' }; 50 } else { 51 const { email, ...rest } = this.errors; 52 this.errors = rest; 53 } 54 } 55 56 validatePassword() { 57 if (this.password.length < 8) { 58 this.errors = { ...this.errors, password: 'Password must be at least 8 characters' }; 59 } else { 60 const { password, ...rest } = this.errors; 61 this.errors = rest; 62 } 63 64 // Re-validate confirm password if it's filled 65 if (this.confirmPassword) { 66 this.validateConfirmPassword(); 67 } 68 } 69 70 validateConfirmPassword() { 71 if (this.password !== this.confirmPassword) { 72 this.errors = { ...this.errors, confirmPassword: 'Passwords do not match' }; 73 } else { 74 const { confirmPassword, ...rest } = this.errors; 75 this.errors = rest; 76 } 77 } 78 79 @action 80 async submit(event) { 81 event.preventDefault(); 82 83 if (!this.isValid) return; 84 85 this.isSubmitting = true; 86 87 try { 88 await this.args.onSubmit({ 89 email: this.email, 90 password: this.password 91 }); 92 93 this.notification.success('Registration successful!'); 94 } catch (error) { 95 this.notification.error(error.message || 'Registration failed'); 96 } finally { 97 this.isSubmitting = false; 98 } 99 } 100}

Infinite Scroll with Modifier

javascript
1// app/modifiers/infinite-scroll.js 2import { modifier } from 'ember-modifier'; 3 4export default modifier((element, [callback], { threshold = 200 }) => { 5 let isLoading = false; 6 7 function handleScroll() { 8 if (isLoading) return; 9 10 const { scrollTop, scrollHeight, clientHeight } = element; 11 const distanceFromBottom = scrollHeight - (scrollTop + clientHeight); 12 13 if (distanceFromBottom < threshold) { 14 isLoading = true; 15 callback().finally(() => { 16 isLoading = false; 17 }); 18 } 19 } 20 21 element.addEventListener('scroll', handleScroll, { passive: true }); 22 23 return () => { 24 element.removeEventListener('scroll', handleScroll); 25 }; 26});

TypeScript Support

Ember has strong TypeScript support. Enable it with:

bash
1ember install ember-cli-typescript
typescript
1// app/components/user-profile.ts 2import Component from '@glimmer/component'; 3import { tracked } from '@glimmer/tracking'; 4import { action } from '@ember/object'; 5import type { TOC } from '@ember/component/template-only'; 6 7interface UserProfileArgs { 8 user: { 9 name: string; 10 email: string; 11 avatarUrl?: string; 12 }; 13 onSave: (data: UserData) => Promise<void>; 14 canEdit?: boolean; 15} 16 17interface UserData { 18 name: string; 19 email: string; 20} 21 22export default class UserProfileComponent extends Component<UserProfileArgs> { 23 @tracked isEditing = false; 24 @tracked formData: UserData | null = null; 25 26 @action 27 async saveUser(event: SubmitEvent): Promise<void> { 28 event.preventDefault(); 29 30 if (!this.formData) return; 31 32 await this.args.onSave(this.formData); 33 this.isEditing = false; 34 } 35} 36 37// Template-only component signature 38export interface GreetingSignature { 39 Element: HTMLDivElement; 40 Args: { 41 name: string; 42 }; 43} 44 45const Greeting: TOC<GreetingSignature> = <template> 46 <div ...attributes>Hello {{@name}}!</div> 47</template>; 48 49export default Greeting;

Remember: Always Use context7 MCP First!

Before implementing any Ember code, query the context7 MCP for relevant project documentation. Context7 provides project-specific guidelines that always supersede these general best practices.

Quick context7 Query Guide

Before writing components:

  • Query: "ember component patterns", "glimmer component", "component architecture"

Before routing work:

  • Query: "ember routing", "route patterns", "navigation"

Before Ember Data:

  • Query: "ember data models", "api integration", "data layer"

Before tests:

  • Query: "ember testing", "test patterns", "test requirements"

When editing existing code:

  • Query the specific feature or pattern you're working with

The context7 MCP is your source of truth for this project's Ember conventions.

Related Skills

Looking for an alternative to javascript-ember or building a Categories.community AI Agent? Explore these related open-source MCP Servers.

View All

widget-generator

Logo of f
f

widget-generator is an open-source AI agent skill for creating widget plugins that are injected into prompt feeds on prompts.chat. It supports two rendering modes: standard prompt widgets using default PromptCard styling and custom render widgets built as full React components.

149.6k
0
Design

chat-sdk

Logo of lobehub
lobehub

chat-sdk is a unified TypeScript SDK for building chat bots across multiple platforms, providing a single interface for deploying bot logic.

73.0k
0
Communication

zustand

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
Communication

data-fetching

Logo of lobehub
lobehub

The ultimate space for work and life — to find, build, and collaborate with agent teammates that grow with you. We are taking agent harness to the next level — enabling multi-agent collaboration, effortless agent team design, and introducing agents as the unit of work interaction.

72.8k
0
Communication