discourse-frontend-conventions

Enforces Discourse frontend conventions for class members, comments, and template invocations.

47.8k|9.0k|Updated Jan 12, 2013
One-click install
npx skills add https://github.com/discourse/discourse --skill discourse-frontend-conventions
Or copy as Structured Prompt for Agent
Please help me install this Agent Skill.
Skill: discourse-frontend-conventions
Source: https://github.com/discourse/discourse/tree/main/.skills/discourse-frontend-conventions
Command: npx skills add https://github.com/discourse/discourse --skill discourse-frontend-conventions

SYSTEM DOCUMENTATION & REQUIREMENTS

What problem does it solve?

Discourse's linter enforces only part of the frontend style rules, leaving private-symbol naming, class member ordering, comment quality, and template invocation ordering inconsistent across JavaScript, TypeScript, and Glimmer code in core, plugins, and themes.

Core Features & Use Cases

  • Private-symbol pattern: Decides between #, unprefixed, and _ members based on decorators, template binding, and cross-class access scope.
  • Member and invocation ordering: Orders class members beyond the lint buckets and groups attributes, @arguments, and modifiers on component invocations in .gjs/.gts files.
  • Comment necessity gate: Deletes redundant or drifting comments, fixes blank lines before documented fields, and avoids in-template comments that break ember-eslint-parser scope analysis.
  • Use Case: When preparing a commit that adds a new Glimmer component, run through the steps to place members correctly, rename mis-prefixed privates, prune comments, and finish with bin/lint --fix.

Quick Start

Review the frontend files I just changed and apply the Discourse conventions for private symbols, member ordering, comments, and invocation ordering, then run bin/lint --fix.

Frequently Asked Questions about discourse-frontend-conventions

High-intent search queries and answers about installing and using this skill.

FAQPage Schema
How do I order class members in Discourse components?

Follow the lint-enforced top-level buckets first, then order methods as getters, public methods, and private methods. Within each bucket, cluster by purpose and sort alphabetically, with dependency order as a hard constraint for property initializers.

When should I use # private fields vs underscore prefix in JavaScript classes?

Use `#` for members accessed only within their own class without decorators, and `_` only when a decorator like `@tracked` or `@action` is needed but the member is not template-bound. Members called from templates or other classes must be unprefixed public API.

Why does eslint report unused vars for imports used in my Glimmer template?

A `{{! }}` comment inside a `<template>` containing backticks, angle brackets, attribute-like snippets, or pipes silently breaks ember-eslint-parser scope analysis. Reword the comment in plain prose so template scope is detected again.

How should attributes and modifiers be ordered on Glimmer component invocations?

Group plain attributes first, then `@arguments`, then modifiers last, never interleaving kinds. Keep `...attributes` in its original position within the attributes group because its placement controls override precedence.

Does this apply to existing files or only new code?

New files are audited in full, while existing files only have the added or changed lines fixed to avoid noisy diffs. Use git status and git diff to determine scope, unless explicitly asked to revamp the whole file.