diff --git a/htmx.routing.yml b/htmx.routing.yml
index 0f69664b34baff7b4d1bec355cd0408cc0d56014..bf4c1ef0d712d133ec3026ddf7c4dd7e3553eb7d 100644
--- a/htmx.routing.yml
+++ b/htmx.routing.yml
@@ -52,6 +52,19 @@ htmx_blocks.htmx_system_block_library:
     _admin_route: true
     _htmx_route: true
 
+htmx.htmx_entity_view:
+  path: '/htmx/{entityType}/{entity}/{viewMode}'
+  defaults:
+    _title: 'HTMX Entity View'
+    _controller: '\Drupal\htmx\Controller\HtmxEntityViewController::view'
+  requirements:
+    _entity_access: entity.view
+  options:
+    _htmx_route: true
+    parameters:
+      entity:
+        type: entity:{entityType}
+
 htmx_blocks.view:
   path: '/htmx/blocks/view/{block}'
   defaults:
diff --git a/src/Controller/HtmxEntityViewController.php b/src/Controller/HtmxEntityViewController.php
new file mode 100644
index 0000000000000000000000000000000000000000..96d3405599014259c257f1c1bf626642af63639c
--- /dev/null
+++ b/src/Controller/HtmxEntityViewController.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\htmx\Controller;
+
+use Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException;
+use Drupal\Core\Controller\ControllerBase;
+use Drupal\Core\Entity\EntityInterface;
+use Drupal\Core\Utility\Error;
+
+/**
+ * Returns an entity rendered in a view mode.
+ */
+final class HtmxEntityViewController extends ControllerBase {
+
+  /**
+   * Builds the response.
+   *
+   * @param string $entityType
+   *   The id of the entity type requested.
+   * @param \Drupal\Core\Entity\EntityInterface $entity
+   *   The entity upcast from the entity id in the request path.
+   * @param string $viewMode
+   *   The view mode to use in rendering the entity.
+   *
+   * @return mixed[]
+   *   The render array.
+   */
+  public function view(string $entityType, EntityInterface $entity, string $viewMode = 'default'): array {
+    $build = [];
+    try {
+      /** @var \Drupal\Core\Entity\EntityViewBuilderInterface $viewBuilder */
+      $viewBuilder = $this->entityTypeManager()->getViewBuilder($entityType);
+      $build = $viewBuilder->view($entity, $viewMode);
+    }
+    catch (InvalidPluginDefinitionException $e) {
+      /*
+       * \Drupal\Core\Entity\EntityTypeManager::getHandler() throws this
+       * exception when it cannot get the requested view builder.
+       */
+      Error::logException($this->getLogger('htmx'), $e);
+    }
+    return $build;
+  }
+
+}
diff --git a/tests/src/Kernel/HtmxEntityViewTest.php b/tests/src/Kernel/HtmxEntityViewTest.php
new file mode 100644
index 0000000000000000000000000000000000000000..994c182ade84daae1fcef8ba8befef56869eae17
--- /dev/null
+++ b/tests/src/Kernel/HtmxEntityViewTest.php
@@ -0,0 +1,73 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Tests\htmx\Kernel;
+
+use Drupal\htmx\Controller\HtmxEntityViewController;
+use Drupal\KernelTests\KernelTestBase;
+use Drupal\node\Entity\Node;
+use Drupal\node\NodeViewBuilder;
+use Drupal\Tests\node\Traits\NodeCreationTrait;
+
+/**
+ * Test description.
+ *
+ * @group htmx
+ */
+final class HtmxEntityViewTest extends KernelTestBase {
+
+  use NodeCreationTrait;
+
+  /**
+   * The class under test.
+   */
+  protected HtmxEntityViewController $controller;
+
+  /**
+   * {@inheritdoc}
+   */
+  protected static $modules = [
+    'htmx',
+    'node',
+    'datetime',
+    'user',
+    'system',
+    'filter',
+    'field',
+    'text',
+  ];
+
+  /**
+   * {@inheritdoc}
+   */
+  protected function setUp(): void {
+    parent::setUp();
+    $this->installConfig('filter');
+    $this->installConfig('node');
+    $this->installSchema('node', 'node_access');
+    $this->installEntitySchema('user');
+    $this->installEntitySchema('node');
+    $this->controller = HtmxEntityViewController::create($this->container);
+  }
+
+  /**
+   * Verify the render array has the appropriate properties.
+   */
+  public function testRenderArray(): void {
+    $node = $this->createNode(['type' => 'page']);
+    $renderArray = $this->controller->view('node', $node, 'teaser');
+    $this->assertArrayHasKey('#node', $renderArray);
+    $this->assertInstanceOf(Node::class, $renderArray['#node']);
+    $this->assertEquals($node->id(), $renderArray['#node']->id());
+    $this->assertArrayHasKey('#view_mode', $renderArray);
+    $this->assertEquals('teaser', $renderArray['#view_mode']);
+    $this->assertArrayHasKey('#theme', $renderArray);
+    $this->assertEquals('node', $renderArray['#theme']);
+    $this->assertArrayHasKey('#pre_render', $renderArray);
+    [$callbackObject, $method] = reset($renderArray['#pre_render']);
+    $this->assertInstanceOf(NodeViewBuilder::class, $callbackObject);
+    $this->assertEquals('build', $method);
+  }
+
+}