diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/scalar/ScalarDisableAutoConfiguration.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/scalar/ScalarDisableAutoConfiguration.java
index a8203969b1..456d0ed089 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/scalar/ScalarDisableAutoConfiguration.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/scalar/ScalarDisableAutoConfiguration.java
@@ -37,6 +37,19 @@
/**
* Disable Scalar WebJar AutoConfiguration.
+ *
+ *
The class stays in this module, because it is shared by both Springdoc Scalar starters, but it
+ * is no longer registered here. This module is a dependency of every starter, so a registration
+ * here made the filter apply to applications using the Swagger UI or the API-only starter as well,
+ * leaving them with neither Scalar controller (#3387). Each Springdoc Scalar starter now declares
+ * the filter in its own {@code META-INF/spring.factories}, which keeps the duplicate registration
+ * protection of #3084 while letting the standalone Scalar integration work everywhere it is not
+ * replaced.
+ *
+ *
Both Scalar auto-configurations are always excluded together, by design: Scalar's own
+ * {@code ScalarWebFluxAutoConfiguration} carries no {@code @ConditionalOnWebApplication}
+ * constraint, so excluding only the matching stack would let a reactive Scalar controller be
+ * registered in a servlet application, and the other way round.
*/
public class ScalarDisableAutoConfiguration
implements AutoConfigurationImportFilter {
diff --git a/springdoc-openapi-starter-common/src/test/java/org/springdoc/scalar/ScalarDisableAutoConfigurationTest.java b/springdoc-openapi-starter-common/src/test/java/org/springdoc/scalar/ScalarDisableAutoConfigurationTest.java
new file mode 100644
index 0000000000..fcede766c5
--- /dev/null
+++ b/springdoc-openapi-starter-common/src/test/java/org/springdoc/scalar/ScalarDisableAutoConfigurationTest.java
@@ -0,0 +1,80 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2026 the original author or authors.
+ * * * * * *
+ * * * * * * 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
+ * * * * * *
+ * * * * * * https://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 org.springdoc.scalar;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
+import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
+import org.springframework.core.io.support.SpringFactoriesLoader;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * springdoc-openapi-starter-common is pulled in by every starter: nothing that disables Scalar's
+ * standalone autoconfiguration may be registered from here, otherwise applications using the
+ * Swagger UI or the API-only starter lose the Scalar integration with nothing replacing it (#3387).
+ * The filter itself must keep excluding both Scalar auto-configurations, since it is the guard
+ * against the duplicate registration of #3084 once a Springdoc Scalar starter declares it.
+ *
+ * @author awinishere
+ */
+class ScalarDisableAutoConfigurationTest {
+
+ private static final String FILTER_CLASS = "org.springdoc.scalar.ScalarDisableAutoConfiguration";
+
+ private static final String[] SCALAR_AUTO_CONFIGURATIONS = {
+ "com.scalar.maven.webmvc.ScalarWebMvcAutoConfiguration",
+ "com.scalar.maven.webflux.ScalarWebFluxAutoConfiguration" };
+
+ private List registeredFilterNames() {
+ SpringFactoriesLoader loader = SpringFactoriesLoader
+ .forDefaultResourceLocation(getClass().getClassLoader());
+ return loader.load(AutoConfigurationImportFilter.class)
+ .stream()
+ .map(filter -> filter.getClass().getName())
+ .toList();
+ }
+
+ @Test
+ void noScalarAutoConfigurationImportFilterIsRegisteredFromThisModule() {
+
+ assertThat(registeredFilterNames()).doesNotContain(FILTER_CLASS);
+ }
+
+ @Test
+ void filterStillDisablesBothScalarAutoConfigurations() {
+
+ boolean[] matches = new ScalarDisableAutoConfiguration()
+ .match(SCALAR_AUTO_CONFIGURATIONS, (AutoConfigurationMetadata) null);
+
+ assertThat(matches).containsExactly(false, false);
+ }
+
+}
diff --git a/springdoc-openapi-starter-common/src/main/resources/META-INF/spring.factories b/springdoc-openapi-starter-webflux-scalar/src/main/resources/META-INF/spring.factories
similarity index 100%
rename from springdoc-openapi-starter-common/src/main/resources/META-INF/spring.factories
rename to springdoc-openapi-starter-webflux-scalar/src/main/resources/META-INF/spring.factories
diff --git a/springdoc-openapi-starter-webflux-scalar/src/test/java/test/org/springdoc/webflux/scalar/ScalarStarterRegistersTheDisableFilterTest.java b/springdoc-openapi-starter-webflux-scalar/src/test/java/test/org/springdoc/webflux/scalar/ScalarStarterRegistersTheDisableFilterTest.java
new file mode 100644
index 0000000000..b84c78120a
--- /dev/null
+++ b/springdoc-openapi-starter-webflux-scalar/src/test/java/test/org/springdoc/webflux/scalar/ScalarStarterRegistersTheDisableFilterTest.java
@@ -0,0 +1,62 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2026 the original author or authors.
+ * * * * * *
+ * * * * * * 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
+ * * * * * *
+ * * * * * * https://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 test.org.springdoc.webflux.scalar;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
+import org.springframework.core.io.support.SpringFactoriesLoader;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The exclusion of Scalar's standalone auto-configuration belongs to the Scalar starters: it is
+ * only legitimate where a Springdoc Scalar controller replaces it (#3387). It is declared in this
+ * module {@code META-INF/spring.factories}, and not in springdoc-openapi-starter-common, so that
+ * it is loaded exactly when this starter is installed.
+ *
+ * @author awinishere
+ */
+class ScalarStarterRegistersTheDisableFilterTest {
+
+ @Test
+ void scalarStarterDisablesTheStandaloneAutoConfiguration() {
+
+ SpringFactoriesLoader loader = SpringFactoriesLoader
+ .forDefaultResourceLocation(getClass().getClassLoader());
+
+ List registeredFilters = loader.load(AutoConfigurationImportFilter.class)
+ .stream()
+ .map(filter -> filter.getClass().getName())
+ .toList();
+
+ assertThat(registeredFilters).contains("org.springdoc.scalar.ScalarDisableAutoConfiguration");
+ }
+
+}
diff --git a/springdoc-openapi-starter-webmvc-scalar/src/main/resources/META-INF/spring.factories b/springdoc-openapi-starter-webmvc-scalar/src/main/resources/META-INF/spring.factories
new file mode 100644
index 0000000000..0b1ebd1193
--- /dev/null
+++ b/springdoc-openapi-starter-webmvc-scalar/src/main/resources/META-INF/spring.factories
@@ -0,0 +1,2 @@
+org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\
+org.springdoc.scalar.ScalarDisableAutoConfiguration
\ No newline at end of file
diff --git a/springdoc-openapi-starter-webmvc-scalar/src/test/java/test/org/springdoc/webmvc/scalar/ScalarStarterRegistersTheDisableFilterTest.java b/springdoc-openapi-starter-webmvc-scalar/src/test/java/test/org/springdoc/webmvc/scalar/ScalarStarterRegistersTheDisableFilterTest.java
new file mode 100644
index 0000000000..55d848dffc
--- /dev/null
+++ b/springdoc-openapi-starter-webmvc-scalar/src/test/java/test/org/springdoc/webmvc/scalar/ScalarStarterRegistersTheDisableFilterTest.java
@@ -0,0 +1,62 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2026 the original author or authors.
+ * * * * * *
+ * * * * * * 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
+ * * * * * *
+ * * * * * * https://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 test.org.springdoc.webmvc.scalar;
+
+import java.util.List;
+
+import org.junit.jupiter.api.Test;
+
+import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
+import org.springframework.core.io.support.SpringFactoriesLoader;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The exclusion of Scalar's standalone autoconfiguration belongs to the Scalar starters: it is
+ * only legitimate where a Springdoc Scalar controller replaces it (#3387). It is declared in this
+ * module {@code META-INF/spring.factories}, and not in springdoc-openapi-starter-common, so that
+ * it is loaded exactly when this starter is installed.
+ *
+ * @author awinishere
+ */
+class ScalarStarterRegistersTheDisableFilterTest {
+
+ @Test
+ void scalarStarterDisablesTheStandaloneAutoConfiguration() {
+
+ SpringFactoriesLoader loader = SpringFactoriesLoader
+ .forDefaultResourceLocation(getClass().getClassLoader());
+
+ List registeredFilters = loader.load(AutoConfigurationImportFilter.class)
+ .stream()
+ .map(filter -> filter.getClass().getName())
+ .toList();
+
+ assertThat(registeredFilters).contains("org.springdoc.scalar.ScalarDisableAutoConfiguration");
+ }
+
+}
diff --git a/springdoc-openapi-starter-webmvc-scalar/src/test/java/test/org/springdoc/webmvc/scalar/app20/SpringDocApp20Test.java b/springdoc-openapi-starter-webmvc-scalar/src/test/java/test/org/springdoc/webmvc/scalar/app20/SpringDocApp20Test.java
new file mode 100644
index 0000000000..ba4b38336a
--- /dev/null
+++ b/springdoc-openapi-starter-webmvc-scalar/src/test/java/test/org/springdoc/webmvc/scalar/app20/SpringDocApp20Test.java
@@ -0,0 +1,70 @@
+/*
+ *
+ * *
+ * * *
+ * * * *
+ * * * * *
+ * * * * * * Copyright 2019-2026 the original author or authors.
+ * * * * * *
+ * * * * * * 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
+ * * * * * *
+ * * * * * * https://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 test.org.springdoc.webmvc.scalar.app20;
+
+import com.scalar.maven.webmvc.ScalarWebMvcAutoConfiguration;
+import com.scalar.maven.webmvc.ScalarWebMvcController;
+import org.junit.jupiter.api.Test;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.context.ApplicationContext;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The Springdoc Scalar starter and Scalar's own integration both declare a bean named
+ * {@code scalarWebMvcController} mapped to {@code ${scalar.path}}: the standalone one must not
+ * survive next to the Springdoc controller, otherwise the application fails on a duplicated bean
+ * definition (#3084). This is the counterpart of the standalone Scalar support restored by #3387.
+ *
+ * @author awinishere
+ */
+@SpringBootTest
+class SpringDocApp20Test {
+
+ @Autowired
+ private ApplicationContext context;
+
+ @Test
+ void scalarStandaloneAutoConfigurationIsNotApplied() {
+
+ assertThat(context.getBeanNamesForType(ScalarWebMvcAutoConfiguration.class)).isEmpty();
+ assertThat(context.getBeanNamesForType(ScalarWebMvcController.class)).isEmpty();
+ }
+
+ @Test
+ void springdocScalarControllerReplacesIt() {
+
+ assertThat(context.getBean("scalarWebMvcController"))
+ .isInstanceOf(org.springdoc.webmvc.scalar.ScalarWebMvcController.class);
+ }
+
+ @SpringBootApplication
+ static class SpringDocTestApp {}
+}