From 16bbed37b2b50277b92047c0429dd730cc81c848 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Mon, 22 Jun 2026 16:41:05 +0000
Subject: [PATCH 1/2] Add RFC 1188: Deprecate Loose Mode and HBS File Authoring
---
...-deprecate-loose-mode-and-hbs-authoring.md | 378 ++++++++++++++++++
1 file changed, 378 insertions(+)
create mode 100644 text/1188-deprecate-loose-mode-and-hbs-authoring.md
diff --git a/text/1188-deprecate-loose-mode-and-hbs-authoring.md b/text/1188-deprecate-loose-mode-and-hbs-authoring.md
new file mode 100644
index 0000000000..cfd37beeed
--- /dev/null
+++ b/text/1188-deprecate-loose-mode-and-hbs-authoring.md
@@ -0,0 +1,378 @@
+---
+stage: accepted
+start-date: 2026-06-22T00:00:00.000Z
+release-date:
+release-versions:
+teams:
+ - framework
+ - learning
+ - cli
+ - typescript
+prs:
+ accepted: # update this to the PR that you propose your RFC in
+project-link:
+---
+
+# Deprecate Loose Mode and HBS File Authoring
+
+## Summary
+
+Deprecate loose mode Handlebars templates and authoring components and route
+templates in `.hbs` files, in favor of the strict mode authoring experience
+provided by `.gjs` and `.gts` template tag files. This is the natural
+conclusion of [RFC #0496 (Handlebars Strict Mode)][rfc-0496],
+[RFC #0779 (First-Class Component Templates)][rfc-0779], and
+[RFC #1046 (Template Tag in Routes)][rfc-1046] all reaching the
+[recommended][stages] stage.
+
+[rfc-0496]: https://github.com/emberjs/rfcs/blob/master/text/0496-handlebars-strict-mode.md
+[rfc-0779]: https://github.com/emberjs/rfcs/blob/master/text/0779-first-class-component-templates.md
+[rfc-1046]: https://github.com/emberjs/rfcs/blob/master/text/1046-template-tag-in-routes.md
+[stages]: https://github.com/emberjs/rfcs/blob/master/README.md#stages
+
+## Motivation
+
+Ember's template language has two modes:
+
+- **Loose mode** (also called non-strict or classic mode): the default behavior
+ used by standalone `.hbs` files. It resolves components, helpers, and
+ modifiers dynamically by name at runtime using the resolver. It supports
+ implicit `this` lookup, implicit globals, and dynamic resolution.
+
+- **Strict mode**: the semantics defined in [RFC #0496][rfc-0496], where every
+ value in a template must be explicitly in scope. There are no implicit globals,
+ no implicit `this` fallback, no dynamic resolution, and no `eval`-like
+ features (e.g., partials, which were deprecated separately). Strict mode is
+ the only mode available in `.gjs` and `.gts` template tag files.
+
+### The Recommended Path Is Already Clear
+
+All three foundation RFCs have progressed to recommended:
+
+- [RFC #0496][rfc-0496] made strict mode semantics the recommended way to write
+ templates.
+- [RFC #0779][rfc-0779] made `.gjs`/`.gts` template tag files—which are always
+ strict mode—the recommended authoring format for components.
+- [RFC #1046][rfc-1046] extended template tag authoring to route templates,
+ completing coverage of every template in an Ember application.
+
+Additionally, [RFC #0995 (Deprecate Non-Co-located Components)][rfc-0995]
+already deprecated the classic separate-directory and pods component layouts,
+leaving only co-located `.hbs`+`.js`/`.ts` pairs and `.gjs`/`.gts` files as
+supported component authoring formats.
+
+[rfc-0995]: https://github.com/emberjs/rfcs/blob/master/text/0995-deprecate-non-colocated-components.md
+
+The ecosystem has converged. New Ember apps generated with the current blueprint
+default to Embroider+Vite, which has first-class `.gjs`/`.gts` support. The
+community is actively producing codemods, lint rules, and IDE tooling for
+`.gjs`/`.gts`. Maintaining loose mode indefinitely imposes ongoing costs:
+
+- **Implementation cost**: the resolver logic, implicit lookup behavior, and
+ loose mode compilation paths must be maintained alongside the stricter,
+ simpler strict mode path.
+
+- **Teaching cost**: new Ember users encounter two incompatible template
+ authoring worlds—global-resolution `.hbs` files and import-based `.gjs`
+ files—which creates confusion about which rules apply where.
+
+- **Tooling cost**: language servers, linters, and formatters must handle two
+ distinct template semantics. Strict mode has richer static analysis
+ possibilities (e.g., "go to definition" for components) that cannot be
+ offered in loose mode.
+
+- **Performance cost**: loose mode requires a live resolver at runtime to
+ dynamically look up components, helpers, and modifiers by name. Strict mode
+ can be fully resolved at build time.
+
+### What Is Being Deprecated
+
+This RFC deprecates:
+
+1. **Loose mode compilation and runtime resolution** — the mechanism by which
+ `.hbs` templates resolve component, helper, and modifier names through
+ implicit global lookup and `this` fallback.
+
+2. **`.hbs` files for component templates** — co-located `.hbs` files paired
+ with a `.js` or `.ts` backing class (e.g., `my-component.hbs` alongside
+ `my-component.js`), as well as template-only `.hbs` files.
+
+3. **`.hbs` files for route templates** — files under `app/templates/` that are
+ used as route-level templates (e.g., `app/templates/application.hbs`).
+
+This RFC does **not** deprecate:
+
+- The `.hbs` file extension itself in other contexts (e.g., inline test
+ templates using `hbs` tagged template literals in test files remain supported
+ and are a separate concern).
+- The underlying Glimmer VM; only the loose mode compilation path on top of it
+ is deprecated.
+- Any `.gjs`/`.gts` behavior; those files are the recommended replacement.
+
+## Transition Path
+
+### Components
+
+**Before (co-located hbs + js):**
+```js
+// app/components/my-greeting.js
+import Component from '@glimmer/component';
+
+export default class MyGreeting extends Component {}
+```
+
+```hbs
+{{! app/components/my-greeting.hbs }}
+
Hello, {{@name}}!
+```
+
+**After (template tag gjs):**
+```gjs
+// app/components/my-greeting.gjs
+import Component from '@glimmer/component';
+
+export default class MyGreeting extends Component {
+
+ Hello, {{@name}}!
+
+}
+```
+
+**Before (template-only hbs component):**
+```hbs
+{{! app/components/my-greeting.hbs }}
+Hello, {{@name}}!
+```
+
+**After (template-only gjs component):**
+```gjs
+{{! app/components/my-greeting.gjs }}
+
+ Hello, {{@name}}!
+
+```
+
+### Route Templates
+
+**Before (route hbs template):**
+```hbs
+{{! app/templates/posts.hbs }}
+Posts
+{{#each @model as |post|}}
+
+{{/each}}
+```
+
+**After (route gjs template):**
+```gjs
+// app/templates/posts.gjs
+import Post from 'my-app/components/post';
+
+
+ Posts
+ {{#each @model as |post|}}
+
+ {{/each}}
+
+```
+
+Note that in the `.gjs` route template, components must be explicitly imported.
+Embroider provides a codemod that can automatically add the necessary imports
+when migrating from loose mode templates.
+
+### Deprecation Warnings
+
+A runtime deprecation warning should be emitted when a loose mode template is
+compiled and invoked. The deprecation message should link to this RFC and to the
+[deprecation guide][deprecation-guide].
+
+[deprecation-guide]: https://deprecations.emberjs.com/
+
+The deprecation ID will be `ember.loose-mode-templates`.
+
+For co-located `.hbs` component templates, the warning should identify the
+specific component file that triggered it (e.g.,
+`app/components/my-greeting.hbs`).
+
+For route-level `.hbs` templates, the warning should identify the route and
+template file.
+
+### Codemods
+
+The [ember-codemod-template-tag][codemod] package can automatically convert
+most `.hbs` component and route template files to `.gjs`/`.gts`. It handles:
+
+- Merging a co-located `.hbs` + `.js`/`.ts` pair into a single `.gjs`/`.gts` file.
+- Converting template-only `.hbs` components to template-only `.gjs` files.
+- Converting route templates from `.hbs` to `.gjs`.
+- Adding explicit imports for components, helpers, and modifiers that were
+ previously resolved by name.
+
+[codemod]: https://github.com/IgnaceMaes/ember-codemod-template-tag
+
+Embroider also provides infrastructure for generating the necessary imports
+during migration as part of its compatibility layer.
+
+### Lint Rules
+
+#### ember-template-lint
+
+A new `no-loose-mode-templates` rule (or equivalent) should be added to
+[ember-template-lint][etl] that reports any `.hbs` file used as a component or
+route template as a warning (later, an error). This gives projects a lint-time
+signal before the deprecation becomes a runtime error in a future major release.
+
+[etl]: https://github.com/ember-template-lint/ember-template-lint
+
+#### eslint-plugin-ember
+
+The [eslint-plugin-ember][epe] `no-classic-components` rule (or an analogous
+rule) should be updated or supplemented to flag co-located `.hbs` files
+alongside their `.js`/`.ts` backing classes, encouraging migration to
+`.gjs`/`.gts`.
+
+[epe]: https://github.com/ember-cli/eslint-plugin-ember
+
+### Blueprints
+
+All relevant `ember-cli` blueprints should be updated to generate `.gjs` or
+`.gts` files by default:
+
+- `ember generate component` — generate `component.gjs`/`component.gts` instead
+ of separate `component.hbs` + `component.js`/`component.ts` files.
+- `ember generate route` — generate `route.gjs`/`route.gts` for the route
+ template instead of a standalone `.hbs` file.
+
+These changes follow the blueprints update already made in
+[RFC #1055 (Vanilla Prettier Setup in Blueprints)][rfc-1055] and related
+blueprint work.
+
+[rfc-1055]: https://github.com/emberjs/rfcs/blob/master/text/1055-vanilla-prettier-setup-in-blueprints.md
+
+### Addon Ecosystem
+
+Addons that ship `.hbs` component templates should migrate to one of:
+
+- **V2 addon format** with `.gjs`/`.gts` files (preferred, per
+ [RFC #0507][rfc-0507] and [RFC #0985][rfc-0985]).
+- Co-located `.hbs` files will continue to work through the deprecation
+ period (one full major version cycle) and will emit a deprecation warning
+ so addon authors are aware.
+
+[rfc-0507]: https://github.com/emberjs/rfcs/blob/master/text/0507-embroider-v2-package-format.md
+[rfc-0985]: https://github.com/emberjs/rfcs/blob/master/text/0985-v2-addon-by-default.md
+
+Addon authors should update their published packages before the loose mode
+removal in the next Ember major version.
+
+### Timeline
+
+- **Deprecation period**: loose mode templates emit a deprecation warning
+ starting in the Ember minor release where this RFC is implemented.
+- **Removal**: loose mode template support will be removed in the next Ember
+ major version following the deprecation release, consistent with Ember's
+ standard deprecation policy.
+
+## How We Teach This
+
+### Guides
+
+The Ember Guides should be updated to exclusively use `.gjs`/`.gts` examples
+in all component and route template sections. References to `.hbs` file
+authoring should be moved to a "migrating from classic templates" section, not
+featured in the primary learning path.
+
+The tutorial should already be using template tag syntax; if it isn't, this
+deprecation is a forcing function to do so.
+
+### Deprecation Guide
+
+A deprecation guide should be published at
+[deprecations.emberjs.com](https://deprecations.emberjs.com/) with the
+deprecation ID `ember.loose-mode-templates`. It should cover:
+
+- An explanation of loose mode and why it is being deprecated.
+- Step-by-step migration instructions for:
+ - Co-located hbs + js/ts component pairs.
+ - Template-only hbs components.
+ - Route-level hbs templates.
+- How to run the codemod.
+- How to silence the deprecation while migrating (using
+ `@ember/optional-features` or a similar mechanism if one is provided).
+
+### API Docs
+
+API documentation that references loose mode resolution, the classic resolver,
+or `.hbs` template authoring should be updated to link to the deprecation guide
+and the template tag authoring docs.
+
+### Messaging to Existing Users
+
+When the deprecation is introduced:
+
+- A blog post should announce the deprecation, explain the rationale, link to
+ the deprecation guide, and highlight codemod tooling.
+- The Ember CLI `ember generate` command should emit a one-time notice directing
+ users to migrate existing `.hbs` files when it detects them in a project.
+
+## Drawbacks
+
+- **Ecosystem churn**: many addons and apps still use `.hbs` files. The migration
+ requires running a codemod or manually converting each file. For large
+ applications with hundreds of templates, this can be a significant one-time
+ investment.
+
+- **Addon consumers**: end users of addons that have not migrated will see
+ deprecation warnings that they cannot suppress without forking the addon or
+ waiting for the addon author to publish an update.
+
+- **`.hbs`-only workflows**: some teams use external templating tools or
+ workflows that specifically target `.hbs` files. Those workflows will need to
+ adapt.
+
+- **Incremental adoption**: projects that cannot immediately migrate all files
+ will need to live with deprecation warnings for a potentially extended period.
+
+## Alternatives
+
+### Keep Loose Mode Indefinitely
+
+We could accept that loose mode is a permanent part of Ember and never deprecate
+it. This avoids migration burden but accepts all the ongoing costs described in
+the Motivation section: the implementation, teaching, tooling, and performance
+costs of maintaining two template systems in perpetuity.
+
+### Deprecate Loose Mode Semantics Without Deprecating `.hbs` Files
+
+We could separately deprecate the loose mode *behaviors* (implicit globals,
+implicit `this` fallback) while still allowing `.hbs` files that have been
+compiled with explicit strict mode flags. In practice, all `.hbs` files in Ember
+apps currently use loose mode, and the ergonomics of opting into strict mode in
+a standalone `.hbs` file are poor. This alternative would add complexity without
+a clear benefit over moving entirely to `.gjs`/`.gts`, which provide strict mode
+by design.
+
+### Require Strict Mode in `.hbs` Files
+
+We could require `.hbs` files to opt into strict mode rather than deprecating
+them entirely. This is a less-breaking path but perpetuates the existence of a
+second template format alongside `.gjs`/`.gts`, splitting the ecosystem without
+delivering the simplification we are aiming for.
+
+## Unresolved questions
+
+- Should there be an opt-out mechanism (e.g., an optional feature flag) to
+ silence the deprecation warning globally for projects that need more time to
+ migrate? Or should the deprecation always emit to ensure visibility?
+
+- What is the minimum Ember version at which this deprecation can land, given
+ that RFC #1046 (template tag in routes) landed in Ember 6.3? Should this
+ deprecation target Ember 6.x or wait for 7.x?
+
+- Should `.hbs` files inside `tests/` (e.g., integration test helper templates
+ authored with the `hbs` tagged template literal) be in scope for this
+ deprecation, or handled in a separate RFC?
+
+- How should Ember Engines handle this transition? Engines may have their own
+ template namespaces and resolver configurations; the deprecation messaging
+ should address this.
From 32902bd9abf44b5c10e0cbc055dd4b0d97416d00 Mon Sep 17 00:00:00 2001
From: Katie Gengler
Date: Mon, 22 Jun 2026 12:44:23 -0400
Subject: [PATCH 2/2] Warn
---
text/1188-deprecate-loose-mode-and-hbs-authoring.md | 2 ++
1 file changed, 2 insertions(+)
diff --git a/text/1188-deprecate-loose-mode-and-hbs-authoring.md b/text/1188-deprecate-loose-mode-and-hbs-authoring.md
index cfd37beeed..f0a3016952 100644
--- a/text/1188-deprecate-loose-mode-and-hbs-authoring.md
+++ b/text/1188-deprecate-loose-mode-and-hbs-authoring.md
@@ -15,6 +15,8 @@ project-link:
# Deprecate Loose Mode and HBS File Authoring
+⚠️ Placeholder RFC generated with copilot, probably don't bother reading yet.
+
## Summary
Deprecate loose mode Handlebars templates and authoring components and route