diff --git a/superset/templates/superset/spa.html b/superset/templates/superset/spa.html
index e9edc718739..8ca114b3cf3 100644
--- a/superset/templates/superset/spa.html
+++ b/superset/templates/superset/spa.html
@@ -67,6 +67,11 @@
{% endblock %}
+ {{ css_bundle(assets_prefix, 'theme') }}
+ {% if entry %}
+ {{ css_bundle(assets_prefix, entry) }}
+ {% endif %}
+
{{ js_bundle(assets_prefix, 'theme') }}
{% block head_js %}
diff --git a/tests/unit_tests/extension_tests.py b/tests/unit_tests/extension_tests.py
index 724b03f01a2..b2b91fea26a 100644
--- a/tests/unit_tests/extension_tests.py
+++ b/tests/unit_tests/extension_tests.py
@@ -14,12 +14,13 @@
# KIND, either express or implied. See the License for the
# specific language governing permissions and limitations
# under the License.
-from os.path import dirname
+from os.path import dirname, join
from unittest.mock import Mock
from superset.extensions import UIManifestProcessor
APP_DIR = f"{dirname(__file__)}/fixtures"
+SUPERSET_DIR = join(dirname(__file__), "..", "..", "superset")
def test_get_manifest_with_prefix():
@@ -49,3 +50,21 @@ def test_get_manifest_no_prefix():
assert manifest["js_manifest"]("styles") == ["/static/dist/styles-js.js"]
assert manifest["css_manifest"]("styles") == []
assert manifest["assets_prefix"] == ""
+
+
+def test_spa_template_includes_css_bundles():
+ """
+ Verify spa.html loads CSS bundles for production builds.
+ """
+ template_path = join(SUPERSET_DIR, "templates", "superset", "spa.html")
+ with open(template_path) as f:
+ template_content = f.read()
+
+ assert "css_bundle(assets_prefix, 'theme')" in template_content, (
+ "spa.html must call css_bundle for the 'theme' entry to load "
+ "extracted CSS (including font @font-face declarations) in production builds"
+ )
+ assert "css_bundle(assets_prefix, entry)" in template_content, (
+ "spa.html must call css_bundle for the page entry to load "
+ "entry-specific extracted CSS in production builds"
+ )