diff --git a/Classes/Controller/DateController.php b/Classes/Controller/DateController.php
index 4cfd0fb..338d6f7 100644
--- a/Classes/Controller/DateController.php
+++ b/Classes/Controller/DateController.php
@@ -7,6 +7,7 @@ namespace WerkraumMedia\Events\Controller;
 use Exception;
 use Psr\Http\Message\ResponseInterface;
 use Throwable;
+use TYPO3\CMS\Core\Http\PropagateResponseException;
 use TYPO3\CMS\Extbase\Annotation as Extbase;
 use TYPO3\CMS\Extbase\Service\ExtensionService;
 use WerkraumMedia\Events\Domain\Model\Date;
@@ -38,13 +39,13 @@ final class DateController extends AbstractController
     {
         parent::initializeAction();
 
+        $this->handlePostRequests();
+
         $contentObject = $this->request->getAttribute('currentContentObject');
         if ($contentObject !== null) {
             $this->demandFactory->setContentObjectRenderer($contentObject);
         }
         $this->dataProcessing->setConfigurationManager($this->configurationManager);
-
-        $this->handlePostRequest();
     }
 
     public function listAction(
@@ -127,22 +128,34 @@ final class DateController extends AbstractController
      *
      * @see: https://en.wikipedia.org/wiki/Post/Redirect/Get
      */
-    private function handlePostRequest(): void
+    private function handlePostRequests(): void
     {
-        if (
-            $this->request->getMethod() === 'POST'
-            && $this->request->hasArgument('search')
-            && is_array($this->request->getArgument('search'))
-        ) {
-            $namespace = $this->extensionService->getPluginNamespace(null, null);
+        if ($this->request->getMethod() !== 'POST') {
+            return;
+        }
+
+        $searchArguments = [];
+        if ($this->request->hasArgument('search')) {
+            $searchArguments = $this->request->getArgument('search');
+        }
+        if (is_array($searchArguments) === false) {
+            $searchArguments = [];
+        }
+        $searchArguments = array_filter($searchArguments);
+
+        $parameter = [];
+        if ($searchArguments !== []) {
+            $parameter['search'] = $searchArguments;
+        }
+
+        $namespace = $this->extensionService->getPluginNamespace(null, null);
+
+        throw new PropagateResponseException(
             $this->redirectToUri($this->request->getAttribute('currentContentObject')->typoLink_URL([
                 'parameter' => 't3://page?uid=current',
-                'additionalParams' => '&' . http_build_query([
-                    $namespace => [
-                        'search' => array_filter($this->request->getArgument('search')),
-                    ],
-                ]),
-            ]));
-        }
+                'additionalParams' => '&' . http_build_query([$namespace => $parameter]),
+            ])),
+            303
+        );
     }
 }
