diff --git a/docs/source/about/changelog.rst b/docs/source/about/changelog.rst
index 30d595b94..b683ab4a4 100644
--- a/docs/source/about/changelog.rst
+++ b/docs/source/about/changelog.rst
@@ -40,11 +40,15 @@ v1.0.1
 **Changed**
 
 - :pull:`1050` - Warn and attempt to fix missing mime types, which can result in ``reactpy.run`` not working as expected.
+- :pull:`1051` - Rename ``reactpy.backend.BackendImplementation`` to ``reactpy.backend.BackendType``
+- :pull:`1051` - Allow ``reactpy.run`` to fail in more predictable ways
 
 **Fixed**
 
 - :issue:`930` - better traceback for JSON serialization errors (via :pull:`1008`)
 - :issue:`437` - explain that JS component attributes must be JSON (via :pull:`1008`)
+- :pull:`1051` - Fix ``reactpy.run`` port assignment sometimes attaching to in-use ports on Windows
+- :pull:`1051` - Fix ``reactpy.run`` not recognizing ``fastapi``
 
 
 v1.0.0
diff --git a/requirements.txt b/requirements.txt
deleted file mode 100644
index dab76855e..000000000
--- a/requirements.txt
+++ /dev/null
@@ -1,9 +0,0 @@
--r requirements/build-docs.txt
--r requirements/build-pkg.txt
--r requirements/check-style.txt
--r requirements/check-types.txt
--r requirements/make-release.txt
--r requirements/pkg-deps.txt
--r requirements/pkg-extras.txt
--r requirements/test-env.txt
--r requirements/nox-deps.txt
diff --git a/src/py/reactpy/reactpy/backend/_common.py b/src/py/reactpy/reactpy/backend/_common.py
index 17983a033..b4d6af19c 100644
--- a/src/py/reactpy/reactpy/backend/_common.py
+++ b/src/py/reactpy/reactpy/backend/_common.py
@@ -14,53 +14,49 @@
 from reactpy.utils import vdom_to_html
 
 if TYPE_CHECKING:
+    import uvicorn
     from asgiref.typing import ASGIApplication
 
 PATH_PREFIX = PurePosixPath("/_reactpy")
 MODULES_PATH = PATH_PREFIX / "modules"
 ASSETS_PATH = PATH_PREFIX / "assets"
 STREAM_PATH = PATH_PREFIX / "stream"
-
 CLIENT_BUILD_DIR = Path(_reactpy_file_path).parent / "_static" / "app" / "dist"
 
-try:
+
+async def serve_with_uvicorn(
+    app: ASGIApplication | Any,
+    host: str,
+    port: int,
+    started: asyncio.Event | None,
+) -> None:
+    """Run a development server for an ASGI application"""
     import uvicorn
