diff --git a/modules/project_browser_devel/src/Plugin/ProjectBrowserSource/RandomDataPlugin.php b/modules/project_browser_devel/src/Plugin/ProjectBrowserSource/RandomDataPlugin.php
index 7b16a795fb73c873f5aed5c56a05e4dc15b1a86f..3fb484262afee880487f9dec31de2bd5f4297d56 100644
--- a/modules/project_browser_devel/src/Plugin/ProjectBrowserSource/RandomDataPlugin.php
+++ b/modules/project_browser_devel/src/Plugin/ProjectBrowserSource/RandomDataPlugin.php
@@ -145,7 +145,7 @@ class RandomDataPlugin extends ProjectBrowserSourceBase {
       NULL,
     );
     $filters['developmentStatus'] = new BooleanFilter(
-      TRUE,
+      FALSE,
       $this->t('Show projects under active development'),
       $this->t('Show all'),
       $this->t('Development status'),
diff --git a/modules/project_browser_source_example/src/Plugin/ProjectBrowserSource/ProjectBrowserSourceExample.php b/modules/project_browser_source_example/src/Plugin/ProjectBrowserSource/ProjectBrowserSourceExample.php
index a8c47418a82ef9f771ad39e7994882a2bae176a5..c7c429eab83e7126891f89e65665681d1f9a73f5 100644
--- a/modules/project_browser_source_example/src/Plugin/ProjectBrowserSource/ProjectBrowserSourceExample.php
+++ b/modules/project_browser_source_example/src/Plugin/ProjectBrowserSource/ProjectBrowserSourceExample.php
@@ -140,7 +140,6 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
         isCompatible: TRUE,
         isMaintained: TRUE,
         isCovered: TRUE,
-        projectUsageTotal: 0,
         machineName: $project_from_source['unique_name'],
         body: [
           'summary' => $project_from_source['short_description'],
@@ -161,7 +160,6 @@ class ProjectBrowserSourceExample extends ProjectBrowserSourceBase {
         isCompatible: TRUE,
         isMaintained: TRUE,
         isCovered: TRUE,
-        projectUsageTotal: 0,
         machineName: $project_from_source['unique_name'] . '2',
         body: [
           'summary' => $project_from_source['short_description'] . ' (different commands)',
diff --git a/src/DevelopmentStatus.php b/src/DevelopmentStatus.php
deleted file mode 100644
index 577db57d078d24711a5bfc32a82b08b2bcb2bc86..0000000000000000000000000000000000000000
--- a/src/DevelopmentStatus.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\project_browser;
-
-use Drupal\Core\StringTranslation\TranslatableMarkup;
-
-/**
- * The development statuses available to the project browser.
- */
-enum DevelopmentStatus: string {
-
-  case Active = '1';
-  case All = '0';
-
-  /**
-   * Represents this enum as a set of options.
-   *
-   * @return array<string, \Drupal\Core\StringTranslation\TranslatableMarkup>
-   *   The cases in this enum. The keys are the backing values, and the values
-   *   are the translatable labels.
-   */
-  public static function asOptions(): array {
-    $options = [];
-    foreach (self::cases() as $case) {
-      $options[$case->value] = $case->label();
-    }
-    return $options;
-  }
-
-  /**
-   * Returns a translatable label for the current case.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   A translatable label.
-   */
-  public function label(): TranslatableMarkup {
-    return match ($this) {
-      self::Active => t('Show projects under active development'),
-      self::All => t('Show all'),
-    };
-  }
-
-}
diff --git a/src/Element/ProjectBrowser.php b/src/Element/ProjectBrowser.php
index 184179ef884e4addde65066ac15130920d67a12f..2a30bd88592754e8b8ae1cf62304ceead0180ebd 100644
--- a/src/Element/ProjectBrowser.php
+++ b/src/Element/ProjectBrowser.php
@@ -11,12 +11,9 @@ use Drupal\Core\Render\Attribute\RenderElement;
 use Drupal\Core\Render\Element;
 use Drupal\Core\Render\Element\ElementInterface;
 use Drupal\Core\Render\Element\RenderElementBase;
-use Drupal\project_browser\DevelopmentStatus;
 use Drupal\project_browser\EnabledSourceHandler;
 use Drupal\project_browser\InstallReadiness;
-use Drupal\project_browser\MaintenanceStatus;
 use Drupal\project_browser\Plugin\ProjectBrowserSourceInterface;
-use Drupal\project_browser\SecurityStatus;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
 /**
@@ -116,12 +113,12 @@ final class ProjectBrowser implements ElementInterface, ContainerFactoryPluginIn
    *   An array of Drupal settings.
    */
   private function getDrupalSettings(string $source, ?int $max_selections = NULL): array {
+    $source = $this->enabledSourceHandler->getCurrentSources()[$source];
+    assert($source instanceof ProjectBrowserSourceInterface);
+
     if (is_int($max_selections) && $max_selections <= 0) {
       throw new \InvalidArgumentException('$max_selections must be a positive integer or NULL.');
     }
-    $current_sources = [
-      $source => $this->enabledSourceHandler->getCurrentSources()[$source],
-    ];
 
     $package_manager = [
       'available' => (bool) $this->configFactory->get('project_browser.admin_settings')->get('allow_ui_install'),
@@ -137,51 +134,16 @@ final class ProjectBrowser implements ElementInterface, ContainerFactoryPluginIn
     }
 
     return [
-      'active_plugins' => array_map(
-        fn (ProjectBrowserSourceInterface $source) => $source->getPluginDefinition()['label'],
-        $current_sources,
-      ),
+      'active_plugin' => $source->getPluginDefinition()['label'],
       'module_path' => $this->moduleHandler->getModule('project_browser')->getPath(),
-      'special_ids' => $this->getSpecialIds(),
-      'sort_options' => array_map(
-        fn (ProjectBrowserSourceInterface $source) => array_values($source->getSortOptions()),
-        $current_sources,
-      ),
-      'maintenance_options' => MaintenanceStatus::asOptions(),
-      'security_options' => SecurityStatus::asOptions(),
-      'development_options' => DevelopmentStatus::asOptions(),
-      'default_plugin_id' => reset($current_sources)->getPluginId(),
+      'sort_options' => array_values($source->getSortOptions()),
+      'default_plugin_id' => $source->getPluginId(),
       'package_manager' => $package_manager,
-      'filters' => array_map(
-        fn (ProjectBrowserSourceInterface $source) => $source->getFilterDefinitions(),
-        $current_sources,
-      ),
+      'filters' => (object) $source->getFilterDefinitions(),
       'max_selections' => $max_selections,
     ];
   }
 
-  /**
-   * Return special IDs for some vocabularies.
-   *
-   * @return array
-   *   List of special IDs per vocabulary.
-   */
-  private static function getSpecialIds(): array {
-    $maintained = MaintenanceStatus::Maintained;
-    $covered = SecurityStatus::Covered;
-    return [
-      'maintenance_status' => [
-        'id' => $maintained->value,
-        'name' => $maintained->label(),
-      ],
-      'security_coverage' => [
-        'id' => $covered->value,
-        'name' => $covered->label(),
-      ],
-      'all_values' => MaintenanceStatus::All->value,
-    ];
-  }
-
   /**
    * {@inheritdoc}
    */
diff --git a/src/MaintenanceStatus.php b/src/MaintenanceStatus.php
deleted file mode 100644
index 42cae92aa93135e981cd501e446d2c9d129ef072..0000000000000000000000000000000000000000
--- a/src/MaintenanceStatus.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\project_browser;
-
-use Drupal\Core\StringTranslation\TranslatableMarkup;
-
-/**
- * The maintenance statuses available to the project browser.
- */
-enum MaintenanceStatus: string {
-
-  case Maintained = '1';
-  case All = '0';
-
-  /**
-   * Represents this enum as a set of options.
-   *
-   * @return array<string, \Drupal\Core\StringTranslation\TranslatableMarkup>
-   *   The cases in this enum. The keys are the backing values, and the values
-   *   are the translatable labels.
-   */
-  public static function asOptions(): array {
-    $options = [];
-    foreach (self::cases() as $case) {
-      $options[$case->value] = $case->label();
-    }
-    return $options;
-  }
-
-  /**
-   * Returns a translatable label for the current case.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   A translatable label.
-   */
-  public function label(): TranslatableMarkup {
-    return match ($this) {
-      self::Maintained => t('Show actively maintained projects'),
-      self::All => t('Show all'),
-    };
-  }
-
-}
diff --git a/src/Plugin/ProjectBrowserSource/DrupalCore.php b/src/Plugin/ProjectBrowserSource/DrupalCore.php
index 6a4d64e5f33b57fa469809e9f9672f3623e097d4..12aa0cb490320db4ae4a600511478306c7201a81 100644
--- a/src/Plugin/ProjectBrowserSource/DrupalCore.php
+++ b/src/Plugin/ProjectBrowserSource/DrupalCore.php
@@ -9,7 +9,6 @@ use Drupal\Core\Site\Settings;
 use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
 use Drupal\project_browser\ProjectBrowser\Project;
 use Drupal\project_browser\ProjectBrowser\ProjectsResultsPage;
-use Drupal\project_browser\SecurityStatus;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\HttpFoundation\RequestStack;
 
@@ -128,7 +127,7 @@ class DrupalCore extends ProjectBrowserSourceBase {
     }
 
     // Filter by coverage.
-    if (!empty($query['security_advisory_coverage']) && $query['security_advisory_coverage'] === SecurityStatus::Covered->value) {
+    if (!empty($query['security_advisory_coverage'])) {
       $projects = array_filter($projects, fn(Project $project) => $project->isCovered);
     }
 
@@ -191,7 +190,6 @@ class DrupalCore extends ProjectBrowserSourceBase {
         isCompatible: TRUE,
         isMaintained: TRUE,
         isCovered: $module->info['package'] !== 'Core (Experimental)',
-        projectUsageTotal: -1,
         machineName: $module_name,
         body: [
           'summary' => $module->info['description'],
diff --git a/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php b/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php
index 70e1496b7eacf94cd00ab3b2a91f9c0e9888b71d..45fccfb8ad01b8fd5817ee24b5033b567d258f42 100644
--- a/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php
+++ b/src/Plugin/ProjectBrowserSource/DrupalDotOrgJsonApi.php
@@ -9,14 +9,11 @@ use Drupal\Core\Cache\CacheBackendInterface;
 use Drupal\Core\Extension\ExtensionVersion;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\Core\Url;
-use Drupal\project_browser\DevelopmentStatus;
-use Drupal\project_browser\MaintenanceStatus;
 use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
 use Drupal\project_browser\ProjectBrowser\Filter\BooleanFilter;
 use Drupal\project_browser\ProjectBrowser\Filter\MultipleChoiceFilter;
 use Drupal\project_browser\ProjectBrowser\Project;
 use Drupal\project_browser\ProjectBrowser\ProjectsResultsPage;
-use Drupal\project_browser\SecurityStatus;
 use GuzzleHttp\ClientInterface;
 use GuzzleHttp\Exception\GuzzleException;
 use Psr\Log\LoggerInterface;
@@ -265,7 +262,7 @@ class DrupalDotOrgJsonApi extends ProjectBrowserSourceBase {
       NULL,
     );
     $filters['developmentStatus'] = new BooleanFilter(
-      TRUE,
+      FALSE,
       $this->t('Show projects under active development'),
       $this->t('Show all'),
       $this->t('Development status'),
@@ -672,27 +669,21 @@ class DrupalDotOrgJsonApi extends ProjectBrowserSourceBase {
     // Maintenance options.
     $maintenance = NULL;
     if (!empty($query['maintenance_status'])) {
-      if ($query['maintenance_status'] == MaintenanceStatus::Maintained->value) {
-        $maintenance = implode(',', $maintained_values);
-      }
+      $maintenance = implode(',', $maintained_values);
     }
     $query['maintenance_status'] = $maintenance;
 
     // Development options.
     $development = NULL;
     if (!empty($query['development_status'])) {
-      if ($query['development_status'] == DevelopmentStatus::Active->value) {
-        $development = implode(',', $active_values);
-      }
+      $development = implode(',', $active_values);
     }
     $query['development_status'] = $development;
 
     // Security options.
     $security = NULL;
     if (!empty($query['security_advisory_coverage'])) {
-      if ($query['security_advisory_coverage'] == SecurityStatus::Covered->value) {
-        $security = implode(',', self::COVERED_VALUES);
-      }
+      $security = implode(',', self::COVERED_VALUES);
     }
     $query['security_advisory_coverage'] = $security;
 
diff --git a/src/Plugin/ProjectBrowserSource/Recipes.php b/src/Plugin/ProjectBrowserSource/Recipes.php
index 967ab4b2d8aac69017a7e2ae7eb3720a85810da8..c10a934a346904bb98f92538b12b850be372e441 100644
--- a/src/Plugin/ProjectBrowserSource/Recipes.php
+++ b/src/Plugin/ProjectBrowserSource/Recipes.php
@@ -19,7 +19,6 @@ use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
 use Drupal\project_browser\ProjectBrowser\Project;
 use Drupal\project_browser\ProjectBrowser\ProjectsResultsPage;
 use Drupal\project_browser\ProjectType;
-use Drupal\project_browser\SecurityStatus;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 use Symfony\Component\Finder\Finder;
 
@@ -112,9 +111,6 @@ class Recipes extends ProjectBrowserSourceBase {
             ]),
           ],
           isCompatible: TRUE,
-          isMaintained: TRUE,
-          isCovered: TRUE,
-          projectUsageTotal: 0,
           machineName: basename($path),
           body: $description ? ['value' => $description] : [],
           title: $recipe['name'],
@@ -133,7 +129,7 @@ class Recipes extends ProjectBrowserSourceBase {
     }
 
     // Filter by coverage.
-    if (!empty($query['security_advisory_coverage']) && $query['security_advisory_coverage'] === SecurityStatus::Covered->value) {
+    if (!empty($query['security_advisory_coverage'])) {
       $projects = array_filter($projects, fn(Project $project) => $project->isCovered);
     }
 
diff --git a/src/ProjectBrowser/Project.php b/src/ProjectBrowser/Project.php
index 01e9dda2649da6f49d74c6b291213c17d2f50400..e03bdea3eddb2b2360355dd7341b5bb0824755a4 100644
--- a/src/ProjectBrowser/Project.php
+++ b/src/ProjectBrowser/Project.php
@@ -70,10 +70,6 @@ class Project implements \JsonSerializable {
    *   Logo of the project.
    * @param bool $isCompatible
    *   Whether the project is compatible with the current version of Drupal.
-   * @param bool $isCovered
-   *   Whether the project is considered to be covered or not.
-   * @param int $projectUsageTotal
-   *   Total usage of the project.
    * @param string $machineName
    *   Value of project_machine_name of the project.
    * @param array $body
@@ -84,8 +80,15 @@ class Project implements \JsonSerializable {
    *   Author of the project in array format.
    * @param string $packageName
    *   The Composer package name of this project, e.g. `drupal/project_browser`.
-   * @param bool $isMaintained
-   *   Whether the project is considered to be maintained or not.
+   * @param int|null $projectUsageTotal
+   *   (optional) Total number of sites known to be using this project, or NULL
+   *   if this information is not known. Defaults to NULL.
+   * @param bool|null $isCovered
+   *   (optional) Whether or not the project is covered by security advisories,
+   *   or NULL if this information is not known. Defaults to NULL.
+   * @param bool|null $isMaintained
+   *   (optional) Whether or not the project is considered maintained, or NULL
+   *   if this information is not known. Defaults to NULL.
    * @param \Drupal\Core\Url|null $url
    *   URL of the project, if any. Defaults to NULL.
    * @param array $categories
@@ -107,14 +110,14 @@ class Project implements \JsonSerializable {
   public function __construct(
     public array $logo,
     public bool $isCompatible,
-    public bool $isCovered,
-    public int $projectUsageTotal,
     public string $machineName,
     private array $body,
     public string $title,
     public array $author,
     public string $packageName,
-    public bool $isMaintained = FALSE,
+    public ?int $projectUsageTotal = NULL,
+    public ?bool $isCovered = NULL,
+    public ?bool $isMaintained = NULL,
     public ?Url $url = NULL,
     public array $categories = [],
     public array $images = [],
@@ -124,6 +127,10 @@ class Project implements \JsonSerializable {
   ) {
     $this->setSummary($body);
 
+    if (is_int($projectUsageTotal) && $projectUsageTotal < 0) {
+      throw new \InvalidArgumentException('The $projectUsageTotal argument cannot be a negative number.');
+    }
+
     if (is_string($type)) {
       // If the $type can't be mapped to a ProjectType case, use it as-is.
       $type = ProjectType::tryFrom($type) ?? $type;
diff --git a/src/SecurityStatus.php b/src/SecurityStatus.php
deleted file mode 100644
index 955975d82a178665621e7d555439e1db9190bb43..0000000000000000000000000000000000000000
--- a/src/SecurityStatus.php
+++ /dev/null
@@ -1,45 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\project_browser;
-
-use Drupal\Core\StringTranslation\TranslatableMarkup;
-
-/**
- * The security coverage statuses available to the project browser.
- */
-enum SecurityStatus: string {
-
-  case Covered = '1';
-  case All = '0';
-
-  /**
-   * Represents this enum as a set of options.
-   *
-   * @return array<string, \Drupal\Core\StringTranslation\TranslatableMarkup>
-   *   The cases in this enum. The keys are the backing values, and the values
-   *   are the translatable labels.
-   */
-  public static function asOptions(): array {
-    $options = [];
-    foreach (self::cases() as $case) {
-      $options[$case->value] = $case->label();
-    }
-    return $options;
-  }
-
-  /**
-   * Returns a translatable label for the current case.
-   *
-   * @return \Drupal\Core\StringTranslation\TranslatableMarkup
-   *   A translatable label.
-   */
-  public function label(): TranslatableMarkup {
-    return match ($this) {
-      self::Covered => t('Show projects covered by a security policy'),
-      self::All => t('Show all'),
-    };
-  }
-
-}
diff --git a/sveltejs/public/build/bundle.js b/sveltejs/public/build/bundle.js
index 01d1f1bf8badee2edff3b1f1df82cd51a0e46bde..f88935469ce32d580ef7621bca8538d94951cb69 100644
Binary files a/sveltejs/public/build/bundle.js and b/sveltejs/public/build/bundle.js differ
diff --git a/sveltejs/public/build/bundle.js.map b/sveltejs/public/build/bundle.js.map
index 7ff6140054aa9bcb6584a688d5dd76ff2429c12b..549b45caa54dda0bdfd51ecebcc69fc89310bd5c 100644
Binary files a/sveltejs/public/build/bundle.js.map and b/sveltejs/public/build/bundle.js.map differ
diff --git a/sveltejs/src/DetailModal.svelte b/sveltejs/src/DetailModal.svelte
index aa1795d0bb248d23096a6861c06826206bc25ec9..8a80fe2cf41f1cf00ce9e4162860086021afc599 100644
--- a/sveltejs/src/DetailModal.svelte
+++ b/sveltejs/src/DetailModal.svelte
@@ -79,7 +79,7 @@
         {Drupal.t('Not compatible with your Drupal installation')}
       </div>
     {/if}
-    {#if project.project_usage_total !== -1}
+    {#if typeof project.project_usage_total === 'number'}
       <div class="pb-detail-modal__sidebar_element">
         <ProjectIcon
           type="usage"
diff --git a/sveltejs/src/MultipleChoiceFilter.svelte b/sveltejs/src/MultipleChoiceFilter.svelte
index 90a5bbe02895fd791cd09d8743a5e3d38b0e75a8..647c692889acc7aa4cbf60286b05196cf1bbac4d 100644
--- a/sveltejs/src/MultipleChoiceFilter.svelte
+++ b/sveltejs/src/MultipleChoiceFilter.svelte
@@ -4,10 +4,9 @@
     moduleCategoryFilter,
     moduleCategoryVocabularies,
     activeTab,
-    sourceFilters,
   } from './stores';
   import { normalizeOptions, shallowCompare } from './util';
-  import { BASE_URL } from './constants';
+  import { BASE_URL, FILTERS } from './constants';
 
   const { Drupal } = window;
   const dispatch = createEventDispatcher();
@@ -86,13 +85,13 @@
         return;
       }
       // Tab without shift moves to next filter.
-      const keys = Object.keys($sourceFilters);
-      const filterMap = Object.fromEntries(Object.entries($sourceFilters));
+      const keys = Object.keys(FILTERS);
+      const filterMap = Object.fromEntries(Object.entries(FILTERS));
 
       const indexOfCategories = keys.indexOf('categories');
       if (indexOfCategories !== -1 && indexOfCategories + 1 < keys.length) {
         const nextKey = keys[indexOfCategories + 1];
-        const nextElement = $sourceFilters[nextKey];
+        const nextElement = FILTERS[nextKey];
         const nextElementKey = Object.keys(filterMap).find(
           (key) => filterMap[key] === nextElement,
         );
diff --git a/sveltejs/src/Project/Project.svelte b/sveltejs/src/Project/Project.svelte
index 6f45f8eae2dc7f8c669a5f87bf340b9581ec7d74..f5550fd855bc59b8aeeeaa64d76912dbfb831893 100644
--- a/sveltejs/src/Project/Project.svelte
+++ b/sveltejs/src/Project/Project.svelte
@@ -75,18 +75,16 @@
         <ProjectIcon type="maintained" />
       </span>
     {/if}
-    {#if toggleView === 'Grid' && project.project_usage_total !== -1}
-      {#if project.project_usage_total !== 0}
-        <div class="pb-project__install-count-container">
-          <span class="pb-project__install-count">
-            {Drupal.formatPlural(
-              project.project_usage_total,
-              `${numberFormatter.format(1)} install`,
-              `${numberFormatter.format(project.project_usage_total)} installs`,
-            )}
-          </span>
-        </div>
-      {/if}
+    {#if toggleView === 'Grid' && typeof project.project_usage_total === 'number' && project.project_usage_total > 0}
+      <div class="pb-project__install-count-container">
+        <span class="pb-project__install-count">
+          {Drupal.formatPlural(
+            project.project_usage_total,
+            `${numberFormatter.format(1)} install`,
+            `${numberFormatter.format(project.project_usage_total)} installs`,
+          )}
+        </span>
+      </div>
     {/if}
     {#if project.warnings && project.warnings.length > 0}
       {#each project.warnings as warning}
@@ -96,12 +94,12 @@
         </span>
       {/each}
     {/if}
-    {#if toggleView === 'List' && project.project_usage_total !== -1}
+    {#if toggleView === 'List' && typeof project.project_usage_total === 'number'}
       <div class="pb-project__project-usage-container">
         <div class="pb-project__image pb-project__image--{displayMode}">
           <ProjectIcon type="usage" variant="project-listing" />
         </div>
-        {#if project.project_usage_total !== 0}
+        {#if project.project_usage_total > 0}
           <div class="pb-project__active-installs-text">
             {Drupal.formatPlural(
               project.project_usage_total,
diff --git a/sveltejs/src/ProjectBrowser.svelte b/sveltejs/src/ProjectBrowser.svelte
index c7636e424162e06625196904e73c4e400de1b337..224135af90995b598b92782fb3858f5e6a493210 100644
--- a/sveltejs/src/ProjectBrowser.svelte
+++ b/sveltejs/src/ProjectBrowser.svelte
@@ -24,13 +24,10 @@
   } from './stores';
   import MediaQuery from './MediaQuery.svelte';
   import {
-    ACTIVELY_MAINTAINED_ID,
-    COVERED_ID,
-    ALL_VALUES_ID,
     DEFAULT_SOURCE_ID,
     BASE_URL,
     FULL_MODULE_PATH,
-    ACTIVE_PLUGINS,
+    ACTIVE_PLUGIN,
     PACKAGE_MANAGER,
     MAX_SELECTIONS,
   } from './constants';
@@ -100,14 +97,23 @@
       // If no category filter is set, reset the tracking for the active tab.
       $categoryCheckedTrack[$activeTab] = [];
     }
-    if ($filters.developmentStatus && $filters.developmentStatus.length) {
-      searchParams.set('development_status', $filters.developmentStatus);
+    if ('developmentStatus' in $filters) {
+      searchParams.set(
+        'development_status',
+        Number($filters.developmentStatus).toString(),
+      );
     }
-    if ($filters.maintenanceStatus && $filters.maintenanceStatus.length) {
-      searchParams.set('maintenance_status', $filters.maintenanceStatus);
+    if ('maintenanceStatus' in $filters) {
+      searchParams.set(
+        'maintenance_status',
+        Number($filters.maintenanceStatus).toString(),
+      );
     }
-    if ($filters.securityCoverage && $filters.securityCoverage.length) {
-      searchParams.set('security_advisory_coverage', $filters.securityCoverage);
+    if ('securityCoverage' in $filters) {
+      searchParams.set(
+        'security_advisory_coverage',
+        Number($filters.securityCoverage).toString(),
+      );
     }
     if (Object.keys($categoryCheckedTrack).length !== 0) {
       searchParams.set(
@@ -157,19 +163,6 @@
     loading = false;
   }
 
-  async function filterRecommended() {
-    // Show recommended projects on initial page load only when no filters are applied.
-    if (
-      $filters.developmentStatus.length === 0 &&
-      $filters.maintenanceStatus.length === 0 &&
-      $filters.securityCoverage.length === 0
-    ) {
-      $filters.maintenanceStatus = ACTIVELY_MAINTAINED_ID;
-      $filters.securityCoverage = COVERED_ID;
-      $filters.developmentStatus = ALL_VALUES_ID;
-    }
-  }
-
   /**
    * Load remote data when the Svelte component is mounted.
    */
@@ -191,8 +184,6 @@
       projectId = null;
     }
 
-    await filterRecommended();
-
     await load($page);
     const focus = element ? document.getElementById(element) : false;
     if (focus) {
@@ -236,11 +227,7 @@
     await load(0);
     page.set(0);
   }
-  async function onAdvancedFilter(event) {
-    $filters.developmentStatus = event.detail.developmentStatus;
-    $filters.maintenanceStatus = event.detail.maintenanceStatus;
-    $filters.securityCoverage = event.detail.securityCoverage;
-
+  async function onAdvancedFilter() {
     await load(0);
     page.set(0);
   }
@@ -269,7 +256,7 @@
           Drupal.t('@count Results for @active_tab, Sorted by @sortText', {
             '@count': numberFormatter.format($rowsCount),
             '@sortText': sortText,
-            '@active_tab': ACTIVE_PLUGINS[$activeTab],
+            '@active_tab': ACTIVE_PLUGIN,
           }),
         );
       }, 210);
diff --git a/sveltejs/src/Search/BooleanFilter.svelte b/sveltejs/src/Search/BooleanFilter.svelte
index 5dd984b529fb9e5e6d9278948f674df2545cc040..906cf43cc1358acdbc05c8565762374959e929dc 100644
--- a/sveltejs/src/Search/BooleanFilter.svelte
+++ b/sveltejs/src/Search/BooleanFilter.svelte
@@ -16,7 +16,7 @@
     bind:value={$filters[type]}
     on:change={changeHandler}
   >
-    <option value="1">{onLabel}</option>
-    <option value="0">{offLabel}</option>
+    <option value={true}>{onLabel}</option>
+    <option value={false}>{offLabel}</option>
   </select>
 </div>
diff --git a/sveltejs/src/Search/FilterApplied.svelte b/sveltejs/src/Search/FilterApplied.svelte
index 7524e1e8f50663be09574abf238eec22e43a16ed..80295a4707823bd1b90abaac25ca984ac67a2c6e 100644
--- a/sveltejs/src/Search/FilterApplied.svelte
+++ b/sveltejs/src/Search/FilterApplied.svelte
@@ -1,27 +1,24 @@
 <script>
-  import { ALL_VALUES_ID, FULL_MODULE_PATH } from '../constants';
+  import { FULL_MODULE_PATH } from '../constants';
 
-  export let id;
   export let label;
   export let clickHandler;
 
   const { Drupal } = window;
 </script>
 
-{#if id !== ALL_VALUES_ID}
-  <p class="filter-applied">
-    <span class="filter-applied__label">{label}</span>
-    <button
-      type="button"
-      on:click={clickHandler}
-      class="filter-applied__button-close"
-    >
-      {#if label}
-        <span class="visually-hidden"
-          >{Drupal.t('Remove @filter', { '@filter': label })}</span
-        >
-      {/if}
-      <img src="{FULL_MODULE_PATH}/images/chip-close-icon.svg" alt="" />
-    </button>
-  </p>
-{/if}
+<p class="filter-applied">
+  <span class="filter-applied__label">{label}</span>
+  <button
+    type="button"
+    on:click={clickHandler}
+    class="filter-applied__button-close"
+  >
+    {#if label}
+      <span class="visually-hidden"
+        >{Drupal.t('Remove @filter', { '@filter': label })}</span
+      >
+    {/if}
+    <img src="{FULL_MODULE_PATH}/images/chip-close-icon.svg" alt="" />
+  </button>
+</p>
diff --git a/sveltejs/src/Search/Search.svelte b/sveltejs/src/Search/Search.svelte
index e588b8c8aaa062bfa75989801fe6397bf32c3324..d24d3fb2b60354838a6eeea1860c7e5901066b35 100644
--- a/sveltejs/src/Search/Search.svelte
+++ b/sveltejs/src/Search/Search.svelte
@@ -1,14 +1,11 @@
 <script>
-  import { createEventDispatcher, getContext, onMount } from 'svelte';
+  import { createEventDispatcher, getContext } from 'svelte';
   import FilterApplied from './FilterApplied.svelte';
   import BooleanFilter from './BooleanFilter.svelte';
-  import { normalizeOptions, shallowCompare } from '../util';
   import MultipleChoiceFilter from '../MultipleChoiceFilter.svelte';
   import SearchSort from './SearchSort.svelte';
   import {
-    sourceFilters,
     filters,
-    filtersVocabularies,
     moduleCategoryFilter,
     categoryCheckedTrack,
     moduleCategoryVocabularies,
@@ -16,16 +13,7 @@
     searchString,
     sortCriteria,
   } from '../stores';
-  import {
-    COVERED_ID,
-    ACTIVELY_MAINTAINED_ID,
-    MAINTENANCE_OPTIONS,
-    DEVELOPMENT_OPTIONS,
-    SECURITY_OPTIONS,
-    ALL_VALUES_ID,
-    FULL_MODULE_PATH,
-    DARK_COLOR_SCHEME,
-  } from '../constants';
+  import { FULL_MODULE_PATH, DARK_COLOR_SCHEME, FILTERS } from '../constants';
 
   const { Drupal } = window;
   const dispatch = createEventDispatcher();
@@ -51,21 +39,6 @@
   let sortText = sortMatch.text;
   let filterComponent;
 
-  const updateVocabularies = (vocabulary, value) => {
-    const normalizedValue = normalizeOptions(value);
-    const storedValue = JSON.parse(localStorage.getItem(`pb.${vocabulary}`));
-    if (storedValue === null || !shallowCompare(normalizedValue, storedValue)) {
-      $filtersVocabularies[vocabulary] = normalizedValue;
-      localStorage.setItem(`pb.${vocabulary}`, JSON.stringify(normalizedValue));
-    }
-  };
-
-  onMount(() => {
-    updateVocabularies('developmentStatus', DEVELOPMENT_OPTIONS);
-    updateVocabularies('maintenanceStatus', MAINTENANCE_OPTIONS);
-    updateVocabularies('securityCoverage', SECURITY_OPTIONS);
-  });
-
   export async function onSearch(event) {
     const state = stateContext.getState();
     const detail = {
@@ -79,7 +52,9 @@
       rows: state.filteredRows,
     };
     dispatch('search', detail);
-    filterComponent.setModuleCategoryVocabulary();
+    if (filterComponent) {
+      filterComponent.setModuleCategoryVocabulary();
+    }
     if (detail.preventDefault !== true) {
       if (detail.searchText.length === 0) {
         stateContext.setRows(state.rows);
@@ -96,12 +71,19 @@
   }
 
   const onAdvancedFilter = async (event) => {
+    if (event) {
+      const filterName = event.target.name;
+
+      if (FILTERS[filterName]._type === 'boolean') {
+        $filters[filterName] = event.target.value === 'true';
+      } else {
+        $filters[filterName] = event.target.value;
+      }
+    }
+
     const state = stateContext.getState();
     const detail = {
       originalEvent: event,
-      developmentStatus: $filters.developmentStatus,
-      maintenanceStatus: $filters.maintenanceStatus,
-      securityCoverage: $filters.securityCoverage,
       page: state.page,
       pageIndex: state.pageIndex,
       pageSize: state.pageSize,
@@ -134,20 +116,30 @@
     document.getElementById('pb-text').focus();
   }
 
+  const filterDefinitions = Object.entries(FILTERS);
+
   /**
-   * Actions performed when clicking filter resets such as "recommended"
-   * @param {string} maintenanceId
-   *    ID of the selected maintenance status.
-   * @param {string} developmentId
-   *   ID of the selected development status.
-   * @param {string} securityId
-   *   ID of the selected security status.
+   * Resets the filters to the initial values provided by the source.
+   *
+   * @param {boolean} clear
+   *   Whether to clear all filter values (i.e., not reset them to their defaults,
+   *   but actually negate them all).
    */
-  const filterResets = (maintenanceId, developmentId, securityId) => {
-    $filters.maintenanceStatus = maintenanceId;
-    $filters.developmentStatus = developmentId;
-    $filters.securityCoverage = securityId;
-    $filters = $filters;
+  const resetFilters = (clear) => {
+    $filters = {};
+    filterDefinitions.forEach(([name, definition]) => {
+      let value;
+      if (clear) {
+        if (definition._type === 'boolean') {
+          value = false;
+        } else if (definition._type === 'multiple_choice') {
+          value = [];
+        }
+      } else {
+        value = definition.value;
+      }
+      $filters[name] = value;
+    });
     $moduleCategoryFilter = [];
     $categoryCheckedTrack = {};
     onAdvancedFilter();
@@ -209,10 +201,10 @@
       </button>
     </div>
   </div>
-  {#if $sourceFilters.length !== 0}
+  {#if filterDefinitions.length !== 0}
     <div class="search__form-filters-container">
       <div class="search__form-filters">
-        {#each Object.entries($sourceFilters) as [filterType, filter]}
+        {#each filterDefinitions as [filterType, filter]}
           {#if filter._type === 'boolean'}
             <BooleanFilter
               name={filter.name}
@@ -239,7 +231,6 @@
           <div class="search__results-count">
             {#each $moduleCategoryFilter as category}
               <FilterApplied
-                id={category}
                 label={$moduleCategoryVocabularies[category]}
                 clickHandler={() => {
                   $moduleCategoryFilter.splice(
@@ -252,26 +243,20 @@
               />
             {/each}
 
-            {#if $filters.securityCoverage !== ALL_VALUES_ID || $filters.maintenanceStatus !== ALL_VALUES_ID || $filters.developmentStatus !== ALL_VALUES_ID || $moduleCategoryFilter.length}
+            {#if $filters.securityCoverage || $filters.maintenanceStatus || $filters.developmentStatus || $moduleCategoryFilter.length}
               <button
                 class="search__filter-button"
                 type="button"
-                on:click|preventDefault={() =>
-                  filterResets(ALL_VALUES_ID, ALL_VALUES_ID, ALL_VALUES_ID)}
+                on:click|preventDefault={() => resetFilters(true)}
               >
                 {Drupal.t('Clear filters')}
               </button>
             {/if}
-            {#if !($filters.maintenanceStatus === ACTIVELY_MAINTAINED_ID && $filters.securityCoverage === COVERED_ID && $filters.developmentStatus === ALL_VALUES_ID && $moduleCategoryFilter.length === 0)}
+            {#if !($filters.maintenanceStatus && $filters.securityCoverage && !$filters.developmentStatus && $moduleCategoryFilter.length === 0)}
               <button
                 class="search__filter-button"
                 type="button"
-                on:click|preventDefault={() =>
-                  filterResets(
-                    ACTIVELY_MAINTAINED_ID,
-                    ALL_VALUES_ID,
-                    COVERED_ID,
-                  )}
+                on:click|preventDefault={() => resetFilters()}
               >
                 {Drupal.t('Recommended filters')}
               </button>
diff --git a/sveltejs/src/constants.js b/sveltejs/src/constants.js
index dd3ab86e9d88a93dd7d274595f59a0108d2d3b1f..bd2219ade5ba245dbb88de915a467e3ce5f91132 100644
--- a/sveltejs/src/constants.js
+++ b/sveltejs/src/constants.js
@@ -1,15 +1,4 @@
-export const MAINTENANCE_OPTIONS =
-  drupalSettings.project_browser.maintenance_options;
-export const SECURITY_OPTIONS = drupalSettings.project_browser.security_options;
-export const DEVELOPMENT_OPTIONS =
-  drupalSettings.project_browser.development_options;
 export const SORT_OPTIONS = drupalSettings.project_browser.sort_options;
-export const ACTIVELY_MAINTAINED_ID =
-  drupalSettings.project_browser.special_ids.maintenance_status.id;
-export const COVERED_ID =
-  drupalSettings.project_browser.special_ids.security_coverage.id;
-export const ALL_VALUES_ID =
-  drupalSettings.project_browser.special_ids.all_values;
 export const DEFAULT_SOURCE_ID =
   drupalSettings.project_browser.default_plugin_id;
 export const BASE_URL = `${window.location.protocol}//${window.location.host}${drupalSettings.path.baseUrl + drupalSettings.path.pathPrefix}`;
@@ -17,7 +6,7 @@ export const FULL_MODULE_PATH = `${BASE_URL}${drupalSettings.project_browser.mod
 export const DARK_COLOR_SCHEME =
   matchMedia('(forced-colors: active)').matches &&
   matchMedia('(prefers-color-scheme: dark)').matches;
-export const ACTIVE_PLUGINS = drupalSettings.project_browser.active_plugins;
+export const ACTIVE_PLUGIN = drupalSettings.project_browser.active_plugin;
 export const PACKAGE_MANAGER = drupalSettings.project_browser.package_manager;
 export const FILTERS = drupalSettings.project_browser.filters || {};
 export const MAX_SELECTIONS = drupalSettings.project_browser.max_selections;
diff --git a/sveltejs/src/stores.js b/sveltejs/src/stores.js
index 8ec141381f71a7f0d9806e96febe47ea4e786381..77196740905e6ba0be0e8bfc730a17988080912e 100644
--- a/sveltejs/src/stores.js
+++ b/sveltejs/src/stores.js
@@ -7,28 +7,16 @@ import {
 
 // Store the selected tab.
 const storedActiveTab = DEFAULT_SOURCE_ID;
-let activeFilters = {};
-if (storedActiveTab in FILTERS) {
-  activeFilters = FILTERS[storedActiveTab];
-}
-export const sourceFilters = writable(activeFilters);
 
 // Store for applied advanced filters.
-const storedFilters = {
-  developmentStatus: '',
-  maintenanceStatus: '',
-  securityCoverage: ''
-};
-export const filters = writable(storedFilters);
+const defaultFilters = {};
+Object.entries(FILTERS).forEach(([name, definition]) => {
+  defaultFilters[name] = definition.value;
+});
+export const filters = writable(defaultFilters);
 
 export const rowsCount = writable(0);
 
-export const filtersVocabularies = writable({
-  developmentStatus: JSON.parse(localStorage.getItem('pb.developmentStatus')) || [],
-  maintenanceStatus: JSON.parse(localStorage.getItem('pb.maintenanceStatus')) || [],
-  securityCoverage: JSON.parse(localStorage.getItem('pb.securityCoverage')) || []
-});
-
 // Store for applied category filters.
 const storedModuleCategoryFilter = [];
 export const moduleCategoryFilter = writable(storedModuleCategoryFilter);
@@ -38,10 +26,6 @@ const storedModuleCategoryVocabularies = JSON.parse(localStorage.getItem('module
 export const moduleCategoryVocabularies = writable(storedModuleCategoryVocabularies);
 moduleCategoryVocabularies.subscribe((val) => localStorage.setItem('moduleCategoryVocabularies', JSON.stringify(val)));
 
-// Store used to check if the page has loaded once already.
-const storedIsFirstLoad = true;
-export const isFirstLoad = writable(storedIsFirstLoad);
-
 // Store the page the user is on.
 const storedPage = 0;
 export const page = writable(storedPage);
@@ -49,7 +33,7 @@ export const page = writable(storedPage);
 export const activeTab = writable(storedActiveTab);
 
 // Store the current sort selected.
-const storedSort = SORT_OPTIONS[storedActiveTab][0].id;
+const storedSort = SORT_OPTIONS[0].id;
 export const sort = writable(storedSort);
 
 // Store tab-wise checked categories.
@@ -65,7 +49,7 @@ const storedSearchString = '';
 export const searchString = writable(storedSearchString);
 
 // Store for sort criteria.
-const storedSortCriteria = SORT_OPTIONS[storedActiveTab];
+const storedSortCriteria = SORT_OPTIONS;
 export const sortCriteria = writable(storedSortCriteria);
 
 // Store the selected toggle view.
diff --git a/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php b/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
index 081570f20346b7f22d30b5b8a1de65cad6b722ef..bfd5fea1900a1b96e830e117b18cea942dace920 100644
--- a/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
+++ b/tests/modules/project_browser_test/src/Plugin/ProjectBrowserSource/ProjectBrowserTestMock.php
@@ -9,14 +9,11 @@ use Drupal\Core\Database\Connection;
 use Drupal\Core\Extension\ModuleHandlerInterface;
 use Drupal\Core\State\StateInterface;
 use Drupal\Core\Url;
-use Drupal\project_browser\DevelopmentStatus;
-use Drupal\project_browser\MaintenanceStatus;
 use Drupal\project_browser\Plugin\ProjectBrowserSourceBase;
 use Drupal\project_browser\ProjectBrowser\Filter\BooleanFilter;
 use Drupal\project_browser\ProjectBrowser\Filter\MultipleChoiceFilter;
 use Drupal\project_browser\ProjectBrowser\Project;
 use Drupal\project_browser\ProjectBrowser\ProjectsResultsPage;
-use Drupal\project_browser\SecurityStatus;
 use Psr\Log\LoggerInterface;
 use Symfony\Component\DependencyInjection\ContainerInterface;
 
@@ -218,23 +215,10 @@ class ProjectBrowserTestMock extends ProjectBrowserSourceBase {
    */
   protected function convertMaintenance(array &$query) {
     if (!empty($query['maintenance_status'])) {
-      $options_available = MaintenanceStatus::asOptions();
-      if (!in_array($query['maintenance_status'], array_keys($options_available))) {
-        unset($query['maintenance_status']);
-      }
-      else {
-        // Valid value.
-        switch ($query['maintenance_status']) {
-          case MaintenanceStatus::Maintained->value:
-            $query['maintenance_status'] = self::MAINTAINED_VALUES;
-            break;
-
-          case MaintenanceStatus::All->value:
-            unset($query['maintenance_status']);
-            break;
-
-        }
-      }
+      $query['maintenance_status'] = self::MAINTAINED_VALUES;
+    }
+    else {
+      unset($query['maintenance_status']);
     }
   }
 
@@ -246,23 +230,10 @@ class ProjectBrowserTestMock extends ProjectBrowserSourceBase {
    */
   protected function convertDevelopment(array &$query) {
     if (!empty($query['development_status'])) {
-      $options_available = DevelopmentStatus::asOptions();
-      if (!in_array($query['development_status'], array_keys($options_available))) {
-        unset($query['development_status']);
-      }
-      else {
-        // Valid value.
-        switch ($query['development_status']) {
-          case DevelopmentStatus::Active->value:
-            $query['development_status'] = self::ACTIVE_VALUES;
-            break;
-
-          case DevelopmentStatus::All->value:
-            unset($query['development_status']);
-            break;
-
-        }
-      }
+      $query['development_status'] = self::ACTIVE_VALUES;
+    }
+    else {
+      unset($query['development_status']);
     }
   }
 
@@ -274,28 +245,13 @@ class ProjectBrowserTestMock extends ProjectBrowserSourceBase {
    */
   protected function convertSecurity(array &$query) {
     if (!empty($query['security_advisory_coverage'])) {
-      $options_available = SecurityStatus::asOptions();
-      if (!in_array($query['security_advisory_coverage'], array_keys($options_available))) {
-        unset($query['security_advisory_coverage']);
-      }
-      else {
-        // Valid value.
-        switch ($query['security_advisory_coverage']) {
-          case SecurityStatus::Covered->value:
-            $query['security_advisory_coverage'] = self::COVERED_VALUES;
-            break;
-
-          case SecurityStatus::All->value:
-            $keys = [];
-            $options = $this->getSecurityCoverages();
-            foreach ($options as $option) {
-              $keys[] = $option['id'];
-            }
-            $query['security_advisory_coverage'] = $keys;
-            break;
-
-        }
-      }
+      $query['security_advisory_coverage'] = self::COVERED_VALUES;
+    }
+    else {
+      $query['security_advisory_coverage'] = array_column(
+        $this->getSecurityCoverages(),
+        'id'
+      );
     }
   }
 
@@ -367,7 +323,7 @@ class ProjectBrowserTestMock extends ProjectBrowserSourceBase {
       NULL,
     );
     $filters['developmentStatus'] = new BooleanFilter(
-      TRUE,
+      FALSE,
       $this->t('Show projects under active development'),
       $this->t('Show all'),
       $this->t('Development status'),
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
index 7b32c45e59d7aa01919f5351afe47943f1c1995d..16225bf5fd91c8b7dd09f0a59a9123d09a74d466 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserInstallerUiTest.php
@@ -57,8 +57,11 @@ class ProjectBrowserInstallerUiTest extends WebDriverTestBase {
 
     $this->installState = $this->container->get(InstallState::class);
 
-    $this->config('project_browser.admin_settings')->set('enabled_sources', ['project_browser_test_mock'])->save(TRUE);
-    $this->config('project_browser.admin_settings')->set('allow_ui_install', TRUE)->save();
+    $this->config('project_browser.admin_settings')
+      ->set('enabled_sources', ['project_browser_test_mock'])
+      ->set('allow_ui_install', TRUE)
+      ->set('max_selections', 1)
+      ->save();
     $this->drupalLogin($this->drupalCreateUser([
       'administer modules',
       'administer site configuration',
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php b/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php
index 013f583bf2075d048801f9591d2cfab114731a4a..252acbd106e2f8f460f7f6ea7a3999a7432f0f40 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserPluginTest.php
@@ -107,13 +107,11 @@ class ProjectBrowserPluginTest extends WebDriverTestBase {
     $this->assertEquals('Show actively maintained projects', $this->getElementText(self::MAINTENANCE_OPTION_SELECTOR . self::OPTION_CHECKED));
     $this->assertEquals('Show all', $this->getElementText(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_CHECKED));
 
+    $page = $this->getSession()->getPage();
     // Clear the security covered filter.
-    $this->clickWithWait(self::SECURITY_OPTION_SELECTOR . self::OPTION_LAST_CHILD);
-    $this->assertEquals('Show all', $this->getElementText(self::SECURITY_OPTION_SELECTOR . self::OPTION_CHECKED));
-
+    $page->selectFieldOption('securityCoverage', 'Show all');
     // Set the development status filter.
-    $this->clickWithWait(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_FIRST_CHILD);
-    $this->assertEquals('Show projects under active development', $this->getElementText(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_CHECKED));
+    $page->selectFieldOption('developmentStatus', 'Show projects under active development');
 
     // Clear all filters.
     $this->pressWithWait('Clear filters');
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
index 1cb47bf99673a57ac39866b25047bd5af987f026..1d6d87faffa3921e16f718d238bfb26466522238 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTest.php
@@ -70,9 +70,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     $this->getSession()->resizeWindow(1250, 1000);
     $this->drupalGet('admin/modules/browse/project_browser_test_mock');
     $this->svelteInitHelper('css', '.pb-project.pb-project--grid');
-    $assert_session->waitForElementVisible('css', '#pb-project-browser .pb-display__button[value="Grid"]');
-    $grid_text = $this->getElementText('#project-browser .pb-display__button[value="Grid"]');
-    $this->assertEquals('Grid', $grid_text);
+    $this->assertNotEmpty($assert_session->waitForButton('Grid'));
     $this->svelteInitHelper('text', '10 Results');
     $assert_session->elementsCount('css', '#project-browser .pb-project.pb-project--grid', 10);
     $this->assertTrue($assert_session->waitForText('Results'));
@@ -380,10 +378,7 @@ class ProjectBrowserUiTest extends WebDriverTestBase {
     }
 
     // Click the Active filter.
-    $this->clickWithWait(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_FIRST_CHILD);
-
-    // Make sure the correct filter was applied.
-    $this->assertEquals('Show projects under active development', $this->getElementText(self::DEVELOPMENT_OPTION_SELECTOR . self::OPTION_CHECKED));
+    $page->selectFieldOption('developmentStatus', 'Show projects under active development');
 
     $this->assertProjectsVisible([
       'Jazz',
diff --git a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php
index 5d65055a79e5dbd5ae95717ca7041d1198f5a892..85a692f6bd83c94cd5fbe253ec1f801458cf1bca 100644
--- a/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php
+++ b/tests/src/FunctionalJavascript/ProjectBrowserUiTestJsonApi.php
@@ -228,9 +228,7 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase {
     $assert_session->pageTextNotContains(' 0 Results');
 
     // Make sure the second filter applied is the security covered filter.
-    $option = $assert_session->optionExists('securityCoverage', '1');
-    $this->assertSame('Show projects covered by a security policy', $option->getText());
-    $this->assertTrue($option->isSelected());
+    $this->assertTrue($assert_session->optionExists('securityCoverage', 'Show projects covered by a security policy')->isSelected());
 
     // Clear the security covered filter.
     $this->clickWithWait(self::SECURITY_OPTION_SELECTOR . self::OPTION_LAST_CHILD);
@@ -309,11 +307,9 @@ class ProjectBrowserUiTestJsonApi extends WebDriverTestBase {
     $this->pressWithWait('Recommended filters');
 
     // Check that the actively maintained tag is present.
-    $maintenance_checked_option = $this->assertSession()->optionExists('maintenanceStatus', '1');
-    $this->assertTrue($maintenance_checked_option->isSelected());
-    $this->assertEquals('Show actively maintained projects', $maintenance_checked_option->getText());
+    $this->assertTrue($assert_session->optionExists('maintenanceStatus', 'Show actively maintained projects')->isSelected());
     // Make sure the second filter applied is the security covered filter.
-    $assert_session->fieldValueEquals('securityCoverage', '1');
+    $this->assertTrue($assert_session->optionExists('securityCoverage', 'Show projects covered by a security policy')->isSelected());
     $this->assertTrue($assert_session->waitForText(' Results'));
     $assert_session->pageTextNotContains(' 0 Results');
   }
diff --git a/tests/src/Kernel/RecipeActivatorTest.php b/tests/src/Kernel/RecipeActivatorTest.php
index 74adbddce67baffe1689aa09d9ae560124d3b0a6..c832f0d1cc778c1f196a449f577adc21eb45ba10 100644
--- a/tests/src/Kernel/RecipeActivatorTest.php
+++ b/tests/src/Kernel/RecipeActivatorTest.php
@@ -49,8 +49,6 @@ class RecipeActivatorTest extends KernelTestBase {
     $project = new Project(
       logo: [],
       isCompatible: TRUE,
-      isCovered: TRUE,
-      projectUsageTotal: 0,
       machineName: 'My Project',
       body: [],
       title: '',