diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index 8418138c8def..f9d3dab201c1 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -62,6 +62,7 @@
 | git-config | ✓ |  |  |  |
 | git-ignore | ✓ |  |  |  |
 | git-rebase | ✓ |  |  |  |
+| gjs | ✓ | ✓ | ✓ | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
 | gleam | ✓ | ✓ |  | `gleam` |
 | glimmer | ✓ |  |  | `ember-language-server` |
 | glsl | ✓ | ✓ | ✓ |  |
@@ -73,6 +74,7 @@
 | gowork | ✓ |  |  | `gopls` |
 | graphql | ✓ | ✓ |  | `graphql-lsp` |
 | groovy | ✓ |  |  |  |
+| gts | ✓ | ✓ | ✓ | `typescript-language-server`, `vscode-eslint-language-server`, `ember-language-server` |
 | hare | ✓ |  |  |  |
 | haskell | ✓ | ✓ |  | `haskell-language-server-wrapper` |
 | haskell-persistent | ✓ |  |  |  |
diff --git a/languages.toml b/languages.toml
index ec3e36ed67b8..ace01e968bb6 100644
--- a/languages.toml
+++ b/languages.toml
@@ -197,6 +197,28 @@ inlayHints.functionLikeReturnTypes.enabled = true
 inlayHints.enumMemberValues.enabled = true
 inlayHints.parameterNames.enabled = "all"
 
+[language-server.vscode-eslint-language-server]
+command = "vscode-eslint-language-server"
+args = ["--stdio"]
+
+[language-server.vscode-eslint-language-server.config]
+validate = "on"
+experimental = { useFlatConfig = false }
+rulesCustomizations = []
+run = "onType"
+problems = { shortenToSingleLine = false }
+nodePath = ""
+
+[language-server.vscode-eslint-language-server.config.codeAction.disableRuleComment]
+enable = true
+location = "separateLine"
+
+[language-server.vscode-eslint-language-server.config.codeAction.showDocumentation]
+enable = true
+
+[language-server.vscode-eslint-language-server.config.workingDirectory]
+mode = "location"
+
 [[language]]
 name = "rust"
 scope = "source.rust"
@@ -3586,3 +3608,51 @@ language-servers = ["pest-language-server"]
 [[grammar]]
 name = "pest"
 source = { git = "https://github.com/pest-parser/tree-sitter-pest", rev = "a8a98a824452b1ec4da7f508386a187a2f234b85" }