diff --git a/Classes/Middleware/AddSearchArgumentsToRouteArgumentsMiddleware.php b/Classes/Middleware/AddSearchArgumentsToRouteArgumentsMiddleware.php
new file mode 100644
index 0000000..fe00a53
--- /dev/null
+++ b/Classes/Middleware/AddSearchArgumentsToRouteArgumentsMiddleware.php
@@ -0,0 +1,81 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * Copyright (C) 2025 Daniel Siepmann <daniel.siepmann@codappix.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+namespace WerkraumMedia\Events\Middleware;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use TYPO3\CMS\Core\Routing\PageArguments;
+use TYPO3\CMS\Core\Utility\ArrayUtility;
+
+/**
+ * Right now I couldn't find any way to add the search parameter to the pagination via addQueryString.
+ * The issue is that these are not part of TYPO3 routing. Nested lists like categories also seem impossible to configure for routing.
+ *
+ * See corresponding core issue: https://forge.typo3.org/issues/105941
+ */
+final class AddSearchArgumentsToRouteArgumentsMiddleware implements MiddlewareInterface
+{
+    public function __construct(
+        private readonly string $routingPath = 'events/search',
+    ) {
+    }
+
+    public function process(
+        ServerRequestInterface $request,
+        RequestHandlerInterface $handler
+    ): ResponseInterface {
+        $previousResult = $request->getAttribute('routing', null);
+        if ($previousResult instanceof PageArguments) {
+            $request = $request->withAttribute('routing', $this->extendPageArguments($previousResult));
+        }
+
+        return $handler->handle($request);
+    }
+
+    private function extendPageArguments(PageArguments $pageArguments): PageArguments
+    {
+        $dynamicArguments = $pageArguments->getDynamicArguments();
+
+        if (ArrayUtility::isValidPath($dynamicArguments, $this->routingPath) === false) {
+            return $pageArguments;
+        }
+
+        $routeArguments = ArrayUtility::setValueByPath(
+            $pageArguments->getRouteArguments(),
+            $this->routingPath,
+            ArrayUtility::getValueByPath($dynamicArguments, $this->routingPath)
+        );
+        $remainingArguments = ArrayUtility::removeByPath($dynamicArguments, $this->routingPath);
+
+        return new PageArguments(
+            $pageArguments->getPageId(),
+            $pageArguments->getPageType(),
+            $routeArguments,
+            $pageArguments->getStaticArguments(),
+            $remainingArguments,
+        );
+    }
+}
diff --git a/Configuration/CeRouting.yaml b/Configuration/CeRouting.yaml
index 3137846..97e80f3 100644
--- a/Configuration/CeRouting.yaml
+++ b/Configuration/CeRouting.yaml
@@ -17,7 +17,9 @@ routeEnhancers:
   EventsPagination:
     type: Plugin
     namespace: events
-    routePath: '/{localizedPage}-{currentPage}'
+    routePath: '/{localizedPage}-{currentPage}/{controller}'
+    defaults:
+      controller: 'Date'
     aspects:
       localizedPage:
         type: LocaleModifier
diff --git a/Configuration/RequestMiddlewares.php b/Configuration/RequestMiddlewares.php
new file mode 100644
index 0000000..453090b
--- /dev/null
+++ b/Configuration/RequestMiddlewares.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+use WerkraumMedia\Events\Middleware\AddSearchArgumentsToRouteArgumentsMiddleware;
+
+return [
+    'frontend' => [
+        'werkraummedia/events/add-search-arguments-to-route-arguments' => [
+            'target' => AddSearchArgumentsToRouteArgumentsMiddleware::class,
+            'after' => [
+                'typo3/cms-frontend/page-resolver',
+            ],
+            'before' => [
+                'typo3/cms-frontend/page-argument-validator',
+            ],
+        ],
+    ],
+];
diff --git a/Documentation/Changelog/5.0.0.rst b/Documentation/Changelog/5.0.0.rst
index 4fe4e45..b03307b 100644
--- a/Documentation/Changelog/5.0.0.rst
+++ b/Documentation/Changelog/5.0.0.rst
@@ -44,6 +44,9 @@ Fixes
 * Ensure pagination settings are provided in expected type (int).
   TypoScript settings will always be strings, so we fix this with a proper type cast.
 
+* Fix broken pagination routing in combination with active search for TYPO3 12.4 and onwards.
+  See: :ref:`searchPagination`.
+
 Tasks
 -----
 