-except ImportError:  # nocov
-    pass
-else:
-
-    async def serve_development_asgi(
-        app: ASGIApplication | Any,
-        host: str,
-        port: int,
-        started: asyncio.Event | None,
-    ) -> None:
-        """Run a development server for an ASGI application"""
-        server = uvicorn.Server(
-            uvicorn.Config(
-                app,
-                host=host,
-                port=port,
-                loop="asyncio",
-                reload=True,
-            )
+
+    server = uvicorn.Server(
+        uvicorn.Config(
+            app,
+            host=host,
+            port=port,
+            loop="asyncio",
         )
-        server.config.setup_event_loop()
-        coros: list[Awaitable[Any]] = [server.serve()]
+    )
+    server.config.setup_event_loop()
+    coros: list[Awaitable[Any]] = [server.serve()]
 
-        # If a started event is provided, then use it signal based on `server.started`
-        if started:
-            coros.append(_check_if_started(server, started))
+    # If a started event is provided, then use it signal based on `server.started`
+    if started:
+        coros.append(_check_if_started(server, started))
 
-        try:
-            await asyncio.gather(*coros)
-        finally:
-            # Since we aren't using the uvicorn's `run()` API, we can't guarantee uvicorn's
-            # order of operations. So we need to make sure `shutdown()` always has an initialized
-            # list of `self.servers` to use.
-            if not hasattr(server, "servers"):  # nocov
-                server.servers = []
-            await asyncio.wait_for(server.shutdown(), timeout=3)
+    try:
+        await asyncio.gather(*coros)
+    finally:
+        # Since we aren't using the uvicorn's `run()` API, we can't guarantee uvicorn's
+        # order of operations. So we need to make sure `shutdown()` always has an initialized
+        # list of `self.servers` to use.
+        if not hasattr(server, "servers"):  # nocov
+            server.servers = []
+        await asyncio.wait_for(server.shutdown(), timeout=3)
 
 
 async def _check_if_started(server: uvicorn.Server, started: asyncio.Event) -> None:
@@ -72,8 +68,7 @@ async def _check_if_started(server: uvicorn.Server, started: asyncio.Event) -> N
 def safe_client_build_dir_path(path: str) -> Path:
     """Prevent path traversal out of :data:`CLIENT_BUILD_DIR`"""
     return traversal_safe_path(
-        CLIENT_BUILD_DIR,
-        *("index.html" if path in ("", "/") else path).split("/"),
+        CLIENT_BUILD_DIR, *("index.html" if path in {"", "/"} else path).split("/")
     )
 
 
@@ -140,6 +135,9 @@ class CommonOptions:
     url_prefix: str = ""
     """The URL prefix where ReactPy resources will be served from"""
 
+    serve_index_route: bool = True
+    """Automatically generate and serve the index route (``/``)"""
+
     def __post_init__(self) -> None:
         if self.url_prefix and not self.url_prefix.startswith("/"):
             msg = "Expected 'url_prefix' to start with '/'"
diff --git a/src/py/reactpy/reactpy/backend/default.py b/src/py/reactpy/reactpy/backend/default.py
index 4ca192c1c..37aad31af 100644
--- a/src/py/reactpy/reactpy/backend/default.py
+++ b/src/py/reactpy/reactpy/backend/default.py
@@ -5,13 +5,26 @@
 from sys import exc_info
 from typing import Any, NoReturn
 
-from reactpy.backend.types import BackendImplementation
-from reactpy.backend.utils import SUPPORTED_PACKAGES, all_implementations
+from reactpy.backend.types import BackendType
+from reactpy.backend.utils import SUPPORTED_BACKENDS, all_implementations
 from reactpy.types import RootComponentConstructor
 
 logger = getLogger(__name__)
+_DEFAULT_IMPLEMENTATION: BackendType[Any] | None = None
 
 
+# BackendType.Options
+class Options:  # nocov
+    """Configuration options that can be provided to the backend.
+    This definition should not be used/instantiated. It exists only for
+    type hinting purposes."""
+
+    def __init__(self, *args: Any, **kwds: Any) -> NoReturn:
+        msg = "Default implementation has no options."
+        raise ValueError(msg)
+
+
+# BackendType.configure
 def configure(
     app: Any, component: RootComponentConstructor, options: None = None
 ) -> None:
@@ -22,17 +35,13 @@ def configure(
     return _default_implementation().configure(app, component)
 
 
+# BackendType.create_development_app
 def create_development_app() -> Any:
     """Create an application instance for development purposes"""
     return _default_implementation().create_development_app()
 
 
-def Options(*args: Any, **kwargs: Any) -> NoReturn:  # nocov
-    """Create configuration options"""
-    msg = "Default implementation has no options."
-    raise ValueError(msg)
-
-
+# BackendType.serve_development_app
 async def serve_development_app(
     app: Any,
     host: str,
@@ -45,10 +54,7 @@ async def serve_development_app(
     )
 
 
-_DEFAULT_IMPLEMENTATION: BackendImplementation[Any] | None = None
-
-
-def _default_implementation() -> BackendImplementation[Any]:
+def _default_implementation() -> BackendType[Any]:
     """Get the first available server implementation"""
     global _DEFAULT_IMPLEMENTATION  # noqa: PLW0603
 
@@ -59,7 +65,7 @@ def _default_implementation() -> BackendImplementation[Any]:
         implementation = next(all_implementations())
     except StopIteration:  # nocov
         logger.debug("Backend implementation import failed", exc_info=exc_info())
-        supported_backends = ", ".join(SUPPORTED_PACKAGES)
+        supported_backends = ", ".join(SUPPORTED_BACKENDS)
         msg = (
             "It seems you haven't installed a backend. To resolve this issue, "
             "you can install a backend by running:\n\n"
diff --git a/src/py/reactpy/reactpy/backend/fastapi.py b/src/py/reactpy/reactpy/backend/fastapi.py
index 575fce1fe..a0137a3dc 100644
--- a/src/py/reactpy/reactpy/backend/fastapi.py
+++ b/src/py/reactpy/reactpy/backend/fastapi.py
@@ -4,22 +4,22 @@
 
 from reactpy.backend import starlette
 
-serve_development_app = starlette.serve_development_app
-"""Alias for :func:`reactpy.backend.starlette.serve_development_app`"""
-
-use_connection = starlette.use_connection
-"""Alias for :func:`reactpy.backend.starlette.use_location`"""
-
-use_websocket = starlette.use_websocket
-"""Alias for :func:`reactpy.backend.starlette.use_websocket`"""
-
+# BackendType.Options
 Options = starlette.Options
-"""Alias for :class:`reactpy.backend.starlette.Options`"""
 
+# BackendType.configure
 configure = starlette.configure
-"""Alias for :class:`reactpy.backend.starlette.configure`"""
 
 
+# BackendType.create_development_app
 def create_development_app() -> FastAPI:
     """Create a development ``FastAPI`` application instance."""
     return FastAPI(debug=True)
+
+
+# BackendType.serve_development_app
+serve_development_app = starlette.serve_development_app
+
+use_connection = starlette.use_connection
+
+use_websocket = starlette.use_websocket
diff --git a/src/py/reactpy/reactpy/backend/flask.py b/src/py/reactpy/reactpy/backend/flask.py
index 46aed3c46..2e00e8f64 100644
--- a/src/py/reactpy/reactpy/backend/flask.py
+++ b/src/py/reactpy/reactpy/backend/flask.py
@@ -45,6 +45,19 @@
 logger = logging.getLogger(__name__)
 
 
+# BackendType.Options
+@dataclass
+class Options(CommonOptions):
+    """Render server config for :func:`reactpy.backend.flask.configure`"""
+
+    cors: bool | dict[str, Any] = False
+    """Enable or configure Cross Origin Resource Sharing (CORS)
+
+    For more information see docs for ``flask_cors.CORS``
+    """
+
+
+# BackendType.configure
 def configure(
     app: Flask, component: RootComponentConstructor, options: Options | None = None
 ) -> None:
@@ -69,20 +82,21 @@ def configure(
     app.register_blueprint(spa_bp)
 
 
+# BackendType.create_development_app
 def create_development_app() -> Flask:
     """Create an application instance for development purposes"""
     os.environ["FLASK_DEBUG"] = "true"
-    app = Flask(__name__)
-    return app
+    return Flask(__name__)
 
 
+# BackendType.serve_development_app
 async def serve_development_app(
     app: Flask,
     host: str,
     port: int,
     started: asyncio.Event | None = None,
 ) -> None:
-    """Run an application using a development server"""
+    """Run a development server for FastAPI"""
     loop = asyncio.get_running_loop()
     stopped = asyncio.Event()
 
@@ -135,17 +149,6 @@ def use_connection() -> Connection[_FlaskCarrier]:
     return conn
 
 
-@dataclass
-class Options(CommonOptions):
-    """Render server config for :func:`reactpy.backend.flask.configure`"""
-
-    cors: bool | dict[str, Any] = False
-    """Enable or configure Cross Origin Resource Sharing (CORS)
-
-    For more information see docs for ``flask_cors.CORS``
-    """
-
-
 def _setup_common_routes(
     api_blueprint: Blueprint,
     spa_blueprint: Blueprint,
@@ -166,10 +169,12 @@ def send_modules_dir(path: str = "") -> Any:
 
     index_html = read_client_index_html(options)
 
-    @spa_blueprint.route("/")
-    @spa_blueprint.route("/<path:_>")
-    def send_client_dir(_: str = "") -> Any:
-        return index_html
+    if options.serve_index_route:
+
+        @spa_blueprint.route("/")
+        @spa_blueprint.route("/<path:_>")
+        def send_client_dir(_: str = "") -> Any:
+            return index_html
 
 
 def _setup_single_view_dispatcher_route(
diff --git a/src/py/reactpy/reactpy/backend/sanic.py b/src/py/reactpy/reactpy/backend/sanic.py
index 53dd0ce68..3fd48db85 100644
--- a/src/py/reactpy/reactpy/backend/sanic.py
+++ b/src/py/reactpy/reactpy/backend/sanic.py
@@ -22,7 +22,7 @@
     read_client_index_html,
     safe_client_build_dir_path,
     safe_web_modules_dir_path,
-    serve_development_asgi,
+    serve_with_uvicorn,
 )
 from reactpy.backend.hooks import ConnectionContext
 from reactpy.backend.hooks import use_connection as _use_connection
@@ -34,6 +34,19 @@
 logger = logging.getLogger(__name__)
 
 
+# BackendType.Options
+@dataclass
+class Options(CommonOptions):
+    """Render server config for :func:`reactpy.backend.sanic.configure`"""
+
+    cors: bool | dict[str, Any] = False
+    """Enable or configure Cross Origin Resource Sharing (CORS)
+
+    For more information see docs for ``sanic_cors.CORS``
+    """
+
+
+# BackendType.configure
 def configure(
     app: Sanic, component: RootComponentConstructor, options: Options | None = None
 ) -> None:
@@ -49,14 +62,15 @@ def configure(
     app.blueprint([spa_bp, api_bp])
 
 
+# BackendType.create_development_app
 def create_development_app() -> Sanic:
     """Return a :class:`Sanic` app instance in test mode"""
     Sanic.test_mode = True
     logger.warning("Sanic.test_mode is now active")
-    app = Sanic(f"reactpy_development_app_{uuid4().hex}", Config())
-    return app
+    return Sanic(f"reactpy_development_app_{uuid4().hex}", Config())
 
 
+# BackendType.serve_development_app
 async def serve_development_app(
     app: Sanic,
     host: str,
@@ -64,7 +78,7 @@ async def serve_development_app(
     started: asyncio.Event | None = None,
 ) -> None:
     """Run a development server for :mod:`sanic`"""
-    await serve_development_asgi(app, host, port, started)
+    await serve_with_uvicorn(app, host, port, started)
 
 
 def use_request() -> request.Request:
@@ -86,17 +100,6 @@ def use_connection() -> Connection[_SanicCarrier]:
     return conn
 
 
-@dataclass
-class Options(CommonOptions):
-    """Render server config for :func:`reactpy.backend.sanic.configure`"""
-
-    cors: bool | dict[str, Any] = False
-    """Enable or configure Cross Origin Resource Sharing (CORS)
-
-    For more information see docs for ``sanic_cors.CORS``
-    """
-
-
 def _setup_common_routes(
     api_blueprint: Blueprint,
     spa_blueprint: Blueprint,
@@ -115,16 +118,17 @@ async def single_page_app_files(
     ) -> response.HTTPResponse:
         return response.html(index_html)
 
-    spa_blueprint.add_route(
-        single_page_app_files,
-        "/",
-        name="single_page_app_files_root",
-    )
-    spa_blueprint.add_route(
-        single_page_app_files,
-        "/<_:path>",
-        name="single_page_app_files_path",
-    )
+    if options.serve_index_route:
+        spa_blueprint.add_route(
+            single_page_app_files,
+            "/",
+            name="single_page_app_files_root",
+        )
+        spa_blueprint.add_route(
+            single_page_app_files,
+            "/<_:path>",
+            name="single_page_app_files_path",
+        )
 
     async def asset_files(
         request: request.Request,
diff --git a/src/py/reactpy/reactpy/backend/starlette.py b/src/py/reactpy/reactpy/backend/starlette.py
index 3a9695b33..2953b97b3 100644
--- a/src/py/reactpy/reactpy/backend/starlette.py
+++ b/src/py/reactpy/reactpy/backend/starlette.py
@@ -21,7 +21,7 @@
     STREAM_PATH,
     CommonOptions,
     read_client_index_html,
-    serve_development_asgi,
+    serve_with_uvicorn,
 )
 from reactpy.backend.hooks import ConnectionContext
 from reactpy.backend.hooks import use_connection as _use_connection
@@ -34,6 +34,19 @@
 logger = logging.getLogger(__name__)
 
 
+# BackendType.Options
+@dataclass
+class Options(CommonOptions):
+    """Render server config for :func:`reactpy.backend.starlette.configure`"""
+
+    cors: bool | dict[str, Any] = False
+    """Enable or configure Cross Origin Resource Sharing (CORS)
+
+    For more information see docs for ``starlette.middleware.cors.CORSMiddleware``
+    """
+
+
+# BackendType.configure
 def configure(
     app: Starlette,
     component: RootComponentConstructor,
@@ -54,11 +67,13 @@ def configure(
     _setup_common_routes(options, app)
 
 
+# BackendType.create_development_app
 def create_development_app() -> Starlette:
     """Return a :class:`Starlette` app instance in debug mode"""
     return Starlette(debug=True)
 
 
+# BackendType.serve_development_app
 async def serve_development_app(
     app: Starlette,
     host: str,
@@ -66,7 +81,7 @@ async def serve_development_app(
     started: asyncio.Event | None = None,
 ) -> None:
     """Run a development server for starlette"""
-    await serve_development_asgi(app, host, port, started)
+    await serve_with_uvicorn(app, host, port, started)
 
 
 def use_websocket() -> WebSocket:
@@ -82,17 +97,6 @@ def use_connection() -> Connection[WebSocket]:
     return conn
 
 
-@dataclass
-class Options(CommonOptions):
-    """Render server config for :func:`reactpy.backend.starlette.configure`"""
-
-    cors: bool | dict[str, Any] = False
-    """Enable or configure Cross Origin Resource Sharing (CORS)
-
-    For more information see docs for ``starlette.middleware.cors.CORSMiddleware``
-    """
-
-
 def _setup_common_routes(options: Options, app: Starlette) -> None:
     cors_options = options.cors
     if cors_options:  # nocov
@@ -115,8 +119,10 @@ def _setup_common_routes(options: Options, app: Starlette) -> None:
     )
     # register this last so it takes least priority
     index_route = _make_index_route(options)
-    app.add_route(url_prefix + "/", index_route)
-    app.add_route(url_prefix + "/{path:path}", index_route)
+
+    if options.serve_index_route:
+        app.add_route(f"{url_prefix}/", index_route)
+        app.add_route(url_prefix + "/{path:path}", index_route)
 
 
 def _make_index_route(options: Options) -> Callable[[Request], Awaitable[HTMLResponse]]:
diff --git a/src/py/reactpy/reactpy/backend/tornado.py b/src/py/reactpy/reactpy/backend/tornado.py
index 5ec877532..8f540ddb4 100644
--- a/src/py/reactpy/reactpy/backend/tornado.py
+++ b/src/py/reactpy/reactpy/backend/tornado.py
@@ -32,10 +32,11 @@
 from reactpy.core.serve import serve_layout
 from reactpy.core.types import ComponentConstructor
 
+# BackendType.Options
 Options = CommonOptions
-"""Render server config for :func:`reactpy.backend.tornado.configure`"""
 
 
+# BackendType.configure
 def configure(
     app: Application,
     component: ComponentConstructor,
@@ -60,10 +61,12 @@ def configure(
     )
 
 
+# BackendType.create_development_app
 def create_development_app() -> Application:
     return Application(debug=True)
 
 
+# BackendType.serve_development_app
 async def serve_development_app(
     app: Application,
     host: str,
@@ -119,12 +122,17 @@ def _setup_common_routes(options: Options) -> _RouteHandlerSpecs:
             StaticFileHandler,
             {"path": str(CLIENT_BUILD_DIR / "assets")},
         ),
-        (
-            r"/(.*)",
-            IndexHandler,
-            {"index_html": read_client_index_html(options)},
-        ),
-    ]
+    ] + (
+        [
+            (
+                r"/(.*)",
+                IndexHandler,
+                {"index_html": read_client_index_html(options)},
+            ),
+        ]
+        if options.serve_index_route
+        else []
+    )
 
 
 def _add_handler(
diff --git a/src/py/reactpy/reactpy/backend/types.py b/src/py/reactpy/reactpy/backend/types.py
index fbc4addc0..51e7bef04 100644
--- a/src/py/reactpy/reactpy/backend/types.py
+++ b/src/py/reactpy/reactpy/backend/types.py
@@ -11,11 +11,11 @@
 
 
 @runtime_checkable
-class BackendImplementation(Protocol[_App]):
+class BackendType(Protocol[_App]):
     """Common interface for built-in web server/framework integrations"""
 
     Options: Callable[..., Any]
-    """A constructor for options passed to :meth:`BackendImplementation.configure`"""
+    """A constructor for options passed to :meth:`BackendType.configure`"""
 
     def configure(
         self,
diff --git a/src/py/reactpy/reactpy/backend/utils.py b/src/py/reactpy/reactpy/backend/utils.py
index 3d9be13a4..183e801f5 100644
--- a/src/py/reactpy/reactpy/backend/utils.py
+++ b/src/py/reactpy/reactpy/backend/utils.py
@@ -3,22 +3,23 @@
 import asyncio
 import logging
 import socket
+import sys
 from collections.abc import Iterator
 from contextlib import closing
 from importlib import import_module
 from typing import Any
 
-from reactpy.backend.types import BackendImplementation
+from reactpy.backend.types import BackendType
 from reactpy.types import RootComponentConstructor
 
 logger = logging.getLogger(__name__)
 
-SUPPORTED_PACKAGES = (
-    "starlette",
+SUPPORTED_BACKENDS = (
     "fastapi",
     "sanic",
     "tornado",
     "flask",
+    "starlette",
 )
 
 
@@ -26,43 +27,37 @@ def run(
     component: RootComponentConstructor,
     host: str = "127.0.0.1",
     port: int | None = None,
-    implementation: BackendImplementation[Any] | None = None,
+    implementation: BackendType[Any] | None = None,
 ) -> None:
     """Run a component with a development server"""
     logger.warning(_DEVELOPMENT_RUN_FUNC_WARNING)
 
     implementation = implementation or import_module("reactpy.backend.default")
-
     app = implementation.create_development_app()
     implementation.configure(app, component)
-
-    host = host
     port = port or find_available_port(host)
-
     app_cls = type(app)
+
     logger.info(
-        f"Running with {app_cls.__module__}.{app_cls.__name__} at http://{host}:{port}"
+        "ReactPy is running with '%s.%s' at http://%s:%s",
+        app_cls.__module__,
+        app_cls.__name__,
+        host,
+        port,
     )
-
     asyncio.run(implementation.serve_development_app(app, host, port))
 
 
-def find_available_port(
-    host: str,
-    port_min: int = 8000,
-    port_max: int = 9000,
-    allow_reuse_waiting_ports: bool = True,
-) -> int:
+def find_available_port(host: str, port_min: int = 8000, port_max: int = 9000) -> int:
     """Get a port that's available for the given host and port range"""
     for port in range(port_min, port_max):
         with closing(socket.socket()) as sock:
             try:
-                if allow_reuse_waiting_ports:
-                    # As per this answer: https://stackoverflow.com/a/19247688/3159288
-                    # setting can be somewhat unreliable because we allow the use of
-                    # ports that are stuck in TIME_WAIT. However, not setting the option
-                    # means we're overly cautious and almost always use a different addr
-                    # even if it could have actually been used.
+                if sys.platform == "linux":
+                    # Fixes bug where every time you restart the server you'll
+                    # get a different port on Linux. This cannot be set on Windows
+                    # otherwise address will always be reused.
+                    # Ref: https://stackoverflow.com/a/19247688/3159288
                     sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
                 sock.bind((host, port))
             except OSError:
@@ -73,26 +68,20 @@ def find_available_port(
     raise RuntimeError(msg)
 
 
-def all_implementations() -> Iterator[BackendImplementation[Any]]:
+def all_implementations() -> Iterator[BackendType[Any]]:
     """Yield all available server implementations"""
-    for name in SUPPORTED_PACKAGES:
+    for name in SUPPORTED_BACKENDS:
         try:
-            relative_import_name = f"{__name__.rsplit('.', 1)[0]}.{name}"
-            module = import_module(relative_import_name)
+            import_module(name)
         except ImportError:  # nocov
-            logger.debug(f"Failed to import {name!r}", exc_info=True)
+            logger.debug("Failed to import %s", name, exc_info=True)
             continue
 
-        if not isinstance(module, BackendImplementation):  # nocov
-            msg = f"{module.__name__!r} is an invalid implementation"
-            raise TypeError(msg)
-
-        yield module
+        reactpy_backend_name = f"{__name__.rsplit('.', 1)[0]}.{name}"
+        yield import_module(reactpy_backend_name)
 
 
-_DEVELOPMENT_RUN_FUNC_WARNING = f"""\
-The `run()` function is only intended for testing during development! To run in \
-production, consider selecting a supported backend and importing its associated \
-`configure()` function from `reactpy.backend.<package>` where `<package>` is one of \
-{list(SUPPORTED_PACKAGES)}. For details refer to the docs on how to run each package.\
+_DEVELOPMENT_RUN_FUNC_WARNING = """\
+The `run()` function is only intended for testing during development! To run \
+in production, refer to the docs on how to use reactpy.backend.*.configure.\
 """
diff --git a/src/py/reactpy/reactpy/testing/backend.py b/src/py/reactpy/reactpy/testing/backend.py
index 549e16056..b699f3071 100644
--- a/src/py/reactpy/reactpy/testing/backend.py
+++ b/src/py/reactpy/reactpy/testing/backend.py
@@ -2,13 +2,13 @@
 
 import asyncio
 import logging
-from contextlib import AsyncExitStack
+from contextlib import AsyncExitStack, suppress
 from types import TracebackType
 from typing import Any, Callable
 from urllib.parse import urlencode, urlunparse
 
 from reactpy.backend import default as default_server
-from reactpy.backend.types import BackendImplementation
+from reactpy.backend.types import BackendType
 from reactpy.backend.utils import find_available_port
 from reactpy.config import REACTPY_TESTING_DEFAULT_TIMEOUT
 from reactpy.core.component import component
@@ -43,21 +43,20 @@ def __init__(
         host: str = "127.0.0.1",
         port: int | None = None,
         app: Any | None = None,
-        implementation: BackendImplementation[Any] | None = None,
+        implementation: BackendType[Any] | None = None,
         options: Any | None = None,
         timeout: float | None = None,
     ) -> None:
         self.host = host
-        self.port = port or find_available_port(host, allow_reuse_waiting_ports=False)
+        self.port = port or find_available_port(host)
         self.mount, self._root_component = _hotswap()
         self.timeout = (
             REACTPY_TESTING_DEFAULT_TIMEOUT.current if timeout is None else timeout
         )
 
-        if app is not None:
-            if implementation is None:
-                msg = "If an application instance its corresponding server implementation must be provided too."
-                raise ValueError(msg)
+        if app is not None and implementation is None:
+            msg = "If an application instance its corresponding server implementation must be provided too."
+            raise ValueError(msg)
 
         self._app = app
         self.implementation = implementation or default_server
@@ -124,10 +123,8 @@ async def __aenter__(self) -> BackendFixture:
 
         async def stop_server() -> None:
             server_future.cancel()
-            try:
+            with suppress(asyncio.CancelledError):
                 await asyncio.wait_for(server_future, timeout=self.timeout)
-            except asyncio.CancelledError:
-                pass
 
         self._exit_stack.push_async_callback(stop_server)
 
diff --git a/src/py/reactpy/reactpy/types.py b/src/py/reactpy/reactpy/types.py
index 715b66fff..4766fe801 100644
--- a/src/py/reactpy/reactpy/types.py
+++ b/src/py/reactpy/reactpy/types.py
@@ -4,7 +4,7 @@
 - :mod:`reactpy.backend.types`
 """
 
-from reactpy.backend.types import BackendImplementation, Connection, Location
+from reactpy.backend.types import BackendType, Connection, Location
 from reactpy.core.component import Component
 from reactpy.core.hooks import Context
 from reactpy.core.types import (
@@ -27,7 +27,7 @@
 )
 
 __all__ = [
-    "BackendImplementation",
+    "BackendType",
     "Component",
     "ComponentConstructor",
     "ComponentType",
diff --git a/src/py/reactpy/tests/test_backend/test_all.py b/src/py/reactpy/tests/test_backend/test_all.py
index 11b9693a2..d697e5d3f 100644
--- a/src/py/reactpy/tests/test_backend/test_all.py
+++ b/src/py/reactpy/tests/test_backend/test_all.py
@@ -6,7 +6,7 @@
 from reactpy import html
 from reactpy.backend import default as default_implementation
 from reactpy.backend._common import PATH_PREFIX
-from reactpy.backend.types import BackendImplementation, Connection, Location
+from reactpy.backend.types import BackendType, Connection, Location
 from reactpy.backend.utils import all_implementations
 from reactpy.testing import BackendFixture, DisplayFixture, poll
 
@@ -17,7 +17,7 @@
     scope="module",
 )
 async def display(page, request):
-    imp: BackendImplementation = request.param
+    imp: BackendType = request.param
 
     # we do this to check that route priorities for each backend are correct
     if imp is default_implementation:
@@ -158,7 +158,7 @@ def ShowRoute():
 
 
 @pytest.mark.parametrize("imp", all_implementations())
-async def test_customized_head(imp: BackendImplementation, page):
+async def test_customized_head(imp: BackendType, page):
     custom_title = f"Custom Title for {imp.__name__}"
 
     @reactpy.component