diff --git a/homeassistant/components/blueprint/__init__.py b/homeassistant/components/blueprint/__init__.py
index 4c7b8e7f4c3f00cba4ebafc51787fac93701ec72..913f1ca517cb1d10aa2a23e494a6a3be7be66b47 100644
--- a/homeassistant/components/blueprint/__init__.py
+++ b/homeassistant/components/blueprint/__init__.py
@@ -8,6 +8,7 @@ from . import websocket_api
 from .const import CONF_USE_BLUEPRINT, DOMAIN  # noqa: F401
 from .errors import (  # noqa: F401
     BlueprintException,
+    BlueprintInUse,
     BlueprintWithNameException,
     FailedToLoad,
     InvalidBlueprint,
@@ -15,7 +16,11 @@ from .errors import (  # noqa: F401
     MissingInput,
 )
 from .models import Blueprint, BlueprintInputs, DomainBlueprints  # noqa: F401
-from .schemas import BLUEPRINT_SCHEMA, is_blueprint_instance_config  # noqa: F401
+from .schemas import (  # noqa: F401
+    BLUEPRINT_INSTANCE_FIELDS,
+    BLUEPRINT_SCHEMA,
+    is_blueprint_instance_config,
+)
 
 CONFIG_SCHEMA = cv.empty_config_schema(DOMAIN)
 
diff --git a/homeassistant/components/template/__init__.py b/homeassistant/components/template/__init__.py
index 5cd5b90e34f1787d2ed01a6267e8e8576680038c..390a4a31bdb7db75731e13efb83879e367670daa 100644
--- a/homeassistant/components/template/__init__.py
+++ b/homeassistant/components/template/__init__.py
@@ -29,6 +29,7 @@ from homeassistant.util.hass_dict import HassKey
 
 from .const import CONF_MAX, CONF_MIN, CONF_STEP, CONF_TRIGGER, DOMAIN, PLATFORMS
 from .coordinator import TriggerUpdateCoordinator
+from .helpers import async_get_blueprints
 
 _LOGGER = logging.getLogger(__name__)
 DATA_COORDINATORS: HassKey[list[TriggerUpdateCoordinator]] = HassKey(DOMAIN)
@@ -36,6 +37,17 @@ DATA_COORDINATORS: HassKey[list[TriggerUpdateCoordinator]] = HassKey(DOMAIN)
 
 async def async_setup(hass: HomeAssistant, config: ConfigType) -> bool:
     """Set up the template integration."""
+
+    # Register template as valid domain for Blueprint
+    blueprints = async_get_blueprints(hass)
+
+    # Add some default blueprints to blueprints/template, does nothing
+    # if blueprints/template already exists but still has to create
+    # an executor job to check if the folder exists so we run it in a
+    # separate task to avoid waiting for it to finish setting up
+    # since a tracked task will be waited at the end of startup
+    hass.async_create_task(blueprints.async_populate(), eager_start=True)
+
     if DOMAIN in config:
         await _process_config(hass, config)
 
@@ -136,7 +148,14 @@ async def _process_config(hass: HomeAssistant, hass_config: ConfigType) -> None:
                         DOMAIN,
                         {
                             "unique_id": conf_section.get(CONF_UNIQUE_ID),
-                            "entities": conf_section[platform_domain],
+                            "entities": [
+                                {
+                                    **entity_conf,
+                                    "raw_blueprint_inputs": conf_section.raw_blueprint_inputs,
+                                    "raw_configs": conf_section.raw_config,
+                                }
+                                for entity_conf in conf_section[platform_domain]
+                            ],
                         },
                         hass_config,
                     ),