diff --git a/Documentation/Features/SearchPagination.rst b/Documentation/Features/SearchPagination.rst
new file mode 100644
index 0000000..b344324
--- /dev/null
+++ b/Documentation/Features/SearchPagination.rst
@@ -0,0 +1,25 @@
+.. index:: single: Search
+.. _searchPagination:
+
+Search Pagination
+=================
+
+The extension supports pagination of search results.
+Please properly configure the system. Add the following `TYPO3_CONF_VARS` configuration:
+
+.. code-block:: php
+
+   'FE' => [
+       'cacheHash' => [
+           'excludedParameters' => [
+               '^events[search]',
+           ],
+       ],
+   ],
+
+Adopt the configuration to your own setup, e.g. change the `pluginNamespace` from `events` to whatever you've configured.
+And ensure the involved plugins are excluded from caching (`USER_INT`).
+
+The extension will assume `events[search]` as default namespace for search arguments.
+Please make use of Services files and Dependency Injection to configure the custom
+`AddSearchArgumentsToRouteArgumentsMiddleware` middleware with your own namespace.
diff --git a/Tests/Functional/Frontend/Fixtures/Database/SearchSetup.php b/Tests/Functional/Frontend/Fixtures/Database/SearchSetup.php
new file mode 100644
index 0000000..42b4d80
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Database/SearchSetup.php
@@ -0,0 +1,57 @@
+<?php
+
+declare(strict_types=1);
+
+return [
+    'tt_content' => [
+        [
+            'pid' => '1',
+            'uid' => '1',
+            'CType' => 'cefilter_filter',
+            'header' => 'Search Form',
+        ],
+        [
+            'pid' => '1',
+            'uid' => '2',
+            'CType' => 'celist_list',
+            'header' => 'Search Results',
+        ],
+    ],
+    'tx_events_domain_model_event' => [
+        [
+            'uid' => '1',
+            'pid' => '2',
+            'title' => 'Event one',
+            'teaser' => 'Some Teaser',
+        ],
+        [
+            'uid' => '2',
+            'pid' => '2',
+            'title' => 'Event two',
+            'teaser' => 'Another teaser',
+        ],
+    ],
+    'tx_events_domain_model_date' => [
+        [
+            'uid' => '1',
+            'pid' => '2',
+            'event' => '1',
+            'start' => '1661626800',
+            'end' => '1661632200',
+        ],
+        [
+            'uid' => '2',
+            'pid' => '2',
+            'event' => '1',
+            'start' => '1660158000',
+            'end' => '1660163400',
+        ],
+        [
+            'uid' => '3',
+            'pid' => '2',
+            'event' => '2',
+            'start' => '1661194800',
+            'end' => '1661200200',
+        ],
+    ],
+];
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/Configuration/TypoScript/Setup.typoscript b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/Configuration/TypoScript/Setup.typoscript
new file mode 100644
index 0000000..47f670c
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/Configuration/TypoScript/Setup.typoscript
@@ -0,0 +1,9 @@
+tt_content.cefilter_filter.20 {
+    view {
+        pluginNamespace = events
+    }
+
+    persistence {
+        storagePid = 2
+    }
+}
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/Resources/Private/Templates/Date/Search.html b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/Resources/Private/Templates/Date/Search.html
new file mode 100644
index 0000000..94090ae
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/Resources/Private/Templates/Date/Search.html
@@ -0,0 +1,53 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+
+    <div class="row">
+        <div class="col-12 col-md-8 offset-md-4">
+            <div class="panel panel-default">
+                <div class="panel-body">
+                    <f:form method="post" name="search" object="{demand}">
+                        <div class="row mb-3">
+                            <div class="col-md-12">
+                                <div class="form-group">
+                                    <label for="searchword">Searchword</label>
+                                    <f:form.textfield type="text" class="form-control" id="searchword" property="searchword" value="{searchword}" />
+                                </div>
+                            </div>
+                        </div>
+                        <div class="row mb-3">
+                            <div class="col col-md-6">
+                                <div class="form-group">
+                                    <label for="start">From:</label>
+                                    <f:form.textfield type="date" class="form-control" id="start" property="start" />
+                                </div>
+                            </div>
+                            <div class="col col-md-6">
+                                <div class="form-group">
+                                    <label for="end">To:</label>
+                                    <f:form.textfield type="date" class="form-control" id="end" property="end" />
+                                </div>
+                            </div>
+                        </div>
+
+                        <f:if condition="{categories}">
+                            <div class="row mb-3">
+                                <f:for each="{categories}" as="category">
+                                    <div class="col-md-4 d-none d-lg-block">
+                                        <div class="form-check">
+                                            <f:form.checkbox class="form-check-input" property="userCategories" value="{category.uid}" id="check_{category.uid}"/>
+                                            <label class="form-check-label" for="check_{category.uid}">{category.title} {category.amountOfEvents}</label>
+                                        </div>
+                                    </div>
+                                </f:for>
+                            </div>
+                        </f:if>
+
+                        <div class="form-group mb-3">
+                            <f:form.submit value="Search" class="btn btn-primary" />
+                        </div>
+                    </f:form>
+                </div>
+            </div>
+        </div>
+    </div>
+
+</html>
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/composer.json b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/composer.json
new file mode 100644
index 0000000..ecd35d6
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/composer.json
@@ -0,0 +1,16 @@
+{
+    "name": "werkraummedia/ce-events-filter",
+    "type": "typo3-cms-extension",
+    "description": "Content element: EXT:events filter",
+    "license": "GPL-2.0-or-later",
+    "version": "v1.0.0",
+    "require": {
+        "typo3/cms-core": "*",
+        "typo3/cms-extbase": "*"
+    },
+    "extra": {
+        "typo3/cms": {
+            "extension-key": "ce_filter"
+        }
+    }
+}
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/ext_emconf.php b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/ext_emconf.php
new file mode 100644
index 0000000..2e39e72
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/ext_emconf.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+$EM_CONF['ce_filter'] = [
+    'title' => 'Events filter',
+    'description' => 'Content Element for \'Events\'',
+    'category' => 'plugin',
+    'version' => '1.0.0',
+    'constraints' => [
+        'depends' => [
+            'typo3' => '*',
+            'events' => '*',
+        ],
+        'conflicts' => [
+        ],
+        'suggests' => [
+        ],
+    ],
+];
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/ext_localconf.php b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/ext_localconf.php
new file mode 100644
index 0000000..f3a0251
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/ext_localconf.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptSetup(
+    '@import "EXT:ce_filter/Configuration/TypoScript/Setup.typoscript"'
+);
+
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+    'CeFilter',
+    'filter',
+    [
+        \WerkraumMedia\Events\Controller\DateController::class => 'search',
+    ],
+    [
+        \WerkraumMedia\Events\Controller\DateController::class => 'search',
+    ],
+    \TYPO3\CMS\Extbase\Utility\ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT
+);
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Configuration/TypoScript/Setup.typoscript b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Configuration/TypoScript/Setup.typoscript
new file mode 100644
index 0000000..fab3308
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Configuration/TypoScript/Setup.typoscript
@@ -0,0 +1,15 @@
+tt_content.celist_list.20 {
+    view {
+        pluginNamespace = events
+    }
+
+    persistence {
+        storagePid = 2
+    }
+
+    settings {
+        sortByDate = start
+        sortOrder = ASC
+        itemsPerPage = 1
+    }
+}
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Resources/Private/Partials/Pagination.html b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Resources/Private/Partials/Pagination.html
new file mode 100644
index 0000000..48f68e2
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Resources/Private/Partials/Pagination.html
@@ -0,0 +1,94 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers"
+    data-namespace-typo3-fluid="true">
+
+    <nav role="navigation" aria-label="Pagination Navigation">
+        <ul class="pagination">
+            <f:if condition="{pagination.previousPageNumber}">
+                <li class="page-item">
+                    <f:if condition="{pagination.previousPageNumber} > 1">
+                        <f:then>
+                            <a class="page-link"
+                                href="{f:uri.action(addQueryString: 1, arguments: {currentPage: pagination.previousPageNumber})}"
+                            >
+                                <span aria-hidden="true">&laquo;</span>
+                            </a>
+                        </f:then>
+                        <f:else>
+                            <a class="page-link" href="{f:uri.action(addQueryString: 1)}">
+                                <span aria-hidden="true">&laquo;</span>
+                            </a>
+                        </f:else>
+                    </f:if>
+                </li>
+            </f:if>
+
+            <f:if condition="{pagination.displayRangeStart} > 1">
+                <li class="page-item">
+                    <a class="page-link"
+                        href="{f:uri.action(addQueryString: 1)}"
+                        aria-label="Goto Page 1"
+                    >
+                        1
+                    </a>
+                </li>
+            </f:if>
+
+            <f:if condition="{pagination.hasLessPages}">
+                <li class="page-item">
+                    <span class="page-link">…</span>
+                </li>
+            </f:if>
+
+            <f:for each="{pagination.allPageNumbers}" as="page">
+                <f:if condition="{page} == {pagination.paginator.currentPageNumber}">
+                    <f:then>
+                        <li class="page-item active">
+                            <span class="page-link"
+                                aria-label="Current Page {page}"
+                                aria-current="true"
+                            >{page}</span>
+                        </li>
+                    </f:then>
+                    <f:else>
+                        <li class="page-item">
+                            <a class="page-link"
+                                href="{f:uri.action(addQueryString: 1, arguments: {currentPage: page})}"
+                                aria-label="Goto Page {page}"
+                            >
+                                {page}
+                            </a>
+                        </li>
+                    </f:else>
+                </f:if>
+            </f:for>
+
+            <f:if condition="{pagination.hasMorePages}">
+                <li class="page-item">
+                    <span class="page-link">…</span>
+                </li>
+            </f:if>
+
+            <f:if condition="{pagination.displayRangeEnd} < {pagination.lastPageNumber}">
+                <li class="page-item">
+                    <a class="page-link"
+                        href="{f:uri.action(addQueryString: 1, arguments: {currentPage: pagination.lastPageNumber})}"
+                        aria-label="Goto Page {pagination.lastPageNumber}"
+                    >
+                        {pagination.lastPageNumber}
+                    </a>
+                </li>
+            </f:if>
+
+            <f:if condition="{pagination.nextPageNumber}">
+                <li class="page-item">
+                    <a class="page-link"
+                        href="{f:uri.action(addQueryString: 1, arguments: {currentPage: pagination.nextPageNumber})}"
+                    >
+                      <span aria-hidden="true">&raquo;</span>
+                    </a>
+                </li>
+            </f:if>
+        </ul>
+    </nav>
+
+</html>
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Resources/Private/Templates/Date/List.html b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Resources/Private/Templates/Date/List.html
new file mode 100644
index 0000000..3bfb675
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/Resources/Private/Templates/Date/List.html
@@ -0,0 +1,29 @@
+<html xmlns:f="http://typo3.org/ns/TYPO3/CMS/Fluid/ViewHelpers" data-namespace-typo3-fluid="true">
+
+<f:if condition="{pagination.paginator.paginatedItems}">
+    <section class="events-list" data-uniform="height">
+
+        <f:for each="{pagination.paginator.paginatedItems}" as="date" iteration="index">
+            <div class="row mb-5">
+                <h3>
+                    {date.event.title}
+                </h3>
+
+                <p>
+                    <f:format.crop maxCharacters="160" respectHtml="true"
+                        respectWordBoundaries="true">
+                        {date.event.teaser}</f:format.crop>
+                </p>
+            </div>
+        </f:for>
+
+    </section>
+
+    <section class="events-list-pagination">
+        {f:render(partial: 'Pagination', arguments: {
+            pagination: pagination
+        })}
+    </section>
+</f:if>
+
+</html>
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/composer.json b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/composer.json
new file mode 100644
index 0000000..d3ab706
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/composer.json
@@ -0,0 +1,16 @@
+{
+    "name": "werkraummedia/ce-list",
+    "type": "typo3-cms-extension",
+    "description": "Content element: EXT:events list",
+    "license": "GPL-2.0-or-later",
+    "version": "v1.0.0",
+    "require": {
+        "typo3/cms-core": "*",
+        "typo3/cms-extbase": "*"
+    },
+    "extra": {
+        "typo3/cms": {
+            "extension-key": "ce_list"
+        }
+    }
+}
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/ext_emconf.php b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/ext_emconf.php
new file mode 100644
index 0000000..82aa72d
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/ext_emconf.php
@@ -0,0 +1,20 @@
+<?php
+
+declare(strict_types=1);
+
+$EM_CONF['ce_list'] = [
+    'title' => 'Events list view',
+    'description' => 'Content Elements for \'Events\'',
+    'category' => 'plugin',
+    'version' => '1.0.0',
+    'constraints' => [
+        'depends' => [
+            'typo3' => '*',
+            'events' => '*',
+        ],
+        'conflicts' => [
+        ],
+        'suggests' => [
+        ],
+    ],
+];
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/ext_localconf.php b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/ext_localconf.php
new file mode 100644
index 0000000..8282237
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/ext_localconf.php
@@ -0,0 +1,19 @@
+<?php
+
+declare(strict_types=1);
+
+\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTypoScriptSetup(
+    '@import "EXT:ce_list/Configuration/TypoScript/Setup.typoscript"'
+);
+
+\TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin(
+    'CeList',
+    'list',
+    [
+        \WerkraumMedia\Events\Controller\DateController::class => 'list',
+    ],
+    [
+        \WerkraumMedia\Events\Controller\DateController::class => 'list',
+    ],
+    \TYPO3\CMS\Extbase\Utility\ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT
+);
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/example/Classes/TestingDateTimeAspectMiddleware.php b/Tests/Functional/Frontend/Fixtures/Extensions/example/Classes/TestingDateTimeAspectMiddleware.php
new file mode 100644
index 0000000..64b4bac
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/example/Classes/TestingDateTimeAspectMiddleware.php
@@ -0,0 +1,54 @@
+<?php
+
+declare(strict_types=1);
+
+/*
+ * Copyright (C) 2025 Daniel Siepmann <daniel.siepmann@codappix.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+ * 02110-1301, USA.
+ */
+
+namespace WerkraumMedia\EventsExample;
+
+use Psr\Http\Message\ResponseInterface;
+use Psr\Http\Message\ServerRequestInterface;
+use Psr\Http\Server\MiddlewareInterface;
+use Psr\Http\Server\RequestHandlerInterface;
+use TYPO3\CMS\Core\Context\Context;
+use TYPO3\CMS\Core\Context\DateTimeAspect;
+
+/**
+ * Allows us to set a specific DateTimeAspect for requests within tests.
+ */
+final class TestingDateTimeAspectMiddleware implements MiddlewareInterface
+{
+    public function __construct(
+        private readonly Context $context,
+    ) {
+    }
+
+    public function process(
+        ServerRequestInterface $request,
+        RequestHandlerInterface $handler
+    ): ResponseInterface {
+        $testingDateAspect = $request->getAttribute('testingDateAspect');
+        if ($testingDateAspect instanceof DateTimeAspect) {
+            $this->context->setAspect('date', $testingDateAspect);
+        }
+
+        return $handler->handle($request);
+    }
+}
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/example/Configuration/RequestMiddlewares.php b/Tests/Functional/Frontend/Fixtures/Extensions/example/Configuration/RequestMiddlewares.php
new file mode 100644
index 0000000..53c4371
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/example/Configuration/RequestMiddlewares.php
@@ -0,0 +1,16 @@
+<?php
+
+declare(strict_types=1);
+
+use WerkraumMedia\EventsExample\TestingDateTimeAspectMiddleware;
+
+return [
+    'frontend' => [
+        'werkraummedia/events/testing-date-time-aspect' => [
+            'target' => TestingDateTimeAspectMiddleware::class,
+            'before' => [
+                'typo3/cms-frontend/timetracker',
+            ],
+        ],
+    ],
+];
diff --git a/Tests/Functional/Frontend/Fixtures/Extensions/example/Configuration/Services.php b/Tests/Functional/Frontend/Fixtures/Extensions/example/Configuration/Services.php
new file mode 100644
index 0000000..f206382
--- /dev/null
+++ b/Tests/Functional/Frontend/Fixtures/Extensions/example/Configuration/Services.php
@@ -0,0 +1,15 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Symfony\Component\DependencyInjection\Loader\Configurator;
+
+return static function (ContainerConfigurator $containerConfigurator) {
+    $services = $containerConfigurator->services()
+        ->defaults()
+        ->autowire()
+        ->autoconfigure()
+    ;
+
+    $services->load('WerkraumMedia\\EventsExample\\', '../Classes/*');
+};
diff --git a/Tests/Functional/Frontend/Fixtures/Sites/default/config.yaml b/Tests/Functional/Frontend/Fixtures/Sites/default/config.yaml
index 5b610ef..50e1956 100644
--- a/Tests/Functional/Frontend/Fixtures/Sites/default/config.yaml
+++ b/Tests/Functional/Frontend/Fixtures/Sites/default/config.yaml
@@ -14,3 +14,6 @@ languages:
     flag: us
     websiteTitle: ''
 rootPageId: 1
