diff --git a/.changeset/nine-cobras-stare.md b/.changeset/nine-cobras-stare.md
new file mode 100644
index 000000000000..9b48f256e6dc
--- /dev/null
+++ b/.changeset/nine-cobras-stare.md
@@ -0,0 +1,5 @@
+---
+'svelte': patch
+---
+
+feat: warn for lowercase `object.component` rendering
\ No newline at end of file
diff --git a/packages/svelte/messages/compile-warnings/template.md b/packages/svelte/messages/compile-warnings/template.md
index 58a251c729f9..3bd2ff4878ce 100644
--- a/packages/svelte/messages/compile-warnings/template.md
+++ b/packages/svelte/messages/compile-warnings/template.md
@@ -38,6 +38,10 @@
> Using `on:%name%` to listen to the %name% event is deprecated. Use the event attribute `on%name%` instead
+## lowercase_component_rendering
+
+> Are you trying to render `%component%`? Component names should be uppercase.
+
## node_invalid_placement_ssr
> %thing% is invalid inside `<%parent%>`. When rendering this component on the server, the resulting HTML will be modified by the browser, likely resulting in a `hydration_mismatch` warning
diff --git a/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js b/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js
index 5c15f70ba2d5..4c2f696e661b 100644
--- a/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js
+++ b/packages/svelte/src/compiler/phases/2-analyze/visitors/RegularElement.js
@@ -78,6 +78,16 @@ export function RegularElement(node, context) {
}
const binding = context.state.scope.get(node.name);
+
+ if (context.state.analysis.runes && node.name.includes('.')) {
+ const [maybe_object] = node.name.split('.');
+ const object_binding = context.state.scope.get(maybe_object);
+
+ if (object_binding) {
+ w.lowercase_component_rendering(node, node.name);
+ }
+ }
+
if (
binding !== null &&
binding.declaration_kind === 'import' &&
diff --git a/packages/svelte/src/compiler/warnings.js b/packages/svelte/src/compiler/warnings.js
index facd53cdec92..1e2153cd3760 100644
--- a/packages/svelte/src/compiler/warnings.js
+++ b/packages/svelte/src/compiler/warnings.js
@@ -115,6 +115,7 @@ export const codes = [
"component_name_lowercase",
"element_invalid_self_closing_tag",
"event_directive_deprecated",
+ "lowercase_component_rendering",
"node_invalid_placement_ssr",
"slot_element_deprecated",
"svelte_element_invalid_this"
@@ -749,6 +750,15 @@ export function event_directive_deprecated(node, name) {
w(node, "event_directive_deprecated", `Using \`on:${name}\` to listen to the ${name} event is deprecated. Use the event attribute \`on${name}\` instead`);
}
+/**
+ * Are you trying to render `%component%`? Component names should be uppercase.
+ * @param {null | NodeLike} node
+ * @param {string} component
+ */
+export function lowercase_component_rendering(node, component) {
+ w(node, "lowercase_component_rendering", `Are you trying to render \`${component}\`? Component names should be uppercase.`);
+}
+
/**
* %thing% is invalid inside `<%parent%>`. When rendering this component on the server, the resulting HTML will be modified by the browser, likely resulting in a `hydration_mismatch` warning
* @param {null | NodeLike} node
diff --git a/packages/svelte/tests/validator/samples/lowercase-component-rendering/input.svelte b/packages/svelte/tests/validator/samples/lowercase-component-rendering/input.svelte
new file mode 100644
index 000000000000..042c9d4f0645
--- /dev/null
+++ b/packages/svelte/tests/validator/samples/lowercase-component-rendering/input.svelte
@@ -0,0 +1,7 @@
+
+
+
+
+
diff --git a/packages/svelte/tests/validator/samples/lowercase-component-rendering/warnings.json b/packages/svelte/tests/validator/samples/lowercase-component-rendering/warnings.json
new file mode 100644
index 000000000000..742e8bdf5999
--- /dev/null
+++ b/packages/svelte/tests/validator/samples/lowercase-component-rendering/warnings.json
@@ -0,0 +1,14 @@
+[
+ {
+ "code": "lowercase_component_rendering",
+ "message": "Are you trying to render `component.component`? Component names should be uppercase.",
+ "start": {
+ "line": 5,
+ "column": 0
+ },
+ "end": {
+ "line": 5,
+ "column": 43
+ }
+ }
+]