diff --git a/homeassistant/components/template/blueprints/inverted_binary_sensor.yaml b/homeassistant/components/template/blueprints/inverted_binary_sensor.yaml
new file mode 100644
index 0000000000000000000000000000000000000000..5be18404a36662d7c948e7a41f30be36d8d10c15
--- /dev/null
+++ b/homeassistant/components/template/blueprints/inverted_binary_sensor.yaml
@@ -0,0 +1,27 @@
+blueprint:
+  name: Invert a binary sensor
+  description: Creates a binary_sensor which holds the inverted value of a reference binary_sensor
+  domain: template
+  source_url: https://github.com/home-assistant/core/blob/dev/homeassistant/components/template/blueprints/inverted_binary_sensor.yaml
+  input:
+    reference_entity:
+      name: Binary sensor to be inverted
+      description: The binary_sensor which needs to have its value inverted
+      selector:
+        entity:
+          domain: binary_sensor
+variables:
+  reference_entity: !input reference_entity
+binary_sensor:
+  state: >
+    {% if states(reference_entity) == 'on' %}
+      off
+    {% elif states(reference_entity) == 'off' %}
+      on
+    {% else %}
+      {{ states(reference_entity) }}
+    {% endif %}
+  # delay_on: not_used in this example
+  # delay_off: not_used in this example
+  # auto_off: not_used in this example
+  availability: "{{ states(reference_entity) not in ('unknown', 'unavailable') }}"
diff --git a/homeassistant/components/template/config.py b/homeassistant/components/template/config.py
index d75b111a6d010995156b05d3632fc5f576b4ac35..e0c5514def9d8a1e3d212cb9a4f05dff5ca701ea 100644
--- a/homeassistant/components/template/config.py
+++ b/homeassistant/components/template/config.py
@@ -1,10 +1,15 @@
 """Template config validator."""
 
+from contextlib import suppress
 import logging
 
 import voluptuous as vol
 
 from homeassistant.components.binary_sensor import DOMAIN as BINARY_SENSOR_DOMAIN
+from homeassistant.components.blueprint import (
+    BLUEPRINT_INSTANCE_FIELDS,
+    is_blueprint_instance_config,
+)
 from homeassistant.components.button import DOMAIN as BUTTON_DOMAIN
 from homeassistant.components.image import DOMAIN as IMAGE_DOMAIN
 from homeassistant.components.number import DOMAIN as NUMBER_DOMAIN
@@ -12,7 +17,13 @@ from homeassistant.components.select import DOMAIN as SELECT_DOMAIN
 from homeassistant.components.sensor import DOMAIN as SENSOR_DOMAIN
 from homeassistant.components.weather import DOMAIN as WEATHER_DOMAIN
 from homeassistant.config import async_log_schema_error, config_without_domain
-from homeassistant.const import CONF_BINARY_SENSORS, CONF_SENSORS, CONF_UNIQUE_ID
+from homeassistant.const import (
+    CONF_BINARY_SENSORS,
+    CONF_NAME,
+    CONF_SENSORS,
+    CONF_UNIQUE_ID,
+    CONF_VARIABLES,
+)
 from homeassistant.core import HomeAssistant
 from homeassistant.helpers import config_validation as cv
 from homeassistant.helpers.condition import async_validate_conditions_config
@@ -29,7 +40,15 @@ from . import (
     sensor as sensor_platform,
     weather as weather_platform,
 )
-from .const import CONF_ACTION, CONF_CONDITION, CONF_TRIGGER, DOMAIN
+from .const import (
+    CONF_ACTION,
+    CONF_CONDITION,
+    CONF_TRIGGER,
+    DOMAIN,
+    PLATFORMS,
+    TemplateConfig,
+)
+from .helpers import async_get_blueprints
 
 PACKAGE_MERGE_HINT = "list"
 
@@ -39,6 +58,7 @@ CONFIG_SECTION_SCHEMA = vol.Schema(
         vol.Optional(CONF_TRIGGER): cv.TRIGGER_SCHEMA,
         vol.Optional(CONF_CONDITION): cv.CONDITIONS_SCHEMA,
         vol.Optional(CONF_ACTION): cv.SCRIPT_SCHEMA,
+        vol.Optional(CONF_VARIABLES): cv.SCRIPT_VARIABLES_SCHEMA,
         vol.Optional(NUMBER_DOMAIN): vol.All(
             cv.ensure_list, [number_platform.NUMBER_SCHEMA]
         ),
@@ -66,9 +86,73 @@ CONFIG_SECTION_SCHEMA = vol.Schema(
         vol.Optional(WEATHER_DOMAIN): vol.All(
             cv.ensure_list, [weather_platform.WEATHER_SCHEMA]
         ),
-    }
+    },
 )
 
