diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 1614cb4d03a..30b5d4fbcde 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -278,7 +278,7 @@ jobs:
- name: Asset Processor Tests
if: matrix.build_type == 'frontend' && matrix.target == 'core'
- working-directory: app/assets/javascripts/asset-processor
+ working-directory: frontend/asset-processor
run: pnpm test
- name: Plugin QUnit
@@ -292,8 +292,8 @@ jobs:
- uses: actions/upload-artifact@v4
if: always() && matrix.build_type == 'frontend'
with:
- name: ember-exam-execution-${{ matrix.target }}-${{ matrix.browser }}-frontend-${{ hashFiles('./app/assets/javascripts/discourse/test-execution-*.json') }}
- path: ./app/assets/javascripts/discourse/test-execution-*.json
+ name: ember-exam-execution-${{ matrix.target }}-${{ matrix.browser }}-frontend-${{ hashFiles('./frontend/discourse/test-execution-*.json') }}
+ path: ./frontend/discourse/test-execution-*.json
- name: Ember Build for System Tests
if: matrix.build_type == 'system'
diff --git a/.pnpmfile.cjs b/.pnpmfile.cjs
index 4c2d77a81a3..f73af57e741 100644
--- a/.pnpmfile.cjs
+++ b/.pnpmfile.cjs
@@ -19,28 +19,23 @@ if (fs.existsSync(`${discourseRoot}/node_modules/.yarn-integrity`)) {
console.log("cleanup done");
}
-const oldAdminPath = `${discourseRoot}/app/assets/javascripts/admin`;
-if (fs.existsSync(`${oldAdminPath}/node_modules`)) {
+const oldFrontendPath = `app/assets/javascripts`;
+if (fs.existsSync(`${discourseRoot}/${oldFrontendPath}`)) {
console.log(
- "Detected old admin node_modules. Performing one-time cleanup..."
+ `[.pnpmfile.cjs] Detected old ${oldFrontendPath} directory. Cleaning up gitignored files...`
);
-
- fs.rmSync(`${oldAdminPath}/node_modules`, {
- recursive: true,
- });
+ execSync(`git clean -f -X ${oldFrontendPath}`, { cwd: discourseRoot });
const anyFiles = !!execSync(
- `find "${oldAdminPath}" -mindepth 1 -type f -print -quit`,
- { encoding: "utf8" }
+ `find "${oldFrontendPath}" -mindepth 1 -type f -print -quit`,
+ { encoding: "utf8", cwd: discourseRoot }
).trim();
if (!anyFiles) {
- fs.rmSync(oldAdminPath, {
+ fs.rmSync(oldFrontendPath, {
recursive: true,
});
}
-
- console.log("admin cleanup done");
}
const pluginBase = `${discourseRoot}/plugins/`;
diff --git a/.prettierignore b/.prettierignore
index 0663ab5c013..fe06c902eb7 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -1,5 +1,4 @@
app/assets/stylesheets/vendor/
-app/assets/javascripts/plugins/
plugins/**/assets/stylesheets/vendor/
plugins/**/assets/javascripts/vendor/
plugins/**/config/locales/**/*.yml
@@ -10,18 +9,12 @@ config/locales/**/*.yml
!config/locales/**/*.en*.yml
script/import_scripts/**/*.yml
-app/assets/javascripts/browser-update.js
-app/assets/javascripts/ember-addons/
-app/assets/javascripts/discourse/lib/autosize.js
-lib/javascripts/locale/
-lib/javascripts/messageformat.js
-lib/highlight_js/
plugins/**/lib/javascripts/locale
public/
-!/app/assets/javascripts/discourse/public
+!/frontend/discourse/public
vendor/
-app/assets/javascripts/discourse/tests/unit/utils/decorators-test.js
-app/assets/javascripts/discourse/tests/fixtures
+frontend/discourse/tests/unit/utils/decorators-test.js
+frontend/discourse/tests/fixtures
spec/
node_modules/
dist/
diff --git a/app/assets/javascripts/discourse-plugins/index.js b/app/assets/javascripts/discourse-plugins/index.js
index 7f9cc521dcc..aec0e3dc514 100644
--- a/app/assets/javascripts/discourse-plugins/index.js
+++ b/app/assets/javascripts/discourse-plugins/index.js
@@ -127,7 +127,7 @@ module.exports = {
},
pluginInfos() {
- const root = path.resolve("../../../../plugins");
+ const root = path.resolve("../../plugins");
const pluginDirectories = fs
.readdirSync(root, { withFileTypes: true })
.filter(
diff --git a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js
index db4c4a108c0..d273ea622f4 100644
--- a/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js
+++ b/app/assets/javascripts/discourse/app/lib/keyboard-shortcuts.js
@@ -263,7 +263,7 @@ export default {
* category: String,
* name: String,
* definition: (See function `buildShortcut` in
- * app/assets/javascripts/discourse/app/controllers/keyboard-shortcuts-help.js
+ * frontend/discourse/app/controllers/keyboard-shortcuts-help.js
* for definition structure)
* }
*
diff --git a/app/assets/javascripts/discourse/ember-cli-build.js b/app/assets/javascripts/discourse/ember-cli-build.js
index 19eecc2ca49..7cde0c9cd46 100644
--- a/app/assets/javascripts/discourse/ember-cli-build.js
+++ b/app/assets/javascripts/discourse/ember-cli-build.js
@@ -23,7 +23,7 @@ const { BroccoliMergeFiles } = require("broccoli-merge-files");
process.env.BROCCOLI_ENABLED_MEMOIZE = true;
module.exports = function (defaults) {
- const discourseRoot = path.resolve("../../../..");
+ const discourseRoot = path.resolve("../..");
const vendorJs = discourseRoot + "/vendor/assets/javascripts/";
// Silence deprecations which we are aware of - see `lib/deprecation-silencer.js`
@@ -103,11 +103,10 @@ module.exports = function (defaults) {
});
// WARNING: We should only import scripts here if they are not in NPM.
- app.import(discourseRoot + "/app/assets/javascripts/polyfills.js");
+ app.import(discourseRoot + "/frontend/polyfills.js");
app.import(
- discourseRoot +
- "/app/assets/javascripts/discourse/public/assets/scripts/module-shims.js"
+ discourseRoot + "/frontend/discourse/public/assets/scripts/module-shims.js"
);
const discoursePluginsTree = app.project
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index 5b43bc5038e..a3dd050c1db 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -734,7 +734,7 @@ class ApplicationController < ActionController::Base
raise Discourse::InvalidAccess.new unless SiteSetting.wizard_enabled?
end
- # Keep in sync with `NO_DESTINATION_COOKIE` in `app/assets/javascripts/discourse/app/lib/utilities.js`
+ # Keep in sync with `NO_DESTINATION_COOKIE` in `frontend/discourse/app/lib/utilities.js`
NO_DESTINATION_COOKIE = %w[/login /signup /session/ /auth/ /uploads/].freeze
def is_valid_destination_url?(url)
diff --git a/app/services/theme_settings_migrations_runner.rb b/app/services/theme_settings_migrations_runner.rb
index c7d1fe85711..6b5fb455f50 100644
--- a/app/services/theme_settings_migrations_runner.rb
+++ b/app/services/theme_settings_migrations_runner.rb
@@ -58,10 +58,7 @@ class ThemeSettingsMigrationsRunner
def self.loader_js_lib_content
@loader_js_lib_content ||=
File.read(
- File.join(
- Rails.root,
- "app/assets/javascripts/discourse/node_modules/loader.js/dist/loader/loader.js",
- ),
+ File.join(Rails.root, "frontend/discourse/node_modules/loader.js/dist/loader/loader.js"),
)
end
diff --git a/app/views/qunit/theme.html.erb b/app/views/qunit/theme.html.erb
index 0a498f9c6d8..6cb7d044f72 100644
--- a/app/views/qunit/theme.html.erb
+++ b/app/views/qunit/theme.html.erb
@@ -26,7 +26,7 @@
<%= discourse_stylesheet_link_tag(:common, theme_id: nil) %>
diff --git a/bin/ember-cli b/bin/ember-cli
index 84f03f2a62d..f21049eb135 100755
--- a/bin/ember-cli
+++ b/bin/ember-cli
@@ -48,7 +48,7 @@ if ARGV.include?("-h") || ARGV.include?("--help")
exec "pnpm ember #{command} --help"
end
-args = ["--dir=app/assets/javascripts/discourse", "ember", command] + (ARGV - CUSTOM_ARGS)
+args = ["--dir=frontend/discourse", "ember", command] + (ARGV - CUSTOM_ARGS)
if !args.include?("test") && !args.include?("build") && !args.include?("--proxy")
args << "--proxy"
diff --git a/config/initializers/assets.rb b/config/initializers/assets.rb
index 1c7ccdcfa99..bc7092c941d 100644
--- a/config/initializers/assets.rb
+++ b/config/initializers/assets.rb
@@ -11,7 +11,7 @@ Rails.application.config.assets.version = "2-#{GlobalSetting.asset_url_salt}"
# Add additional assets to the asset load path.
Rails.application.config.assets.paths.push(
"#{Rails.root}/public/javascripts",
- "#{Rails.root}/app/assets/javascripts/discourse/dist/assets",
+ "#{Rails.root}/frontend/discourse/dist/assets",
)
Rails.application.config.assets.paths.push(
diff --git a/config/projections.json b/config/projections.json
index 7f49f292172..48beefeba15 100644
--- a/config/projections.json
+++ b/config/projections.json
@@ -1,29 +1,29 @@
{
- "app/assets/javascripts/discourse/components/*.js": {
+ "frontend/discourse/components/*.js": {
"command": "dcomponent"
},
- "app/assets/javascripts/discourse/lib/*.js": {
+ "frontend/discourse/lib/*.js": {
"command": "dlib"
},
- "app/assets/javascripts/discourse/routes/*.js": {
+ "frontend/discourse/routes/*.js": {
"command": "droute"
},
- "app/assets/javascripts/discourse/controllers/*.js": {
+ "frontend/discourse/controllers/*.js": {
"command": "dcontroller"
},
- "app/assets/javascripts/discourse/models/*.js": {
+ "frontend/discourse/models/*.js": {
"command": "dmodel"
},
- "app/assets/javascripts/discourse/helpers/*.js": {
+ "frontend/discourse/helpers/*.js": {
"command": "dhelper"
},
- "app/assets/javascripts/discourse/templates/*.hbs": {
+ "frontend/discourse/templates/*.hbs": {
"command": "dtemplate"
},
- "app/assets/javascripts/discourse/templates/*.hbr": {
+ "frontend/discourse/templates/*.hbr": {
"command": "dtemplate"
},
- "app/assets/javascripts/discourse/views/*.js": {
+ "frontend/discourse/views/*.js": {
"command": "dview"
},
"app/serializers/*.rb": {
diff --git a/eslint.config.mjs b/eslint.config.mjs
index a4e31eb208d..c94b630fb9e 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -11,18 +11,14 @@ export default [
},
{
ignores: [
- "app/assets/javascripts/ember-addons/",
- "lib/javascripts/locale/*",
- "lib/javascripts/messageformat.js",
- "lib/javascripts/messageformat-lookup.js",
"plugins/**/lib/javascripts/locale",
"plugins/discourse-math/public",
"public/",
"vendor/",
- "app/assets/javascripts/discourse/tests/fixtures",
+ "frontend/discourse/tests/fixtures",
"**/node_modules/",
"spec/",
- "app/assets/javascripts/discourse/dist/",
+ "frontend/discourse/dist/",
"tmp/",
],
},
diff --git a/jsconfig.json b/jsconfig.json
index a47e13cd029..aa9ca4c0cf9 100644
--- a/jsconfig.json
+++ b/jsconfig.json
@@ -8,31 +8,31 @@
"allowJs": true,
"paths": {
"discourse/admin/*": [
- "./app/assets/javascripts/discourse/admin/*"
+ "./frontend/discourse/admin/*"
],
"discourse/*": [
- "./app/assets/javascripts/discourse/app/*"
+ "./frontend/discourse/app/*"
],
"discourse/tests/*": [
- "./app/assets/javascripts/discourse/tests/*"
+ "./frontend/discourse/tests/*"
],
"admin/*": [
- "./app/assets/javascripts/discourse/admin/*"
+ "./frontend/discourse/admin/*"
],
"pretty-text/*": [
- "./app/assets/javascripts/pretty-text/addon/*"
+ "./frontend/pretty-text/addon/*"
],
"select-kit/*": [
- "./app/assets/javascripts/select-kit/addon/*"
+ "./frontend/select-kit/addon/*"
],
"float-kit/*": [
- "./app/assets/javascripts/float-kit/addon/*"
+ "./frontend/float-kit/addon/*"
],
"truth-helpers/*": [
- "./app/assets/javascripts/truth-helpers/addon/*"
+ "./frontend/truth-helpers/addon/*"
],
"dialog-holder/*": [
- "./app/assets/javascripts/dialog-holder/addon/*"
+ "./frontend/dialog-holder/addon/*"
],
"discourse/plugins/automation/*": [
"./plugins/automation/assets/javascripts/*",
@@ -213,15 +213,15 @@
}
},
"include": [
- "./app/assets/javascripts/discourse/admin",
- "./app/assets/javascripts/discourse/app",
- "./app/assets/javascripts/discourse/tests",
- "./app/assets/javascripts/discourse/admin",
- "./app/assets/javascripts/pretty-text/addon",
- "./app/assets/javascripts/select-kit/addon",
- "./app/assets/javascripts/float-kit/addon",
- "./app/assets/javascripts/truth-helpers/addon",
- "./app/assets/javascripts/dialog-holder/addon",
+ "./frontend/discourse/admin",
+ "./frontend/discourse/app",
+ "./frontend/discourse/tests",
+ "./frontend/discourse/admin",
+ "./frontend/pretty-text/addon",
+ "./frontend/select-kit/addon",
+ "./frontend/float-kit/addon",
+ "./frontend/truth-helpers/addon",
+ "./frontend/dialog-holder/addon",
"./plugins/automation/assets/javascripts",
"./plugins/automation/test/javascripts",
"./plugins/chat/assets/javascripts",
@@ -312,6 +312,6 @@
"./themes/horizon/test"
],
"exclude": [
- "app/assets/javascripts/discourse/tests/unit/utils/decorators-test.js"
+ "frontend/discourse/tests/unit/utils/decorators-test.js"
]
}
diff --git a/lefthook.yml b/lefthook.yml
index 73886650005..b0f4df99553 100644
--- a/lefthook.yml
+++ b/lefthook.yml
@@ -20,11 +20,11 @@ pre-commit:
run: pnpm pprettier --list-different {staged_files}
eslint:
glob: "*.{js,gjs}"
- include: "app/assets/javascripts|plugins/.+?/assets/javascripts"
+ include: "frontend|plugins/.+?/assets/javascripts"
run: pnpm eslint --quiet {staged_files}
ember-template-lint:
glob: "*.{hbs,gjs}"
- include: "app/assets/javascripts|plugins/.+?/assets/javascripts"
+ include: "frontend|plugins/.+?/assets/javascripts"
run: pnpm ember-template-lint {staged_files}
yaml-syntax:
glob: "*.{yaml,yml}"
@@ -48,11 +48,11 @@ fix-staged:
run: pnpm pprettier --write {staged_files}
eslint:
glob: "*.{js,gjs}"
- include: "app/assets/javascripts|plugins/.+?/assets/javascripts|themes"
+ include: "frontend|plugins/.+?/assets/javascripts|themes"
run: pnpm eslint --fix {staged_files}
ember-template-lint:
glob: "*.{gjs,hbs}"
- include: "app/assets/javascripts|plugins/.+?/assets/javascripts|themes"
+ include: "frontend|plugins/.+?/assets/javascripts|themes"
run: pnpm ember-template-lint --fix {staged_files}
stylelint:
glob: "*.scss"
diff --git a/lib/asset_processor.rb b/lib/asset_processor.rb
index 5835e99b28a..06e8cadbb42 100644
--- a/lib/asset_processor.rb
+++ b/lib/asset_processor.rb
@@ -24,12 +24,7 @@ class AssetProcessor
end
def self.build_asset_processor
- Discourse::Utils.execute_command(
- "pnpm",
- "-C=app/assets/javascripts/asset-processor",
- "node",
- "build.js",
- )
+ Discourse::Utils.execute_command("pnpm", "-C=frontend/asset-processor", "node", "build.js")
end
def self.build_production_asset_processor
diff --git a/lib/autospec/rspec_runner.rb b/lib/autospec/rspec_runner.rb
index d77d01e4723..cdb684660b8 100644
--- a/lib/autospec/rspec_runner.rb
+++ b/lib/autospec/rspec_runner.rb
@@ -26,9 +26,7 @@ module Autospec
watch(%r{\Aspec/fabricators/.+_fabricator\.rb\z}) { "spec" }
- watch(%r{\Aapp/assets/javascripts/pretty-text/.*\.js\.es6\z}) do
- "spec/components/pretty_text_spec.rb"
- end
+ watch(%r{\Afrontend/pretty-text/.*\.js\.es6\z}) { "spec/components/pretty_text_spec.rb" }
watch(%r{\Aplugins/.*/discourse-markdown/.*\.js\.es6\z}) do
"spec/components/pretty_text_spec.rb"
end
diff --git a/lib/discourse_plugin_registry.rb b/lib/discourse_plugin_registry.rb
index 5ac22fc414a..a17e1455332 100644
--- a/lib/discourse_plugin_registry.rb
+++ b/lib/discourse_plugin_registry.rb
@@ -250,9 +250,9 @@ class DiscoursePluginRegistry
end
VENDORED_CORE_PRETTY_TEXT_MAP = {
- "moment.js" => "app/assets/javascripts/discourse/node_modules/moment/moment.js",
+ "moment.js" => "frontend/discourse/node_modules/moment/moment.js",
"moment-timezone.js" =>
- "app/assets/javascripts/discourse/node_modules/moment-timezone/builds/moment-timezone-with-data.js",
+ "frontend/discourse/node_modules/moment-timezone/builds/moment-timezone-with-data.js",
}
def self.core_asset_for_name(name)
diff --git a/lib/ember_cli.rb b/lib/ember_cli.rb
index 573920ab206..56f5dc5ecbe 100644
--- a/lib/ember_cli.rb
+++ b/lib/ember_cli.rb
@@ -5,7 +5,7 @@ class EmberCli < ActiveSupport::CurrentAttributes
attribute :request_cache
def self.dist_dir
- "#{Rails.root}/app/assets/javascripts/discourse/dist"
+ "#{Rails.root}/frontend/discourse/dist"
end
def self.assets
diff --git a/lib/highlight_js.rb b/lib/highlight_js.rb
index 882f32fb6de..d535309976e 100644
--- a/lib/highlight_js.rb
+++ b/lib/highlight_js.rb
@@ -1,8 +1,7 @@
# frozen_string_literal: true
module HighlightJs
- HIGHLIGHTJS_DIR =
- "#{Rails.root}/app/assets/javascripts/discourse/node_modules/@highlightjs/cdn-assets/"
+ HIGHLIGHTJS_DIR = "#{Rails.root}/frontend/discourse/node_modules/@highlightjs/cdn-assets/"
VERSION = 1 # bump to invalidate caches following core changes
def self.languages
diff --git a/lib/js_locale_helper.rb b/lib/js_locale_helper.rb
index a655de4c838..d931d7ff07f 100644
--- a/lib/js_locale_helper.rb
+++ b/lib/js_locale_helper.rb
@@ -266,7 +266,7 @@ module JsLocaleHelper
path = "#{Rails.root}/node_modules/@discourse/moment-timezone-names-translations/locales"
type = :moment_js_timezones
else
- path = "#{Rails.root}/app/assets/javascripts/discourse/node_modules/moment/locale"
+ path = "#{Rails.root}/frontend/discourse/node_modules/moment/locale"
type = :moment_js
end
diff --git a/lib/presence_channel.rb b/lib/presence_channel.rb
index 929edb8bdf0..68f0113bfd0 100644
--- a/lib/presence_channel.rb
+++ b/lib/presence_channel.rb
@@ -1,7 +1,7 @@
# frozen_string_literal: true
# The server-side implementation of PresenceChannels. See also {PresenceController}
-# and +app/assets/javascripts/discourse/app/services/presence.js+
+# and +frontend/discourse/app/services/presence.js+
class PresenceChannel
class NotFound < StandardError
end
diff --git a/lib/pretty_text.rb b/lib/pretty_text.rb
index d378aa7f8b4..806b8b1ce68 100644
--- a/lib/pretty_text.rb
+++ b/lib/pretty_text.rb
@@ -82,9 +82,9 @@ module PrettyText
ctx.attach("__helpers.#{method}", PrettyText::Helpers.method(method))
end
- root_path = "#{Rails.root}/app/assets/javascripts"
- d_node_modules = "#{Rails.root}/app/assets/javascripts/discourse/node_modules"
- md_node_modules = "#{Rails.root}/app/assets/javascripts/discourse-markdown-it/node_modules"
+ root_path = "#{Rails.root}/frontend"
+ d_node_modules = "#{Rails.root}/frontend/discourse/node_modules"
+ md_node_modules = "#{Rails.root}/frontend/discourse-markdown-it/node_modules"
ctx.load("#{d_node_modules}/loader.js/dist/loader/loader.js")
ctx.load("#{md_node_modules}/markdown-it/dist/markdown-it.js")
ctx.load("#{md_node_modules}/xss/dist/xss.js")
diff --git a/lib/tasks/docker.rake b/lib/tasks/docker.rake
index 2d7835eb87f..206b00f460e 100644
--- a/lib/tasks/docker.rake
+++ b/lib/tasks/docker.rake
@@ -183,7 +183,7 @@ task "docker:test" do
else
@good &&= run_or_fail("bundle exec rake plugin:update_all") unless ENV["SKIP_PLUGINS"]
@good &&= run_or_fail("bundle exec rubocop") unless ENV["SKIP_CORE"]
- @good &&= run_or_fail("pnpm eslint app/assets/javascripts") unless ENV["SKIP_CORE"]
+ @good &&= run_or_fail("pnpm eslint frontend") unless ENV["SKIP_CORE"]
@good &&=
run_or_fail(
"pnpm eslint --ext .js,.js.es6 --no-error-on-unmatched-pattern plugins",
@@ -202,7 +202,7 @@ task "docker:test" do
puts "Listing prettier offenses in core:"
@good &&=
run_or_fail(
- 'pnpm pprettier --list-different "app/assets/stylesheets/**/*.scss" "app/assets/javascripts/**/*.js"',
+ 'pnpm pprettier --list-different "app/assets/stylesheets/**/*.scss" "frontend/**/*.js"',
)
end
diff --git a/lib/tasks/javascript.rake b/lib/tasks/javascript.rake
index d11fe6d0e5a..222f5d69cda 100644
--- a/lib/tasks/javascript.rake
+++ b/lib/tasks/javascript.rake
@@ -7,7 +7,7 @@ def write_template(path, task_name, template)
JS
basename = File.basename(path)
- output_path = "#{Rails.root}/app/assets/javascripts/#{path}"
+ output_path = "#{Rails.root}/frontend/#{path}"
File.write(output_path, "#{header}\n\n#{template}")
puts "#{basename} created"
diff --git a/lib/tasks/qunit.rake b/lib/tasks/qunit.rake
index 93471045c92..c546c09e770 100644
--- a/lib/tasks/qunit.rake
+++ b/lib/tasks/qunit.rake
@@ -113,13 +113,7 @@ task "qunit:test", %i[qunit_path filter] do |_, args|
# Bypass `ember test` - it only works properly for the `/tests` path.
# We have to trigger a `build` manually so that JS is available for rails to serve.
if !reuse_build
- system(
- "pnpm",
- "ember",
- "build",
- chdir: "#{Rails.root}/app/assets/javascripts/discourse",
- exception: true,
- )
+ system("pnpm", "ember", "build", chdir: "#{Rails.root}/frontend/discourse", exception: true)
end
env["THEME_TEST_PAGES"] = if ENV["THEME_IDS"]
@@ -144,7 +138,7 @@ task "qunit:test", %i[qunit_path filter] do |_, args|
# Print out all env for debugging purposes
p env
- system(env, *cmd, chdir: "#{Rails.root}/app/assets/javascripts/discourse")
+ system(env, *cmd, chdir: "#{Rails.root}/frontend/discourse")
success &&= $?.success?
ensure
diff --git a/package.json b/package.json
index 58510038c65..208ce0406d9 100644
--- a/package.json
+++ b/package.json
@@ -37,17 +37,17 @@
"lint:fix": "concurrently \"pnpm:lint:*:fix\" --names \"fix:\"",
"lint:css": "pnpm stylelint 'app/assets/stylesheets/**/*.scss' $(script/list_bundled_plugins '/assets/stylesheets/**/*.scss') 'themes/**/*.scss'",
"lint:css:fix": "pnpm stylelint --fix 'app/assets/stylesheets/**/*.scss' $(script/list_bundled_plugins '/assets/stylesheets/**/*.scss') 'themes/**/*.scss'",
- "lint:js": "eslint ./app/assets/javascripts $(script/list_bundled_plugins) ./themes --cache --no-error-on-unmatched-pattern",
- "lint:js:fix": "eslint --fix ./app/assets/javascripts $(script/list_bundled_plugins) ./themes --no-error-on-unmatched-pattern",
- "lint:hbs": "ember-template-lint 'app/assets/javascripts/**/*.{gjs,hbs}' 'plugins/*/assets/javascripts/**/*.{gjs,hbs}' 'plugins/*/admin/assets/javascripts/**/*.{gjs,hbs}' 'themes/**/*.{gjs,hbs}'",
- "lint:hbs:fix": "ember-template-lint 'app/assets/javascripts/**/*.{gjs,hbs}' 'plugins/*/assets/javascripts/**/*.{gjs,hbs}' 'plugins/*/admin/assets/javascripts/**/*.{gjs,hbs}' 'themes/**/*.{gjs,hbs}' --fix",
- "lint:prettier": "pnpm pprettier --list-different 'app/assets/stylesheets/**/*.scss' 'app/assets/javascripts/**/*.{js,gjs,hbs,css}' $(script/list_bundled_plugins '/assets/stylesheets/**/*.scss') $(script/list_bundled_plugins '/{assets,admin/assets,test}/javascripts/**/*.{js,gjs,hbs}') 'themes/**/*.{js,gjs,hbs,scss}'",
- "lint:prettier:fix": "pnpm prettier -w --no-error-on-unmatched-pattern 'app/assets/stylesheets/**/*.scss' 'app/assets/javascripts/**/*.{js,gjs,hbs,css}' $(script/list_bundled_plugins '/assets/stylesheets/**/*.scss') $(script/list_bundled_plugins '/{assets,admin/assets,test}/javascripts/**/*.{js,gjs,hbs}') 'themes/**/*.{js,gjs,hbs,scss}'",
+ "lint:js": "eslint ./frontend $(script/list_bundled_plugins) ./themes --cache --no-error-on-unmatched-pattern",
+ "lint:js:fix": "eslint --fix ./frontend $(script/list_bundled_plugins) ./themes --no-error-on-unmatched-pattern",
+ "lint:hbs": "ember-template-lint 'frontend/**/*.{gjs,hbs}' 'plugins/*/assets/javascripts/**/*.{gjs,hbs}' 'plugins/*/admin/assets/javascripts/**/*.{gjs,hbs}' 'themes/**/*.{gjs,hbs}'",
+ "lint:hbs:fix": "ember-template-lint 'frontend/**/*.{gjs,hbs}' 'plugins/*/assets/javascripts/**/*.{gjs,hbs}' 'plugins/*/admin/assets/javascripts/**/*.{gjs,hbs}' 'themes/**/*.{gjs,hbs}' --fix",
+ "lint:prettier": "pnpm pprettier --list-different 'app/assets/stylesheets/**/*.scss' 'frontend/**/*.{js,gjs,hbs,css}' $(script/list_bundled_plugins '/assets/stylesheets/**/*.scss') $(script/list_bundled_plugins '/{assets,admin/assets,test}/javascripts/**/*.{js,gjs,hbs}') 'themes/**/*.{js,gjs,hbs,scss}'",
+ "lint:prettier:fix": "pnpm prettier -w --no-error-on-unmatched-pattern 'app/assets/stylesheets/**/*.scss' 'frontend/**/*.{js,gjs,hbs,css}' $(script/list_bundled_plugins '/assets/stylesheets/**/*.scss') $(script/list_bundled_plugins '/{assets,admin/assets,test}/javascripts/**/*.{js,gjs,hbs}') 'themes/**/*.{js,gjs,hbs,scss}'",
"lint:glint": "ember-tsc -p jsconfig.json --noEmit",
"lttf:ignore": "lint-to-the-future ignore",
"lttf:output": "lint-to-the-future output -o ./lint-progress/",
"lint-progress": "pnpm lttf:output && npx html-pages ./lint-progress --no-cache",
- "ember": "pnpm --dir=app/assets/javascripts/discourse ember",
+ "ember": "pnpm --dir=frontend/discourse ember",
"playwright-install": "playwright install --no-shell chromium"
},
"engines": {
diff --git a/plugins/discourse-assign/test/javascripts/acceptance/assign-enabled-test.js b/plugins/discourse-assign/test/javascripts/acceptance/assign-enabled-test.js
index 81238e1ffe8..c8e6e901355 100644
--- a/plugins/discourse-assign/test/javascripts/acceptance/assign-enabled-test.js
+++ b/plugins/discourse-assign/test/javascripts/acceptance/assign-enabled-test.js
@@ -322,7 +322,7 @@ acceptance(
// usually this is done automatically by this pretender but we
// have to do it manually here because we are overriding the
- // pretender see app/assets/javascripts/discourse/tests/helpers/create-pretender.js
+ // pretender see frontend/discourse/tests/helpers/create-pretender.js
json.user.can_edit = true;
return helper.response(200, json);
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 1e2cc5ae830..bb970ece466 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -107,7 +107,7 @@ importers:
specifier: 5.6.x
version: 5.6.3
- app/assets/javascripts/asset-processor:
+ frontend/asset-processor:
dependencies:
'@babel/core':
specifier: ^7.28.4
@@ -204,7 +204,7 @@ importers:
specifier: ^3.2.4
version: 3.2.4(@types/node@24.9.1)(jsdom@25.0.1)(terser@5.44.0)
- app/assets/javascripts/custom-proxy:
+ frontend/custom-proxy:
devDependencies:
clean-base-url:
specifier: ^1.0.0
@@ -225,9 +225,9 @@ importers:
specifier: ^3.3.2
version: 3.3.2
- app/assets/javascripts/deprecation-silencer: {}
+ frontend/deprecation-silencer: {}
- app/assets/javascripts/dialog-holder:
+ frontend/dialog-holder:
dependencies:
a11y-dialog:
specifier: 8.1.4
@@ -261,7 +261,7 @@ importers:
specifier: 5.99.9
version: 5.99.9(@swc/core@1.13.5)(esbuild@0.25.11)
- app/assets/javascripts/discourse:
+ frontend/discourse:
dependencies:
'@faker-js/faker':
specifier: ^10.1.0
@@ -673,7 +673,7 @@ importers:
specifier: ^1.0.15
version: 1.0.15
- app/assets/javascripts/discourse-i18n:
+ frontend/discourse-i18n:
dependencies:
'@embroider/addon-shim':
specifier: ^1.9.0
@@ -682,7 +682,7 @@ importers:
specifier: ^7.4.0
version: 7.4.0
- app/assets/javascripts/discourse-markdown-it:
+ frontend/discourse-markdown-it:
dependencies:
'@embroider/addon-shim':
specifier: ^1.9.0
@@ -706,7 +706,7 @@ importers:
specifier: ^1.0.15
version: 1.0.15
- app/assets/javascripts/discourse-plugins:
+ frontend/discourse-plugins:
dependencies:
'@babel/core':
specifier: ^7.28.4
@@ -737,7 +737,7 @@ importers:
specifier: 5.99.9
version: 5.99.9(@swc/core@1.13.5)(esbuild@0.25.11)
- app/assets/javascripts/discourse-widget-hbs:
+ frontend/discourse-widget-hbs:
dependencies:
'@babel/core':
specifier: ^7.28.4
@@ -801,9 +801,9 @@ importers:
specifier: 5.99.9
version: 5.99.9(@swc/core@1.13.5)(esbuild@0.25.11)
- app/assets/javascripts/ember-cli-progress-ci: {}
+ frontend/ember-cli-progress-ci: {}
- app/assets/javascripts/float-kit:
+ frontend/float-kit:
dependencies:
'@babel/core':
specifier: ^7.28.4
@@ -888,7 +888,7 @@ importers:
specifier: 5.99.9
version: 5.99.9(@swc/core@1.13.5)(esbuild@0.25.11)
- app/assets/javascripts/pretty-text:
+ frontend/pretty-text:
dependencies:
'@babel/core':
specifier: ^7.28.4
@@ -964,7 +964,7 @@ importers:
specifier: 5.99.9
version: 5.99.9(@swc/core@1.13.5)(esbuild@0.25.11)
- app/assets/javascripts/select-kit:
+ frontend/select-kit:
dependencies:
'@babel/core':
specifier: ^7.28.4
@@ -1058,7 +1058,7 @@ importers:
specifier: 5.99.9
version: 5.99.9(@swc/core@1.13.5)(esbuild@0.25.11)
- app/assets/javascripts/truth-helpers:
+ frontend/truth-helpers:
dependencies:
'@embroider/addon-shim':
specifier: ^1.9.0
diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml
index bc62ab6b42b..fc3f33dd7b2 100644
--- a/pnpm-workspace.yaml
+++ b/pnpm-workspace.yaml
@@ -1,15 +1,15 @@
packages:
-- "app/assets/javascripts/custom-proxy"
-- "app/assets/javascripts/deprecation-silencer"
-- "app/assets/javascripts/dialog-holder"
-- "app/assets/javascripts/discourse"
-- "app/assets/javascripts/discourse-i18n"
-- "app/assets/javascripts/discourse-markdown-it"
-- "app/assets/javascripts/discourse-plugins"
-- "app/assets/javascripts/discourse-widget-hbs"
-- "app/assets/javascripts/ember-cli-progress-ci"
-- "app/assets/javascripts/float-kit"
-- "app/assets/javascripts/pretty-text"
-- "app/assets/javascripts/select-kit"
-- "app/assets/javascripts/asset-processor"
-- "app/assets/javascripts/truth-helpers"
+- "frontend/custom-proxy"
+- "frontend/deprecation-silencer"
+- "frontend/dialog-holder"
+- "frontend/discourse"
+- "frontend/discourse-i18n"
+- "frontend/discourse-markdown-it"
+- "frontend/discourse-plugins"
+- "frontend/discourse-widget-hbs"
+- "frontend/ember-cli-progress-ci"
+- "frontend/float-kit"
+- "frontend/pretty-text"
+- "frontend/select-kit"
+- "frontend/asset-processor"
+- "frontend/truth-helpers"
diff --git a/script/assemble_ember_build.rb b/script/assemble_ember_build.rb
index aafd74a993e..e44677e79b4 100755
--- a/script/assemble_ember_build.rb
+++ b/script/assemble_ember_build.rb
@@ -15,9 +15,9 @@ DOWNLOAD_TEMP_FILE = "#{__dir__}/../tmp/assets.tar.gz"
PRE_BUILD_ROOT = "https://get.discourse.org/discourse-assets"
-JS_SOURCE_PATHS = %w[app/assets/javascripts package.json pnpm-lock.yaml]
+JS_SOURCE_PATHS = %w[frontend package.json pnpm-lock.yaml]
-EMBER_APP_DIR = "app/assets/javascripts/discourse"
+EMBER_APP_DIR = "frontend/discourse"
BUILD_INFO_FILE = "#{EMBER_APP_DIR}/dist/BUILD_INFO.json"
Dir.chdir("#{__dir__}/..")
diff --git a/script/build_jsconfig.rb b/script/build_jsconfig.rb
index 5fe113cf027..2cb879e10b5 100755
--- a/script/build_jsconfig.rb
+++ b/script/build_jsconfig.rb
@@ -7,15 +7,15 @@ require "json"
Dir.chdir("#{__dir__}/..") # rubocop:disable Discourse/NoChdir because this is not part of the app
CORE_NAMESPACES = {
- "discourse/admin/*" => ["app/assets/javascripts/discourse/admin"],
- "discourse/*" => ["app/assets/javascripts/discourse/app"],
- "discourse/tests/*" => ["app/assets/javascripts/discourse/tests"],
- "admin/*" => ["app/assets/javascripts/discourse/admin"], # TODO: remove once all core code is migrated to new import path
- "pretty-text/*" => ["app/assets/javascripts/pretty-text/addon"],
- "select-kit/*" => ["app/assets/javascripts/select-kit/addon"],
- "float-kit/*" => ["app/assets/javascripts/float-kit/addon"],
- "truth-helpers/*" => ["app/assets/javascripts/truth-helpers/addon"],
- "dialog-holder/*" => ["app/assets/javascripts/dialog-holder/addon"],
+ "discourse/admin/*" => ["frontend/discourse/admin"],
+ "discourse/*" => ["frontend/discourse/app"],
+ "discourse/tests/*" => ["frontend/discourse/tests"],
+ "admin/*" => ["frontend/discourse/admin"], # TODO: remove once all core code is migrated to new import path
+ "pretty-text/*" => ["frontend/pretty-text/addon"],
+ "select-kit/*" => ["frontend/select-kit/addon"],
+ "float-kit/*" => ["frontend/float-kit/addon"],
+ "truth-helpers/*" => ["frontend/truth-helpers/addon"],
+ "dialog-holder/*" => ["frontend/dialog-holder/addon"],
}
def relative(from, to)
@@ -42,7 +42,7 @@ def write_config(package_dir, extras: {})
},
"include" => namespaces.flat_map { |ns, paths| paths.map { |p| relative(package_dir, p) } },
"exclude" => [
- "app/assets/javascripts/discourse/tests/unit/utils/decorators-test.js", # Native class decorators - unsupported by ts/glint
+ "frontend/discourse/tests/unit/utils/decorators-test.js", # Native class decorators - unsupported by ts/glint
],
}
diff --git a/script/check_reproducible_assets.rb b/script/check_reproducible_assets.rb
index b61d012bae0..9f14213c377 100755
--- a/script/check_reproducible_assets.rb
+++ b/script/check_reproducible_assets.rb
@@ -7,7 +7,7 @@
require "digest"
-DIST_DIR = File.expand_path("#{__dir__}/../app/assets/javascripts/discourse/dist")
+DIST_DIR = File.expand_path("#{__dir__}/../frontend/discourse/dist")
def collect_asset_info
files =
diff --git a/script/publish_built_assets.rb b/script/publish_built_assets.rb
index 5adea77dbd7..29c785356b4 100755
--- a/script/publish_built_assets.rb
+++ b/script/publish_built_assets.rb
@@ -26,7 +26,7 @@ end
common_env = { "DISCOURSE_DOWNLOAD_PRE_BUILT_ASSETS" => "0", "LOAD_PLUGINS" => "0" }
-Dir.chdir("#{__dir__}/../app/assets/javascripts/discourse")
+Dir.chdir("#{__dir__}/../frontend/discourse")
FileUtils.rm_rf("dist")
system({ **common_env, "EMBER_ENV" => "production" }, "#{__dir__}/assemble_ember_build.rb")
diff --git a/spec/integrity/coding_style_spec.rb b/spec/integrity/coding_style_spec.rb
index f22851a4f11..45e7d259e76 100644
--- a/spec/integrity/coding_style_spec.rb
+++ b/spec/integrity/coding_style_spec.rb
@@ -48,8 +48,8 @@ RSpec.describe "Coding style" do
describe "non-colocated component templates" do
{
- "discourse" => "app/assets/javascripts/discourse/app/templates/components",
- "admin" => "app/assets/javascripts/admin/addon/templates/components",
+ "discourse" => "frontend/discourse/app/templates/components",
+ "admin" => "frontend/admin/addon/templates/components",
"chat/discourse" => "plugins/chat/assets/javascripts/discourse/templates/components",
"chat/admin" => "plugins/chat/assets/javascripts/admin/templates/components",
"styleguide" => "plugins/styleguide/assets/javascripts/discourse/templates/components",
diff --git a/spec/integrity/js_constants_spec.rb b/spec/integrity/js_constants_spec.rb
index 559f2c45337..c1a0e7e5a18 100644
--- a/spec/integrity/js_constants_spec.rb
+++ b/spec/integrity/js_constants_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe "constants match ruby" do
def parse(file)
# mini racer doesn't handle JS modules so we'll do this hack
- source = File.read("#{Rails.root}/app/assets/javascripts/#{file}")
+ source = File.read("#{Rails.root}/frontend/#{file}")
source.gsub!(/^export */, "")
ctx.eval(source)
end
diff --git a/spec/lib/js_locale_helper_spec.rb b/spec/lib/js_locale_helper_spec.rb
index 574b6e91c3b..3954cfb8c10 100644
--- a/spec/lib/js_locale_helper_spec.rb
+++ b/spec/lib/js_locale_helper_spec.rb
@@ -2,7 +2,7 @@
RSpec.describe JsLocaleHelper do
let(:v8_ctx) do
- discourse_node_modules = "#{Rails.root}/app/assets/javascripts/discourse/node_modules"
+ discourse_node_modules = "#{Rails.root}/frontend/discourse/node_modules"
mf_runtime = "#{discourse_node_modules}/@messageformat/runtime"
processor = AssetProcessor.new
ctx = MiniRacer::Context.new
@@ -13,7 +13,7 @@ RSpec.describe JsLocaleHelper do
"@messageformat/runtime": "#{mf_runtime}/esm/runtime.js",
"@messageformat/runtime/lib/cardinals": "#{mf_runtime}/esm/cardinals.js",
"make-plural/cardinals": "#{discourse_node_modules}/make-plural/cardinals.mjs",
- "discourse-i18n": "#{Rails.root}/app/assets/javascripts/discourse-i18n/src/index.js",
+ "discourse-i18n": "#{Rails.root}/frontend/discourse-i18n/src/index.js",
}.each do |module_name, path|
ctx.eval(processor.perform(File.read(path), "", module_name.to_s))
end
diff --git a/spec/lib/plugin/instance_spec.rb b/spec/lib/plugin/instance_spec.rb
index 970d2160434..2d5b69fb861 100644
--- a/spec/lib/plugin/instance_spec.rb
+++ b/spec/lib/plugin/instance_spec.rb
@@ -350,7 +350,7 @@ TEXT
plugin.send :register_assets!
expect(DiscoursePluginRegistry.vendored_core_pretty_text.first).to eq(
- "app/assets/javascripts/discourse/node_modules/moment/moment.js",
+ "frontend/discourse/node_modules/moment/moment.js",
)
end
end
@@ -577,10 +577,7 @@ TEXT
expect(locale[:fallbackLocale]).to eq("pt_BR")
expect(locale[:moment_js]).to eq(
- [
- "pt-br",
- "#{Rails.root}/app/assets/javascripts/discourse/node_modules/moment/locale/pt-br.js",
- ],
+ ["pt-br", "#{Rails.root}/frontend/discourse/node_modules/moment/locale/pt-br.js"],
)
expect(locale[:moment_js_timezones]).to eq(
[
@@ -601,7 +598,7 @@ TEXT
expect(locale[:fallbackLocale]).to be_nil
expect(locale[:moment_js]).to eq(
- ["tlh", "#{Rails.root}/app/assets/javascripts/discourse/node_modules/moment/locale/tlh.js"],
+ ["tlh", "#{Rails.root}/frontend/discourse/node_modules/moment/locale/tlh.js"],
)
expect(locale[:plural]).to eq(plural.with_indifferent_access)