+
+[[language]]
+name = "gjs"
+scope = "source.gjs"
+file-types = ["gjs"]
+roots = ["package.json", "ember-cli-build.js"]
+comment-token = "//"
+block-comment-tokens = { start = "/*", end = "*/" }
+language-servers = [
+    { except-features = [
+        "format", "diagnostics",
+    ], name = "typescript-language-server" },
+    "vscode-eslint-language-server",
+    "ember-language-server",
+]
+indent = { tab-width = 2, unit = "  " }
+grammar = "javascript"
+
+[language.auto-pairs]
+'<' = '>'
+"'" = "'"
+"{" = "}"
+"(" = ")"
+'"' = '"'
+
+[[language]]
+name = "gts"
+scope = "source.gts"
+file-types = ["gts"]
+roots = ["package.json", "ember-cli-build.js"]
+comment-token = "//"
+block-comment-tokens = { start = "/*", end = "*/" }
+language-servers = [
+    { except-features = [
+        "format", "diagnostics",
+    ], name = "typescript-language-server" },
+    "vscode-eslint-language-server",
+    "ember-language-server",
+]
+indent = { tab-width = 2, unit = "  " }
+grammar = "typescript"
+
+[language.auto-pairs]
+'<' = '>'
+"'" = "'"
+"{" = "}"
+"(" = ")"
+'"' = '"'
diff --git a/runtime/queries/_gjs/highlights.scm b/runtime/queries/_gjs/highlights.scm
new file mode 100644
index 000000000000..f410a10705d9
--- /dev/null
+++ b/runtime/queries/_gjs/highlights.scm
@@ -0,0 +1,5 @@
+[
+  (glimmer_opening_tag)
+  (glimmer_closing_tag)
+] @constant.builtin
+
diff --git a/runtime/queries/_gjs/injections.scm b/runtime/queries/_gjs/injections.scm
new file mode 100644
index 000000000000..830463168b6a
--- /dev/null
+++ b/runtime/queries/_gjs/injections.scm
@@ -0,0 +1,20 @@
+; PARSE GLIMMER TEMPLATES
+(call_expression
+  function: [
+    (identifier) @injection.language
+    (member_expression
+      property: (property_identifier) @injection.language)
+  ]
+  arguments: (template_string) @injection.content)
+
+; e.g.: <template><SomeComponent @arg={{double @value}} /></template>
+((glimmer_template) @injection.content
+ (#set! injection.language "hbs"))
+
+; Parse Ember/Glimmer/Handlebars/HTMLBars/etc. template literals
+; e.g.: await render(hbs`<SomeComponent />`)
+(call_expression
+  function: ((identifier) @_name
+             (#eq? @_name "hbs"))
+  arguments: ((template_string) @glimmer
+              (#offset! @glimmer 0 1 0 -1)))
diff --git a/runtime/queries/gjs/highlights.scm b/runtime/queries/gjs/highlights.scm
new file mode 100644
index 000000000000..519838521e3f
--- /dev/null
+++ b/runtime/queries/gjs/highlights.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_javascript,ecma
diff --git a/runtime/queries/gjs/indents.scm b/runtime/queries/gjs/indents.scm
new file mode 100644
index 000000000000..519838521e3f
--- /dev/null
+++ b/runtime/queries/gjs/indents.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_javascript,ecma
diff --git a/runtime/queries/gjs/injections.scm b/runtime/queries/gjs/injections.scm
new file mode 100644
index 000000000000..519838521e3f
--- /dev/null
+++ b/runtime/queries/gjs/injections.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_javascript,ecma
diff --git a/runtime/queries/gjs/locals.scm b/runtime/queries/gjs/locals.scm
new file mode 100644
index 000000000000..519838521e3f
--- /dev/null
+++ b/runtime/queries/gjs/locals.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_javascript,ecma
diff --git a/runtime/queries/gjs/tags.scm b/runtime/queries/gjs/tags.scm
new file mode 100644
index 000000000000..519838521e3f
--- /dev/null
+++ b/runtime/queries/gjs/tags.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_javascript,ecma
diff --git a/runtime/queries/gjs/textobjects.scm b/runtime/queries/gjs/textobjects.scm
new file mode 100644
index 000000000000..519838521e3f
--- /dev/null
+++ b/runtime/queries/gjs/textobjects.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_javascript,ecma
diff --git a/runtime/queries/gts/highlights.scm b/runtime/queries/gts/highlights.scm
new file mode 100644
index 000000000000..5ad3ee1bb8b2
--- /dev/null
+++ b/runtime/queries/gts/highlights.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_typescript,ecma
diff --git a/runtime/queries/gts/indents.scm b/runtime/queries/gts/indents.scm
new file mode 100644
index 000000000000..5ad3ee1bb8b2
--- /dev/null
+++ b/runtime/queries/gts/indents.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_typescript,ecma
diff --git a/runtime/queries/gts/injections.scm b/runtime/queries/gts/injections.scm
new file mode 100644
index 000000000000..5ad3ee1bb8b2
--- /dev/null
+++ b/runtime/queries/gts/injections.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_typescript,ecma
diff --git a/runtime/queries/gts/locals.scm b/runtime/queries/gts/locals.scm
new file mode 100644
index 000000000000..5ad3ee1bb8b2
--- /dev/null
+++ b/runtime/queries/gts/locals.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_typescript,ecma
diff --git a/runtime/queries/gts/tags.scm b/runtime/queries/gts/tags.scm
new file mode 100644
index 000000000000..5ad3ee1bb8b2
--- /dev/null
+++ b/runtime/queries/gts/tags.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_typescript,ecma
diff --git a/runtime/queries/gts/textobjects.scm b/runtime/queries/gts/textobjects.scm
new file mode 100644
index 000000000000..5ad3ee1bb8b2
--- /dev/null
+++ b/runtime/queries/gts/textobjects.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_typescript,ecma