+TEMPLATE_BLUEPRINT_INSTANCE_SCHEMA = vol.Schema(
+    {
+        vol.Optional(CONF_NAME): cv.string,
+        vol.Optional(CONF_UNIQUE_ID): cv.string,
+    }
+).extend(BLUEPRINT_INSTANCE_FIELDS.schema)
+
+
+async def _async_resolve_blueprints(
+    hass: HomeAssistant,
+    config: ConfigType,
+) -> TemplateConfig:
+    """If a config item requires a blueprint, resolve that item to an actual config."""
+    raw_config = None
+    raw_blueprint_inputs = None
+
+    with suppress(ValueError):  # Invalid config
+        raw_config = dict(config)
+
+    if is_blueprint_instance_config(config):
+        config = TEMPLATE_BLUEPRINT_INSTANCE_SCHEMA(config)
+        blueprints = async_get_blueprints(hass)
+
+        blueprint_inputs = await blueprints.async_inputs_from_config(config)
+        raw_blueprint_inputs = blueprint_inputs.config_with_inputs
+
+        config = blueprint_inputs.async_substitute()
+
+        platforms = [platform for platform in PLATFORMS if platform in config]
+        if len(platforms) > 1:
+            raise vol.Invalid("more than one platform defined per blueprint")
+        if len(platforms) == 1:
+            platform = platforms.pop()
+            for prop in (CONF_NAME, CONF_UNIQUE_ID, CONF_VARIABLES):
+                if prop in config:
+                    config[platform][prop] = config.pop(prop)
+        raw_config = dict(config)
+
+    template_config = TemplateConfig(CONFIG_SECTION_SCHEMA(config))
+    template_config.raw_blueprint_inputs = raw_blueprint_inputs
+    template_config.raw_config = raw_config
+
+    return template_config
+
+
+async def async_validate_config_section(
+    hass: HomeAssistant, config: ConfigType
+) -> TemplateConfig:
+    """Validate an entire config section for the template integration."""
+
+    validated_config = await _async_resolve_blueprints(hass, config)
+
+    if CONF_TRIGGER in validated_config:
+        validated_config[CONF_TRIGGER] = await async_validate_trigger_config(
+            hass, validated_config[CONF_TRIGGER]
+        )
+
+    if CONF_CONDITION in validated_config:
+        validated_config[CONF_CONDITION] = await async_validate_conditions_config(
+            hass, validated_config[CONF_CONDITION]
+        )
+
+    return validated_config
+
 
 async def async_validate_config(hass: HomeAssistant, config: ConfigType) -> ConfigType:
     """Validate config."""
@@ -79,17 +163,9 @@ async def async_validate_config(hass: HomeAssistant, config: ConfigType) -> Conf
 
     for cfg in cv.ensure_list(config[DOMAIN]):
         try:
-            cfg = CONFIG_SECTION_SCHEMA(cfg)
-
-            if CONF_TRIGGER in cfg:
-                cfg[CONF_TRIGGER] = await async_validate_trigger_config(
-                    hass, cfg[CONF_TRIGGER]
-                )
-
-            if CONF_CONDITION in cfg:
-                cfg[CONF_CONDITION] = await async_validate_conditions_config(
-                    hass, cfg[CONF_CONDITION]
-                )
+            template_config: TemplateConfig = await async_validate_config_section(
+                hass, cfg
+            )
         except vol.Invalid as err:
             async_log_schema_error(err, DOMAIN, cfg, hass)
             async_notify_setup_error(hass, DOMAIN)
