diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index 8418138c8..f9d3dab20 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 ec3e36ed6..ace01e968 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 000000000..f410a1070
--- /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 000000000..830463168
--- /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.:
+((glimmer_template) @injection.content
+ (#set! injection.language "hbs"))
+
+; Parse Ember/Glimmer/Handlebars/HTMLBars/etc. template literals
+; e.g.: await render(hbs``)
+(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 000000000..519838521
--- /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 000000000..519838521
--- /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 000000000..519838521
--- /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 000000000..519838521
--- /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 000000000..519838521
--- /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 000000000..519838521
--- /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 000000000..5ad3ee1bb
--- /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 000000000..5ad3ee1bb
--- /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 000000000..5ad3ee1bb
--- /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 000000000..5ad3ee1bb
--- /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 000000000..5ad3ee1bb
--- /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 000000000..5ad3ee1bb
--- /dev/null
+++ b/runtime/queries/gts/textobjects.scm
@@ -0,0 +1 @@
+; inherits: _gjs,_typescript,ecma