+imports:
+  -
+    resource: 'EXT:events/Configuration/CeRouting.yaml'
diff --git a/Tests/Functional/Frontend/SearchTest.php b/Tests/Functional/Frontend/SearchTest.php
new file mode 100644
index 0000000..ea11956
--- /dev/null
+++ b/Tests/Functional/Frontend/SearchTest.php
@@ -0,0 +1,141 @@
+<?php
+
+declare(strict_types=1);
+
+namespace WerkraumMedia\Events\Tests\Functional\Frontend;
+
+use DateTimeImmutable;
+use PHPUnit\Framework\Attributes\Test;
+use TYPO3\CMS\Core\Context\DateTimeAspect;
+use TYPO3\CMS\Core\Http\StreamFactory;
+use TYPO3\CMS\Core\Utility\ArrayUtility;
+use TYPO3\TestingFramework\Core\Functional\Framework\Frontend\InternalRequest;
+
+final class SearchTest extends AbstractFrontendTestCase
+{
+    protected function setUp(): void
+    {
+        $this->testExtensionsToLoad = [
+            ...$this->testExtensionsToLoad,
+            'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Extensions/ce_filter/',
+            'typo3conf/ext/events/Tests/Functional/Frontend/Fixtures/Extensions/ce_list/',
+        ];
+
+        ArrayUtility::mergeRecursiveWithOverrule($this->configurationToUseInTestInstance, [
+            'FE' => [
+                'cacheHash' => [
+                    'excludedParameters' => [
+                        '^events[search]',
+                    ],
+                ],
+            ],
+        ]);
+
+        parent::setUp();
+
+        $this->importPHPDataSet(__DIR__ . '/Fixtures/Database/SearchSetup.php');
+    }
+
+    #[Test]
+    public function submittingPostWithoutSearchArgumentsRedirectsToGet(): void
+    {
+        $request = new InternalRequest('https://example.com/');
+        $request = $request->withMethod('POST');
+        $request = $request->withPageId(1);
+
+        $response = $this->executeFrontendSubRequest($request);
+
+        self::assertSame(303, $response->getStatusCode());
+        self::assertSame('http://example.com/', $response->getHeaderLine('location'));
+    }
+
+    #[Test]
+    public function submittingPostWithSearchArgumentsRedirectsToGet(): void
+    {
+        $request = new InternalRequest('https://example.com/');
+        $request = $request->withMethod('POST');
+        $request = $request->withPageId(1);
+        $request = $request->withBody((new StreamFactory())->createStream(http_build_query([
+            'events' => [
+                'search' => [
+                    'searchword' => 'Event',
+                ],
+            ],
+        ])));
+
+        $response = $this->executeFrontendSubRequest($request);
+
+        self::assertSame(303, $response->getStatusCode());
+        self::assertSame('http://example.com/?events%5Bsearch%5D%5Bsearchword%5D=Event', $response->getHeaderLine('location'));
+    }
+
+    #[Test]
+    public function submittedInputShownInForm(): void
+    {
+        $request = new InternalRequest('https://example.com/');
+        $request = $request->withQueryParams([
+            'events' => [
+                'search' => [
+                    'searchword' => 'Event',
+                ],
+            ],
+        ]);
+        $request = $request->withPageId(1);
+        $response = $this->executeFrontendSubRequest($request);
+        $html = $response->getBody()->__toString();
+
+        self::assertSame(200, $response->getStatusCode());
+        self::assertStringContainsString('value="Event"', $html, 'Submitted value is not rendered within form');
+    }
+
+    #[Test]
+    public function submittedInputIsKeptWithinPagination(): void
+    {
+        $request = new InternalRequest('https://example.com/');
+        $request = $request->withAttribute('testingDateAspect', new DateTimeAspect(new DateTimeImmutable('2022-08-10')));
+        $request = $request->withQueryParams([
+            'events' => [
+                'search' => [
+                    'searchword' => 'Event',
+                ],
+            ],
+        ]);
+        $request = $request->withPageId(1);
+        $response = $this->executeFrontendSubRequest($request);
+        $html = $response->getBody()->__toString();
+
+        self::assertSame(200, $response->getStatusCode());
+        self::assertStringContainsString('Event one', $html);
+        self::assertStringContainsString('Current Page 1', $html);
+        self::assertStringContainsString('/page-2?events%5Bsearch%5D%5Bsearchword%5D=Event&amp;cHash=41711281293c1c3a3aa161e96bbd4e98', $html);
+        self::assertStringNotContainsString('Event two', $html);
+
+        self::assertStringContainsString('value="Event"', $html, 'Submitted value is not rendered within form');
+
+        // Ensure going to 2nd page works (make sure it is available after warming up cache for first page)
+
+        $request = new InternalRequest('https://example.com/');
+        $request = $request->withAttribute('testingDateAspect', new DateTimeAspect(new DateTimeImmutable('2022-08-10')));
+        $request = $request->withQueryParams([
+            'events' => [
+                'search' => [
+                    'searchword' => 'Event',
+                ],
+                'controller' => 'Date',
+                'currentPage' => '2',
+            ],
+            'cHash' => '41711281293c1c3a3aa161e96bbd4e98',
+        ]);
+        $request = $request->withPageId(1);
+        $response = $this->executeFrontendSubRequest($request);
+        $html = $response->getBody()->__toString();
+
+        self::assertSame(200, $response->getStatusCode());
+        self::assertStringContainsString('Event two', $html);
+        self::assertStringContainsString('Current Page 2', $html);
+        self::assertStringContainsString('/page-1?events%5Bsearch%5D%5Bsearchword%5D=Event&amp;cHash=13c33adfef09ccb19da7d399ada25c4c', $html);
+        self::assertStringNotContainsString('Event one', $html);
+
+        self::assertStringContainsString('value="Event"', $html, 'Submitted value is not rendered within form');
+    }
+}
diff --git a/composer.json b/composer.json
index 2bce866..9ec6243 100644
--- a/composer.json
+++ b/composer.json
@@ -38,6 +38,7 @@
     "autoload-dev": {
         "psr-4": {
             "WerkraumMedia\\Events\\Tests\\": "Tests",
+            "WerkraumMedia\\EventsExample\\": "Tests/Functional/Frontend/Fixtures/Extensions/example/Classes/",
             "WerkraumMedia\\CustomCategories\\": "Tests/Functional/Psr14Events/DestinationDataImport/Fixtures/Extensions/custom_categories/Classes/",
             "WerkraumMedia\\CustomEvent\\": "Tests/Functional/Psr14Events/DestinationDataImport/Fixtures/Extensions/custom_event/Classes/"
         }