@@ -109,7 +185,7 @@ async def async_validate_config(hass: HomeAssistant, config: ConfigType) -> Conf
                 binary_sensor_platform.rewrite_legacy_to_modern_conf,
             ),
         ):
-            if old_key not in cfg:
+            if old_key not in template_config:
                 continue
 
             if not legacy_warn_printed:
@@ -121,11 +197,13 @@ async def async_validate_config(hass: HomeAssistant, config: ConfigType) -> Conf
                     "https://www.home-assistant.io/integrations/template#configuration-for-trigger-based-template-sensors"
                 )
 
-            definitions = list(cfg[new_key]) if new_key in cfg else []
-            definitions.extend(transform(hass, cfg[old_key]))
-            cfg = {**cfg, new_key: definitions}
+            definitions = (
+                list(template_config[new_key]) if new_key in template_config else []
+            )
+            definitions.extend(transform(hass, template_config[old_key]))
+            template_config = TemplateConfig({**template_config, new_key: definitions})
 
-        config_sections.append(cfg)
+        config_sections.append(template_config)
 
     # Create a copy of the configuration with all config for current
     # component removed and add validated config back in.
diff --git a/homeassistant/components/template/const.py b/homeassistant/components/template/const.py
index fc3f3c84b38d8696f64742c52171a2106d3d4e5c..f333d14797ef98c0b4a91f45100a13232b36859e 100644
--- a/homeassistant/components/template/const.py
+++ b/homeassistant/components/template/const.py
@@ -1,6 +1,8 @@
 """Constants for the Template Platform Components."""
 
+from homeassistant.components.blueprint import BLUEPRINT_SCHEMA
 from homeassistant.const import Platform
+from homeassistant.helpers.typing import ConfigType
 
 CONF_ACTION = "action"
 CONF_ATTRIBUTE_TEMPLATES = "attribute_templates"
@@ -38,3 +40,12 @@ PLATFORMS = [
     Platform.VACUUM,
     Platform.WEATHER,
 ]
+
+TEMPLATE_BLUEPRINT_SCHEMA = BLUEPRINT_SCHEMA
+
+
+class TemplateConfig(dict):
+    """Dummy class to allow adding attributes."""
+
+    raw_config: ConfigType | None = None
+    raw_blueprint_inputs: ConfigType | None = None
diff --git a/homeassistant/components/template/helpers.py b/homeassistant/components/template/helpers.py
new file mode 100644
index 0000000000000000000000000000000000000000..b320f2128cdf643446b38f51b3edea33f69074cf
--- /dev/null
+++ b/homeassistant/components/template/helpers.py
@@ -0,0 +1,63 @@
+"""Helpers for template integration."""
+
+import logging
+
+from homeassistant.components import blueprint
+from homeassistant.const import SERVICE_RELOAD
+from homeassistant.core import HomeAssistant, callback
+from homeassistant.helpers.entity_platform import async_get_platforms
+from homeassistant.helpers.singleton import singleton
+
+from .const import DOMAIN, TEMPLATE_BLUEPRINT_SCHEMA
+from .template_entity import TemplateEntity
+
+DATA_BLUEPRINTS = "template_blueprints"
+
+LOGGER = logging.getLogger(__name__)
+
+
+@callback
+def templates_with_blueprint(hass: HomeAssistant, blueprint_path: str) -> list[str]:
+    """Return all template entity ids that reference the blueprint."""
+    return [
+        entity_id
+        for platform in async_get_platforms(hass, DOMAIN)
+        for entity_id, template_entity in platform.entities.items()
+        if isinstance(template_entity, TemplateEntity)
+        and template_entity.referenced_blueprint == blueprint_path
+    ]
+
+
+@callback
+def blueprint_in_template(hass: HomeAssistant, entity_id: str) -> str | None:
+    """Return the blueprint the template entity is based on or None."""
+    for platform in async_get_platforms(hass, DOMAIN):
+        if isinstance(
+            (template_entity := platform.entities.get(entity_id)), TemplateEntity
+        ):
+            return template_entity.referenced_blueprint
+    return None
+
+
+def _blueprint_in_use(hass: HomeAssistant, blueprint_path: str) -> bool:
+    """Return True if any template references the blueprint."""
+    return len(templates_with_blueprint(hass, blueprint_path)) > 0
+
+
+async def _reload_blueprint_templates(hass: HomeAssistant, blueprint_path: str) -> None:
+    """Reload all templates that rely on a specific blueprint."""
+    await hass.services.async_call(DOMAIN, SERVICE_RELOAD)
+
+
+@singleton(DATA_BLUEPRINTS)
+@callback
+def async_get_blueprints(hass: HomeAssistant) -> blueprint.DomainBlueprints:
+    """Get template blueprints."""
+    return blueprint.DomainBlueprints(
+        hass,
+        DOMAIN,
+        LOGGER,
+        _blueprint_in_use,
+        _reload_blueprint_templates,
+        TEMPLATE_BLUEPRINT_SCHEMA,
+    )
diff --git a/homeassistant/components/template/manifest.json b/homeassistant/components/template/manifest.json
index 4112ca7a73fdd02884b1e1841d0c1b3579be7f6a..57188aebaa3f7f0c74c455ad3aed9395fa0d26d0 100644
--- a/homeassistant/components/template/manifest.json
+++ b/homeassistant/components/template/manifest.json
@@ -4,6 +4,7 @@
   "after_dependencies": ["group"],
   "codeowners": ["@PhracturedBlue", "@tetienne", "@home-assistant/core"],
   "config_flow": true,
