| stage | start-date | release-date | release-versions | teams | prs | project-link | suite | |||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
accepted |
2026-01-12 00:00:00 UTC |
|
|
This RFC proposes standardizing and supporting two new opt-in modes when generating apps from the Ember app blueprint (@ember/app-blueprint): --no-compat and --minimal.
--no-compat generates an Ember app that intentionally omits legacy compatibility layers needed for older addon formats and older build/boot conventions. It prioritizes modern ESM tooling, significantly faster installs/builds/boot, and smoother integration with the broader Vite/ESM ecosystem.
--minimal builds on --no-compat and additionally strips “project hygiene” tooling (linting/formatting/testing scaffolding), producing a small app shell well-suited for demos and for embedding Ember in other repositories and multi-framework environments (e.g. icon libraries, Vite plugin repos, Astro integrations).
This RFC also documents the project intent to make “no-compat” the default for newly generated apps in a future major step, after ecosystem readiness and a clear transition path.
Ember’s “new app” experience increasingly targets modern JavaScript workflows: ESM-first packages, Vite-powered builds, and native browser capabilities. However, today’s default generated app must carry a set of compatibility layers to support:
- older addon formats (notably v1 addons)
- legacy build/boot wiring
- legacy templating and HTML “content-for” integration points
- Node-side configuration files and conventions
Those layers are valuable for upgrading existing apps and for broad compatibility, but they impose real costs for brand-new apps:
- Slower installs and heavier dependency trees (e.g.
ember-cliand its transitive deps) - Slower build and boot, especially in large apps
- Friction integrating Ember into “ESM-native” ecosystems (Vite SSR, Astro, etc.)
We need first-class support for two distinct “new app” use-cases:
-
Modern Ember apps that do not need legacy compatibility
- Apps that do not depend on v1 addons
- Apps that do not need HTML
content-for - Apps that want ESM-first conventions like
"type": "module"
-
Ultra-light Ember shells for demos and integration
- Minimal “it boots” projects for embedding Ember into other repos
- Multi-framework demo matrices (React/Vue/Svelte/Ember) where the repo uses a shared test harness and linting strategy
- Integration spikes in other ecosystems (e.g. Iconify, Vite plugin repos, Astro integrations), where the generated app is a fixture rather than a long-lived production app
This RFC formalizes the public API surface introduced by these flags and sets expectations around support, documentation, and the migration path toward a future where “no-compat” can become the default.
This RFC covers the behavior and support commitments for two generator flags on the Ember app blueprint, as implemented in ember-cli/ember-app-blueprint PR #49:
--no-compat--minimal
This RFC does not propose removing existing defaults today. The default remains the “compat” behavior. Instead, we:
- document what these modes generate
- define the supported/unsupported compatibility boundaries
- describe the intent and prerequisites for making “no-compat” the default in the future
- compat mode: the current default generated output which includes legacy compatibility support (notably
@embroider/compatand the conventions it enables). - no-compat mode: an opt-in generated output with the compatibility layer removed.
- minimal mode: an opt-in output built on no-compat, with additional removal of linting/formatting/testing scaffolding.
When generating a new app from @ember/app-blueprint, users may pass:
--no-compat(or equivalently--compat=false)--minimal
Precedence rules:
--minimalforcesno-compatbehavior.- If
--minimalis set, explicit--compat/--no-compatflags are ignored.
When --no-compat is enabled, the generated app prioritizes ESM and modern tooling and removes older compatibility features.
It includes the following high-level changes (as in PR #49):
-
ESM by default
package.jsonincludes"type": "module"- Adds an
importsmap for ergonomic subpath imports (e.g.#app/*,#config,#components/*).
-
Node tooling expectations updated
package.jsonsets a modern minimum Node version (in PR #49:engines.node: ">= 24").
-
Remove legacy compatibility dependencies
- Removes
@embroider/compatand related compat-only dependencies. - Removes
ember-clifrom the generated app’s devDependencies.- Tradeoff: the generated project no longer includes local scaffolding via
ember g. - Mitigation: users can still run generators via
pnpm dlx ember-cli g .../npx ember-cli g ...when needed.
- Tradeoff: the generated project no longer includes local scaffolding via
- Removes
-
Remove legacy features supported via compat
- No v1 addon compatibility (the generated app assumes v2+ addons).
- No
.hbsfile support for components/tests (template compilation is handled via modern compilation and template-tag usage). - No HTML
content-forusage in HTML entrypoints. - No Node-side
config/environment.js-style “node-land config”. Instead, config is generated as an ESM module (in PR #49:app/config/environment.ts) which reads fromimport.meta.env.
-
Vite integration changes
- Vite config conditionally omits classic support when in no-compat mode.
-
HTML entrypoints adjusted
index.htmlandtests/index.htmlare made conditional:- In compat mode, they continue using
{{content-for ...}}and Embroider virtual CSS/JS. - In no-compat mode, they instead directly link app styles and omit
content-forblocks.
- In compat mode, they continue using
-
Testing harness adjustments (when tests are present)
- The generated
config/environmentexports anenterTestMode()helper in non-minimal builds. tests/test-helpercallsenterTestMode()in no-compat builds.testemis configured to run fromdistin no-compat mode.
- The generated
--minimal is explicitly intended for demos and integration fixtures.
It includes everything from --no-compat and additionally:
-
Removes linting/formatting/testing scaffolding
- Strips common
lint:*andformatscripts. - Removes common lint/format/test devDependencies (eslint, prettier, ember-template-lint, qunit/testem, etc.).
- Strips common
-
Inverts a couple of defaults to reduce “stuff” in the minimal app
- Data layer defaults are more conservative:
- warp-drive becomes opt-in (
--warp-drive), rather than something you later remove.
- warp-drive becomes opt-in (
- “Welcome page” becomes opt-in (
--welcome).
- Data layer defaults are more conservative:
-
Produces a very small runtime surface
- Uses a strict application resolver oriented around explicit module discovery.
- Uses
import.meta.globto eagerly load key module categories.
In other words:
--minimalimplies--no-compat.--no-compatdoes not imply--minimal.
This RFC records the intent to eventually make “no-compat” the default for newly generated apps.
That shift is not proposed to happen immediately. It requires:
- Addon ecosystem readiness (v2+ coverage for common needs)
- Clear messaging for new users about what is/isn’t supported
- A clear story for teams that still need compatibility (explicit
--compatmode)
The long-term goal is:
- Default: no-compat (modern, faster, ESM-first)
- Opt-in: compat mode for projects that need legacy support as long as the slower/long-tail upgrade process from existing compat-using projects
- Opt-in: minimal mode for fixtures, demos, and embedded use-cases
--no-compatshould continue to ship with lint/test defaults unless explicitly requested otherwise.--minimalintentionally removes lint/test tooling, so no lint rules should be assumed.
No-compat does not inherently reduce debuggability, but removing legacy tooling changes how apps are booted and where configuration comes from. Documentation and troubleshooting guides should be updated accordingly.
The type=module default and the removal of legacy compat layers are aligned with Vite SSR and other ESM-first tooling. This RFC does not mandate a particular SSR solution but aims to remove common blockers.
--no-compat draws a bright line: v1 addons are not supported in the generated project.
This is both a feature (simpler, faster, modern) and a risk (some users will hit unsupported addons). The default remains compat for now to mitigate this.
ESM + imports maps can improve editor navigation (e.g. #app/*), but requires that tooling understands imports. The generated output should remain aligned with common TypeScript/JS tooling.
Because ember-cli is removed in --no-compat, generator UX changes. The recommended story is:
- use
npx ember-cli g .../pnpm dlx ember-cli g ...when you need scaffolding - keep the generated project itself light by default
We should teach this as a mode switch for the generated app, not as a new “framework feature”.
Key messaging:
--no-compatis for modern apps that don’t need legacy addon/build compatibility.--minimalis for fixtures, demos, and embedding Ember in other repos.
Concrete teaching changes:
-
Update the app blueprint README and Ember CLI docs to include an “Options” section describing:
- what each flag does
- what you give up
- who should use it
-
Provide a small decision table:
- “Are you new to Ember?” → start with default (no-compat)
- “Do you need v1 addons?” → default/compat
- “Are you building an ESM-first app or want the fastest build/boot?” →
--no-compat - “Are you embedding Ember into another repo?” →
--minimal
-
Provide a follow-up guide: “From minimal to production”
- how to add linting
- how to add testing
- how to add routing/UI/etc.
-
Call out the future direction explicitly:
- We intend “no-compat by default” in the future.
--minimalremains a niche but valuable tool for integration and demos.
- More public API surface area: every new flag is a support commitment.
- Potential confusion for new users:
- users may pick
--minimaland be surprised there are no tests/lints. - users may pick
--no-compatand be surprised a v1 addon doesn’t work.
- users may pick
- Ecosystem fragmentation risk: “compat” vs “no-compat” could lead to duplicated docs and support channels.
- Node version constraints: setting a high minimum Node version may be a barrier in some environments.
- Generator/scaffolding UX tradeoff: removing local
ember-climakes the generated app lighter, but removes the familiarember gworkflow unless invoked vianpx/pnpm dlx.
-
Separate blueprints instead of flags
- e.g. publish
@ember/app-blueprint-no-compatand@ember/app-blueprint-minimal. - Pros: fewer flags; clearer separation.
- Cons: more packages to discover/version; harder to share fixes across variants.
- e.g. publish
-
A single
--mode=flag- e.g.
--mode=compat|no-compat|minimal. - Pros: explicit, scales to new modes.
- Cons: breaks existing expectations; adds parsing/UX complexity.
- e.g.
-
Keep everything as-is
- Don’t add new modes.
- Cost: continued friction for modern apps and for embedding Ember in other ecosystems; continued overhead for users who don’t need legacy compatibility, will result in forks of blueprinting entirely.
-
Make no-compat the default immediately
- Pros: forces ecosystem to modernize.
- Cons: too disruptive; poor onboarding experience until addons/docs are ready.
n/a