diff --git a/pom.xml b/pom.xml
index 0d8e0ff6a7a..a46814020ad 100644
--- a/pom.xml
+++ b/pom.xml
@@ -66,6 +66,7 @@
vaadin-slider-flow-parent
vaadin-master-detail-layout-flow-parent
vaadin-ai-components-flow-parent
+ test-app
scm:https:https://github.com/vaadin/flow-components.git
diff --git a/test-app/README.md b/test-app/README.md
new file mode 100644
index 00000000000..82c055add66
--- /dev/null
+++ b/test-app/README.md
@@ -0,0 +1,17 @@
+# Test App
+
+Sandbox app for testing various combinations of components from this repo. All component modules are on the classpath. No stylesheet is loaded by default (`@NoTheme` in `AppShell.java` — see its javadoc for enabling Lumo or Aura).
+
+## Running
+
+```sh
+mvn package jetty:run -am -B -DskipTests -pl test-app
+```
+
+Then open http://localhost:8080. The server runs in dev mode with frontend hot deploy, but needs a restart after Java changes.
+
+To stop:
+
+```sh
+mvn jetty:stop -pl test-app
+```
diff --git a/test-app/pom.xml b/test-app/pom.xml
new file mode 100644
index 00000000000..6923b2e123d
--- /dev/null
+++ b/test-app/pom.xml
@@ -0,0 +1,357 @@
+
+
+ 4.0.0
+
+ com.vaadin
+ vaadin-flow-components
+ 25.3-SNAPSHOT
+
+ test-app
+ war
+ Test App
+ Sandbox app for testing combinations of components
+
+
+ com.vaadin
+ flow-client
+
+
+ com.vaadin
+ flow-data
+
+
+ com.vaadin
+ flow-html-components
+
+
+ com.vaadin
+ vaadin-accordion-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-ai-components-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-app-layout-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-aura-theme
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-avatar-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-badge-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-board-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-breadcrumbs-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-button-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-card-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-charts-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-checkbox-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-combo-box-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-confirm-dialog-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-context-menu-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-crud-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-custom-field-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-dashboard-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-date-picker-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-date-time-picker-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-details-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-dev-server
+
+
+ com.vaadin
+ vaadin-dialog-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-field-highlighter-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-form-layout-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-grid-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-grid-pro-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-icons-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-list-box-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-login-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-lumo-theme
+
+
+ com.vaadin
+ vaadin-map-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-markdown-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-master-detail-layout-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-menu-bar-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-messages-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-notification-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-ordered-layout-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-popover-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-progress-bar-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-radio-button-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-renderer-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-rich-text-editor-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-select-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-side-nav-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-slider-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-split-layout-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-spreadsheet-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-tabs-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-text-field-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-time-picker-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-upload-flow
+ ${project.version}
+
+
+ com.vaadin
+ vaadin-virtual-list-flow
+ ${project.version}
+
+
+ org.slf4j
+ slf4j-simple
+
+
+
+
+
+ maven-clean-plugin
+
+
+
+ ${project.basedir}
+
+ package*.json
+ pnpm*
+ vite.generated.ts
+ types.d.ts
+ tsconfig.json
+ frontend/routes.tsx
+ frontend/App.tsx
+
+
+
+ ${project.basedir}/node_modules
+
+
+ ${project.basedir}/frontend/generated
+
+
+
+
+
+ com.vaadin
+ flow-maven-plugin
+
+
+ org.eclipse.jetty.ee10
+ jetty-ee10-maven-plugin
+
+
+
+ start-jetty
+ none
+
+
+ stop-jetty
+ none
+
+
+
+
+ maven-install-plugin
+
+ true
+
+
+
+ org.sonatype.plugins
+ nexus-staging-maven-plugin
+
+ true
+
+
+
+
+
diff --git a/test-app/src/main/java/com/vaadin/testapp/AppShell.java b/test-app/src/main/java/com/vaadin/testapp/AppShell.java
new file mode 100644
index 00000000000..3510412ea9e
--- /dev/null
+++ b/test-app/src/main/java/com/vaadin/testapp/AppShell.java
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2000-2026 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testapp;
+
+import com.vaadin.flow.component.page.AppShellConfigurator;
+
+public class AppShell implements AppShellConfigurator {
+}
diff --git a/test-app/src/main/java/com/vaadin/testapp/MainView.java b/test-app/src/main/java/com/vaadin/testapp/MainView.java
new file mode 100644
index 00000000000..270e0e78322
--- /dev/null
+++ b/test-app/src/main/java/com/vaadin/testapp/MainView.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2000-2026 Vaadin Ltd.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.vaadin.testapp;
+
+import com.vaadin.flow.component.html.Div;
+import com.vaadin.flow.router.Route;
+
+@Route("")
+public class MainView extends Div {
+ public MainView() {
+
+ }
+}
diff --git a/test-app/vite.config.ts b/test-app/vite.config.ts
new file mode 100644
index 00000000000..a62a861ce3b
--- /dev/null
+++ b/test-app/vite.config.ts
@@ -0,0 +1,16 @@
+// @ts-ignore can not be resolved until NPM packages are installed
+import { defineConfig, UserConfigFn } from 'vite';
+// @ts-ignore can not be resolved until Flow generates base Vite config
+import { vaadinConfig } from './vite.generated';
+import { sharedConfig, mergeConfigs } from '../shared/shared-vite-config';
+
+const customConfig: UserConfigFn = (env) => ({
+ // Here you can add custom Vite parameters
+ // https://vitejs.dev/config/
+});
+
+export default defineConfig((env) => mergeConfigs(
+ vaadinConfig(env),
+ sharedConfig(env),
+ customConfig(env)
+));