+  "dependencies": ["blueprint"],
   "documentation": "https://www.home-assistant.io/integrations/template",
   "integration_type": "helper",
   "iot_class": "local_push",
diff --git a/homeassistant/components/template/template_entity.py b/homeassistant/components/template/template_entity.py
index ebb6aa3a48c49ed359bb5587a5a2c57c16d972e0..3e70e1c3546fcfc132bd2ceac4b46661150743ea 100644
--- a/homeassistant/components/template/template_entity.py
+++ b/homeassistant/components/template/template_entity.py
@@ -6,17 +6,20 @@ from collections.abc import Callable, Mapping
 import contextlib
 import itertools
 import logging
-from typing import Any
+from typing import Any, cast
 
 from propcache import under_cached_property
 import voluptuous as vol
 
+from homeassistant.components.blueprint import CONF_USE_BLUEPRINT
 from homeassistant.const import (
     CONF_ENTITY_PICTURE_TEMPLATE,
     CONF_FRIENDLY_NAME,
     CONF_ICON,
     CONF_ICON_TEMPLATE,
     CONF_NAME,
+    CONF_PATH,
+    CONF_VARIABLES,
     STATE_UNKNOWN,
 )
 from homeassistant.core import (
@@ -77,6 +80,7 @@ TEMPLATE_ENTITY_COMMON_SCHEMA = vol.Schema(
     {
         vol.Optional(CONF_ATTRIBUTES): vol.Schema({cv.string: cv.template}),
         vol.Optional(CONF_AVAILABILITY): cv.template,
+        vol.Optional(CONF_VARIABLES): cv.SCRIPT_VARIABLES_SCHEMA,
     }
 ).extend(TEMPLATE_ENTITY_BASE_SCHEMA.schema)
 
@@ -287,12 +291,16 @@ class TemplateEntity(Entity):  # pylint: disable=hass-enforce-class-module
             self._icon_template = icon_template
             self._entity_picture_template = entity_picture_template
             self._friendly_name_template = None
+            self._run_variables = {}
+            self._blueprint_inputs = None
         else:
             self._attribute_templates = config.get(CONF_ATTRIBUTES)
             self._availability_template = config.get(CONF_AVAILABILITY)
             self._icon_template = config.get(CONF_ICON)
             self._entity_picture_template = config.get(CONF_PICTURE)
             self._friendly_name_template = config.get(CONF_NAME)
+            self._run_variables = config.get(CONF_VARIABLES, {})
+            self._blueprint_inputs = config.get("raw_blueprint_inputs")
 
         class DummyState(State):
             """None-state for template entities not yet added to the state machine."""
@@ -331,6 +339,18 @@ class TemplateEntity(Entity):  # pylint: disable=hass-enforce-class-module
                     variables=variables, parse_result=False
                 )
 
+    @callback
+    def _render_variables(self) -> dict:
+        if isinstance(self._run_variables, dict):
+            return self._run_variables
+
+        return self._run_variables.async_render(
+            self.hass,
+            {
+                "this": TemplateStateFromEntityId(self.hass, self.entity_id),
+            },
+        )
+
     @callback
     def _update_available(self, result: str | TemplateError) -> None:
         if isinstance(result, TemplateError):
@@ -360,6 +380,13 @@ class TemplateEntity(Entity):  # pylint: disable=hass-enforce-class-module
             attribute_key, attribute_template, None, _update_attribute
         )
 
+    @property
+    def referenced_blueprint(self) -> str | None:
+        """Return referenced blueprint or None."""
+        if self._blueprint_inputs is None:
+            return None
+        return cast(str, self._blueprint_inputs[CONF_USE_BLUEPRINT][CONF_PATH])
+
     def add_template_attribute(
         self,
         attribute: str,
@@ -459,7 +486,10 @@ class TemplateEntity(Entity):  # pylint: disable=hass-enforce-class-module
         template_var_tups: list[TrackTemplate] = []
         has_availability_template = False
 
-        variables = {"this": TemplateStateFromEntityId(self.hass, self.entity_id)}
+        variables = {
+            "this": TemplateStateFromEntityId(self.hass, self.entity_id),
+            **self._render_variables(),
+        }
 
         for template, attributes in self._template_attrs.items():
             template_var_tup = TrackTemplate(template, variables)
@@ -563,6 +593,7 @@ class TemplateEntity(Entity):  # pylint: disable=hass-enforce-class-module
         await script.async_run(
             run_variables={
                 "this": TemplateStateFromEntityId(self.hass, self.entity_id),
+                **self._render_variables(),
                 **run_variables,
             },
             context=context,
diff --git a/tests/components/filter/test_sensor.py b/tests/components/filter/test_sensor.py
index a9581b78f4ed06e954b6a2cc7b8cd0fb764794f9..a3e0e58908a08061c81b800cfd5a0437a936f8e2 100644
--- a/tests/components/filter/test_sensor.py
+++ b/tests/components/filter/test_sensor.py
@@ -37,6 +37,11 @@ import homeassistant.util.dt as dt_util
 from tests.common import assert_setup_component, get_fixture_path
 
 
+@pytest.fixture(autouse=True, name="stub_blueprint_populate")
+def stub_blueprint_populate_autouse(stub_blueprint_populate: None) -> None:
+    """Stub copying the blueprints to the config folder."""
+
+
 @pytest.fixture(name="values")
 def values_fixture() -> list[State]:
     """Fixture for a list of test States."""
diff --git a/tests/components/template/conftest.py b/tests/components/template/conftest.py
index b37330b1bc4a1f9116be9bdddec2356f077252bf..bdca84ba071ad5e3efb5289e161638b6eacc1e0f 100644
--- a/tests/components/template/conftest.py
+++ b/tests/components/template/conftest.py
@@ -36,3 +36,8 @@ async def start_ha(
 async def caplog_setup_text(caplog: pytest.LogCaptureFixture) -> str:
     """Return setup log of integration."""
     return caplog.text
+
+
+@pytest.fixture(autouse=True, name="stub_blueprint_populate")
+def stub_blueprint_populate_autouse(stub_blueprint_populate: None) -> None:
+    """Stub copying the blueprints to the config folder."""
diff --git a/tests/components/template/test_blueprint.py b/tests/components/template/test_blueprint.py
new file mode 100644
index 0000000000000000000000000000000000000000..1df9e738b06d8523b9d9d7e8f8849d86cce557ca
--- /dev/null
+++ b/tests/components/template/test_blueprint.py
@@ -0,0 +1,242 @@
+"""Test blueprints."""
+
+from collections.abc import Iterator
+import contextlib
+from os import PathLike
+import pathlib
+from unittest.mock import MagicMock, patch
+
+import pytest
+
+from homeassistant.components import template
+from homeassistant.components.blueprint import (
+    BLUEPRINT_SCHEMA,
+    Blueprint,
+    BlueprintInUse,
+    DomainBlueprints,
+)
+from homeassistant.components.template import DOMAIN, SERVICE_RELOAD
+from homeassistant.core import HomeAssistant, callback
+from homeassistant.helpers import device_registry as dr
+from homeassistant.setup import async_setup_component
+from homeassistant.util import yaml
+
+from tests.common import async_mock_service
+
+BUILTIN_BLUEPRINT_FOLDER = pathlib.Path(template.__file__).parent / "blueprints"
+
+
+@contextlib.contextmanager
+def patch_blueprint(
+    blueprint_path: str, data_path: str | PathLike[str]
+) -> Iterator[None]:
+    """Patch blueprint loading from a different source."""
+    orig_load = DomainBlueprints._load_blueprint
+
+    @callback
+    def mock_load_blueprint(self, path):
+        if path != blueprint_path:
+            pytest.fail(f"Unexpected blueprint {path}")
+            return orig_load(self, path)
+
+        return Blueprint(
+            yaml.load_yaml(data_path),
+            expected_domain=self.domain,
+            path=path,
+            schema=BLUEPRINT_SCHEMA,
+        )
+
+    with patch(
+        "homeassistant.components.blueprint.models.DomainBlueprints._load_blueprint",
+        mock_load_blueprint,
+    ):
+        yield
+
+
+@contextlib.contextmanager
+def patch_invalid_blueprint() -> Iterator[None]:
+    """Patch blueprint returning an invalid one."""
+
+    @callback
+    def mock_load_blueprint(self, path):
+        return Blueprint(
+            {
+                "blueprint": {
+                    "domain": "template",
+                    "name": "Invalid template blueprint",
+                },
+                "binary_sensor": {},
+                "sensor": {},
+            },
+            expected_domain=self.domain,
+            path=path,
+            schema=BLUEPRINT_SCHEMA,
+        )
+
+    with patch(
+        "homeassistant.components.blueprint.models.DomainBlueprints._load_blueprint",
+        mock_load_blueprint,
+    ):
+        yield
+
+
+async def test_inverted_binary_sensor(
+    hass: HomeAssistant, device_registry: dr.DeviceRegistry
+) -> None:
+    """Test inverted binary sensor blueprint."""
+    hass.states.async_set("binary_sensor.foo", "on", {"friendly_name": "Foo"})
+    hass.states.async_set("binary_sensor.bar", "off", {"friendly_name": "Bar"})
+
+    with patch_blueprint(
+        "inverted_binary_sensor.yaml",
+        BUILTIN_BLUEPRINT_FOLDER / "inverted_binary_sensor.yaml",
+    ):
+        assert await async_setup_component(
+            hass,
+            "template",
+            {
+                "template": [
+                    {
+                        "use_blueprint": {
+                            "path": "inverted_binary_sensor.yaml",
+                            "input": {"reference_entity": "binary_sensor.foo"},
+                        },
+                        "name": "Inverted foo",
+                    },
+                    {
+                        "use_blueprint": {
+                            "path": "inverted_binary_sensor.yaml",
+                            "input": {"reference_entity": "binary_sensor.bar"},
+                        },
+                        "name": "Inverted bar",
+                    },
+                ]
+            },
+        )
+
+    hass.states.async_set("binary_sensor.foo", "off", {"friendly_name": "Foo"})
+    hass.states.async_set("binary_sensor.bar", "on", {"friendly_name": "Bar"})
+    await hass.async_block_till_done()
+
+    assert hass.states.get("binary_sensor.foo").state == "off"
+    assert hass.states.get("binary_sensor.bar").state == "on"
+
+    inverted_foo = hass.states.get("binary_sensor.inverted_foo")
+    assert inverted_foo
+    assert inverted_foo.state == "on"
+
+    inverted_bar = hass.states.get("binary_sensor.inverted_bar")
+    assert inverted_bar
+    assert inverted_bar.state == "off"
+
+    foo_template = template.helpers.blueprint_in_template(hass, "binary_sensor.foo")
+    inverted_foo_template = template.helpers.blueprint_in_template(
+        hass, "binary_sensor.inverted_foo"
+    )
+    assert foo_template is None
+    assert inverted_foo_template == "inverted_binary_sensor.yaml"
+
+    inverted_binary_sensor_blueprint_entity_ids = (
+        template.helpers.templates_with_blueprint(hass, "inverted_binary_sensor.yaml")
+    )
+    assert len(inverted_binary_sensor_blueprint_entity_ids) == 2
+
+    assert len(template.helpers.templates_with_blueprint(hass, "dummy.yaml")) == 0
+
+    with pytest.raises(BlueprintInUse):
+        await template.async_get_blueprints(hass).async_remove_blueprint(
+            "inverted_binary_sensor.yaml"
+        )
+
+
+async def test_domain_blueprint(hass: HomeAssistant) -> None:
+    """Test DomainBlueprint services."""
+    reload_handler_calls = async_mock_service(hass, DOMAIN, SERVICE_RELOAD)
+    mock_create_file = MagicMock()
+    mock_create_file.return_value = True
+
+    with patch(
+        "homeassistant.components.blueprint.models.DomainBlueprints._create_file",
+        mock_create_file,
+    ):
+        await template.async_get_blueprints(hass).async_add_blueprint(
+            Blueprint(
+                {
+                    "blueprint": {
+                        "domain": DOMAIN,
+                        "name": "Test",
+                    },
+                },
+                expected_domain="template",
+                path="xxx",
+                schema=BLUEPRINT_SCHEMA,
+            ),
+            "xxx",
+            True,
+        )
+    assert len(reload_handler_calls) == 1
+
+
+async def test_invalid_blueprint(
+    hass: HomeAssistant, caplog: pytest.LogCaptureFixture
+) -> None:
+    """Test an invalid blueprint definition."""
+
+    with patch_invalid_blueprint():
+        assert await async_setup_component(
+            hass,
+            "template",
+            {
+                "template": [
+                    {
+                        "use_blueprint": {
+                            "path": "invalid.yaml",
+                        },
+                        "name": "Invalid blueprint instance",
+                    },
+                ]
+            },
+        )
+
+    assert "more than one platform defined per blueprint" in caplog.text
+    assert await template.async_get_blueprints(hass).async_get_blueprints() == {}
+
+
+async def test_no_blueprint(hass: HomeAssistant) -> None:
+    """Test templates without blueprints."""
+    with patch_blueprint(
+        "inverted_binary_sensor.yaml",
+        BUILTIN_BLUEPRINT_FOLDER / "inverted_binary_sensor.yaml",
+    ):
+        assert await async_setup_component(
+            hass,
+            "template",
+            {
+                "template": [
+                    {"binary_sensor": {"name": "test entity", "state": "off"}},
+                    {
+                        "use_blueprint": {
+                            "path": "inverted_binary_sensor.yaml",
+                            "input": {"reference_entity": "binary_sensor.foo"},
+                        },
+                        "name": "inverted entity",
+                    },
+                ]
+            },
+        )
+
+    hass.states.async_set("binary_sensor.foo", "off", {"friendly_name": "Foo"})
+    await hass.async_block_till_done()
+
+    assert (
+        len(
+            template.helpers.templates_with_blueprint(
+                hass, "inverted_binary_sensor.yaml"
+            )
+        )
+        == 1
+    )
+    assert (
+        template.helpers.blueprint_in_template(hass, "binary_sensor.test_entity")
+        is None
+    )