diff --git a/e2e/test/scenarios/onboarding/home/browse.cy.spec.ts b/e2e/test/scenarios/onboarding/home/browse.cy.spec.ts
index 3f0be43433c3505991b190710454d78fe9c9f371..008b853d894a089239b238250cfb32fd2001e04a 100644
--- a/e2e/test/scenarios/onboarding/home/browse.cy.spec.ts
+++ b/e2e/test/scenarios/onboarding/home/browse.cy.spec.ts
@@ -15,6 +15,11 @@ import {
 
 const { PRODUCTS_ID } = SAMPLE_DATABASE;
 
+const filterButton = () =>
+  cy
+    .findByTestId("browse-models-header")
+    .findByRole("button", { name: /Filters/i });
+
 describeWithSnowplow("scenarios > browse", () => {
   beforeEach(() => {
     resetSnowplow();
@@ -100,7 +105,7 @@ describeWithSnowplow("scenarios > browse", () => {
   it("on an open-source instance, the Browse models page has no controls for setting filters", () => {
     cy.visit("/");
     navigationSidebar().findByLabelText("Browse models").click();
-    cy.findByRole("button", { name: /filter icon/i }).should("not.exist");
+    filterButton().should("not.exist");
     cy.findByRole("switch", { name: /Show verified models only/ }).should(
       "not.exist",
     );
@@ -119,8 +124,7 @@ describeWithSnowplowEE("scenarios > browse (EE)", () => {
     );
     cy.intercept("POST", "/api/moderation-review").as("updateVerification");
   });
-  const openFilterPopover = () =>
-    cy.findByRole("button", { name: /filter icon/i }).click();
+  const openFilterPopover = () => filterButton().click();
   const toggle = () =>
     cy.findByRole("switch", { name: /Show verified models only/ });
 
@@ -132,10 +136,6 @@ describeWithSnowplowEE("scenarios > browse (EE)", () => {
   const recentModel2 = () => recentsGrid().findByText("Model 2");
   const model1Row = () => modelsTable().findByRole("row", { name: /Model 1/i });
   const model2Row = () => modelsTable().findByRole("row", { name: /Model 2/i });
-  const filterButton = () =>
-    cy
-      .findByTestId("browse-models-header")
-      .findByRole("button", { name: /filter icon/i });
 
   const setVerification = (linkSelector: RegExp | string) => {
     cy.findByLabelText("Move, trash, and more...").click();
diff --git a/enterprise/frontend/src/metabase-enterprise/browse/components/BrowseModels.unit.spec.tsx b/enterprise/frontend/src/metabase-enterprise/browse/models/BrowseModels.unit.spec.tsx
similarity index 98%
rename from enterprise/frontend/src/metabase-enterprise/browse/components/BrowseModels.unit.spec.tsx
rename to enterprise/frontend/src/metabase-enterprise/browse/models/BrowseModels.unit.spec.tsx
index 3dc80a5392d18f8c77f1c3a5f5e9507a642df229..f615978b30fb809551ea29fc07dfc07ca6c96160 100644
--- a/enterprise/frontend/src/metabase-enterprise/browse/components/BrowseModels.unit.spec.tsx
+++ b/enterprise/frontend/src/metabase-enterprise/browse/models/BrowseModels.unit.spec.tsx
@@ -6,11 +6,11 @@ import {
 } from "__support__/server-mocks";
 import { mockSettings } from "__support__/settings";
 import { renderWithProviders, screen, within } from "__support__/ui";
-import { BrowseModels } from "metabase/browse/components/BrowseModels";
+import { BrowseModels } from "metabase/browse";
 import {
   createMockModelResult,
   createMockRecentModel,
-} from "metabase/browse/test-utils";
+} from "metabase/browse/models/test-utils";
 import type { RecentCollectionItem } from "metabase-types/api";
 import {
   createMockCollection,
diff --git a/enterprise/frontend/src/metabase-enterprise/collections/utils.unit.spec.tsx b/enterprise/frontend/src/metabase-enterprise/collections/utils.unit.spec.tsx
index 5f3b35e7ee8c793134cecfbd4137eb7096a907b3..0570b2f2cca5eb2b52e2f276e2e69dd7f991affa 100644
--- a/enterprise/frontend/src/metabase-enterprise/collections/utils.unit.spec.tsx
+++ b/enterprise/frontend/src/metabase-enterprise/collections/utils.unit.spec.tsx
@@ -1,7 +1,7 @@
 import { setupEnterprisePlugins } from "__support__/enterprise";
 import { mockSettings } from "__support__/settings";
 import { renderWithProviders } from "__support__/ui";
-import { createMockModelResult } from "metabase/browse/test-utils";
+import { createMockModelResult } from "metabase/browse/models/test-utils";
 import {
   createMockCollection,
   createMockTokenFeatures,
diff --git a/enterprise/frontend/src/metabase-enterprise/content_verification/ModelFilterControls.styled.tsx b/enterprise/frontend/src/metabase-enterprise/content_verification/ModelFilterControls.styled.tsx
deleted file mode 100644
index 88e51c28cb81dad0fd95e15d49bdeb0d8e40a1f9..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/content_verification/ModelFilterControls.styled.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import styled from "@emotion/styled";
-
-import { Text } from "metabase/ui";
-
-export const ModelFilterControlSwitchLabel = styled(Text)`
-  text-align: right;
-  font-weight: bold;
-  line-height: 1rem;
-  padding: 0 0.75rem;
-`;
diff --git a/enterprise/frontend/src/metabase-enterprise/content_verification/ModelFilterControls.tsx b/enterprise/frontend/src/metabase-enterprise/content_verification/ModelFilterControls.tsx
deleted file mode 100644
index 1acb1250272fd255b8abbd856adef2a6b10684dc..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/content_verification/ModelFilterControls.tsx
+++ /dev/null
@@ -1,82 +0,0 @@
-import { useCallback } from "react";
-import { t } from "ttag";
-import _ from "underscore";
-
-import type {
-  ActualModelFilters,
-  ModelFilterControlsProps,
-} from "metabase/browse/utils";
-import { useUserSetting } from "metabase/common/hooks";
-import { Button, Icon, Paper, Popover, Switch, Text } from "metabase/ui";
-
-export const ModelFilterControls = ({
-  actualModelFilters,
-  setActualModelFilters,
-}: ModelFilterControlsProps) => {
-  const [__, setVerifiedFilterStatus] = useUserSetting(
-    "browse-filter-only-verified-models",
-    { shouldRefresh: false },
-  );
-  const setVerifiedFilterStatusDebounced = _.debounce(
-    setVerifiedFilterStatus,
-    200,
-  );
-
-  const handleModelFilterChange = useCallback(
-    (modelFilterName: string, active: boolean) => {
-      // For now, only one filter is supported
-      setVerifiedFilterStatusDebounced(active);
-      setActualModelFilters((prev: ActualModelFilters) => {
-        return { ...prev, [modelFilterName]: active };
-      });
-    },
-    [setActualModelFilters, setVerifiedFilterStatusDebounced],
-  );
-
-  // There's only one filter for now
-  const filters = [actualModelFilters.onlyShowVerifiedModels];
-
-  const areAnyFiltersActive = filters.some(filter => filter);
-
-  return (
-    <Popover position="bottom-end">
-      <Popover.Target>
-        <Button p="sm" lh={0} variant="subtle" color="text-dark" pos="relative">
-          {areAnyFiltersActive && <Dot />}
-          <Icon name="filter" />
-        </Button>
-      </Popover.Target>
-      <Popover.Dropdown p="lg">
-        <Switch
-          label={
-            <Text
-              align="end"
-              weight="bold"
-            >{t`Show verified models only`}</Text>
-          }
-          role="switch"
-          checked={actualModelFilters.onlyShowVerifiedModels}
-          onChange={e => {
-            handleModelFilterChange("onlyShowVerifiedModels", e.target.checked);
-          }}
-          labelPosition="left"
-        />
-      </Popover.Dropdown>
-    </Popover>
-  );
-};
-
-const Dot = () => {
-  return (
-    <Paper
-      pos="absolute"
-      right="0px"
-      top="7px"
-      radius="50%"
-      bg={"var(--mb-color-brand)"}
-      w="sm"
-      h="sm"
-      data-testid="filter-dot"
-    />
-  );
-};
diff --git a/enterprise/frontend/src/metabase-enterprise/content_verification/index.ts b/enterprise/frontend/src/metabase-enterprise/content_verification/index.ts
index a5c206fcb98b94d49974a472837f0f93083e80eb..1e318383b25edbd3e7e67f1088909db8c362d53e 100644
--- a/enterprise/frontend/src/metabase-enterprise/content_verification/index.ts
+++ b/enterprise/frontend/src/metabase-enterprise/content_verification/index.ts
@@ -1,19 +1,18 @@
 import { PLUGIN_CONTENT_VERIFICATION } from "metabase/plugins";
 import { hasPremiumFeature } from "metabase-enterprise/settings";
 
-import { ModelFilterControls } from "./ModelFilterControls";
 import { VerifiedFilter } from "./VerifiedFilter";
 import { MetricFilterControls, getDefaultMetricFilters } from "./metrics";
-import { availableModelFilters, useModelFilterSettings } from "./utils";
+import { ModelFilterControls, getDefaultModelFilters } from "./models";
 
 if (hasPremiumFeature("content_verification")) {
   Object.assign(PLUGIN_CONTENT_VERIFICATION, {
+    contentVerificationEnabled: true,
     VerifiedFilter,
+
     ModelFilterControls,
-    availableModelFilters,
-    useModelFilterSettings,
+    getDefaultModelFilters,
 
-    contentVerificationEnabled: true,
     getDefaultMetricFilters,
     MetricFilterControls,
   });
diff --git a/enterprise/frontend/src/metabase-enterprise/content_verification/metrics.tsx b/enterprise/frontend/src/metabase-enterprise/content_verification/metrics.tsx
index 7a78ad6f1511bbedc8c06bdb0818aaa265318ea6..2522465ddb1fbb0c8b6e6d2392223d4279f291ed 100644
--- a/enterprise/frontend/src/metabase-enterprise/content_verification/metrics.tsx
+++ b/enterprise/frontend/src/metabase-enterprise/content_verification/metrics.tsx
@@ -4,7 +4,7 @@ import { t } from "ttag";
 import type {
   MetricFilterControlsProps,
   MetricFilterSettings,
-} from "metabase/browse/utils";
+} from "metabase/browse/metrics";
 import { useUserSetting } from "metabase/common/hooks";
 import { getSetting } from "metabase/selectors/settings";
 import { Button, Icon, Paper, Popover, Switch, Text } from "metabase/ui";
diff --git a/enterprise/frontend/src/metabase-enterprise/content_verification/models.tsx b/enterprise/frontend/src/metabase-enterprise/content_verification/models.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7d9f473960d0bfd978de96bb8cae090ba3d609cc
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/content_verification/models.tsx
@@ -0,0 +1,85 @@
+import { type ChangeEvent, useCallback } from "react";
+import { t } from "ttag";
+
+import type {
+  ModelFilterControlsProps,
+  ModelFilterSettings,
+} from "metabase/browse/models";
+import { useUserSetting } from "metabase/common/hooks";
+import { getSetting } from "metabase/selectors/settings";
+import { Button, Icon, Paper, Popover, Switch, Text } from "metabase/ui";
+import type { State } from "metabase-types/store";
+
+const USER_SETTING_KEY = "browse-filter-only-verified-models";
+
+export function getDefaultModelFilters(state: State): ModelFilterSettings {
+  return {
+    verified: getSetting(state, USER_SETTING_KEY) ?? false,
+  };
+}
+
+// This component is similar to the MetricFilterControls component from ./MetricFilterControls.tsx
+// merging them might be a good idea in the future.
+export const ModelFilterControls = ({
+  modelFilters,
+  setModelFilters,
+}: ModelFilterControlsProps) => {
+  const areAnyFiltersActive = Object.values(modelFilters).some(Boolean);
+
+  const [_, setUserSetting] = useUserSetting(USER_SETTING_KEY);
+
+  const handleVerifiedFilterChange = useCallback(
+    function (evt: ChangeEvent<HTMLInputElement>) {
+      setModelFilters({ ...modelFilters, verified: evt.target.checked });
+      setUserSetting(evt.target.checked);
+    },
+    [modelFilters, setModelFilters, setUserSetting],
+  );
+
+  return (
+    <Popover position="bottom-end">
+      <Popover.Target>
+        <Button
+          p="sm"
+          lh={0}
+          variant="subtle"
+          color="var(--mb-color-text-dark)"
+          pos="relative"
+          aria-label={t`Filters`}
+        >
+          {areAnyFiltersActive && <Dot />}
+          <Icon name="filter" />
+        </Button>
+      </Popover.Target>
+      <Popover.Dropdown p="lg">
+        <Switch
+          label={
+            <Text
+              align="end"
+              weight="bold"
+            >{t`Show verified models only`}</Text>
+          }
+          role="switch"
+          checked={Boolean(modelFilters.verified)}
+          onChange={handleVerifiedFilterChange}
+          labelPosition="left"
+        />
+      </Popover.Dropdown>
+    </Popover>
+  );
+};
+
+const Dot = () => {
+  return (
+    <Paper
+      pos="absolute"
+      right="0px"
+      top="7px"
+      radius="50%"
+      bg={"var(--mb-color-brand)"}
+      w="sm"
+      h="sm"
+      data-testid="filter-dot"
+    />
+  );
+};
diff --git a/enterprise/frontend/src/metabase-enterprise/content_verification/utils.ts b/enterprise/frontend/src/metabase-enterprise/content_verification/utils.ts
deleted file mode 100644
index 5e7f5968c03495f41beda64a4cb139fcab7fe8cd..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/content_verification/utils.ts
+++ /dev/null
@@ -1,40 +0,0 @@
-import type { Dispatch, SetStateAction } from "react";
-import { useEffect, useMemo, useState } from "react";
-
-import type {
-  ActualModelFilters,
-  AvailableModelFilters,
-} from "metabase/browse/utils";
-import { useUserSetting } from "metabase/common/hooks";
-
-export const availableModelFilters: AvailableModelFilters = {
-  onlyShowVerifiedModels: {
-    predicate: model => model.moderated_status === "verified",
-    activeByDefault: true,
-  },
-};
-
-export const useModelFilterSettings = (): [
-  ActualModelFilters,
-  Dispatch<SetStateAction<ActualModelFilters>>,
-] => {
-  const [initialVerifiedFilterStatus] = useUserSetting(
-    "browse-filter-only-verified-models",
-    { shouldRefresh: false },
-  );
-  const initialModelFilters = useMemo(
-    () => ({
-      onlyShowVerifiedModels: initialVerifiedFilterStatus ?? false,
-    }),
-    [initialVerifiedFilterStatus],
-  );
-
-  const [actualModelFilters, setActualModelFilters] =
-    useState<ActualModelFilters>(initialModelFilters);
-
-  useEffect(() => {
-    setActualModelFilters(initialModelFilters);
-  }, [initialModelFilters, setActualModelFilters]);
-
-  return [actualModelFilters, setActualModelFilters];
-};
diff --git a/enterprise/frontend/src/metabase-enterprise/content_verification/utils.unit.spec.ts b/enterprise/frontend/src/metabase-enterprise/content_verification/utils.unit.spec.ts
deleted file mode 100644
index 0a65bb1485c62ec6b45c510f93f1c752a8a2cf46..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/content_verification/utils.unit.spec.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { createMockModelResult } from "metabase/browse/test-utils";
-
-import { availableModelFilters } from "./utils";
-
-describe("Utilities related to content verification", () => {
-  it("include a constant that defines a filter for only showing verified models", () => {
-    const models = [
-      createMockModelResult({
-        name: "A verified model",
-        moderated_status: "verified",
-      }),
-      createMockModelResult({
-        name: "An unverified model",
-        moderated_status: null,
-      }),
-    ];
-    const filteredModels = models.filter(
-      availableModelFilters.onlyShowVerifiedModels.predicate,
-    );
-    expect(filteredModels.length).toBe(1);
-    expect(filteredModels[0].name).toBe("A verified model");
-  });
-});
diff --git a/frontend/src/metabase/browse/components/BrowseModels.tsx b/frontend/src/metabase/browse/components/BrowseModels.tsx
deleted file mode 100644
index 94e62e4c21eec54549dce340d37c35b8d9d65563..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/browse/components/BrowseModels.tsx
+++ /dev/null
@@ -1,161 +0,0 @@
-import { useMemo } from "react";
-import { t } from "ttag";
-
-import NoResults from "assets/img/no_results.svg";
-import { useListRecentsQuery } from "metabase/api";
-import { useFetchModels } from "metabase/common/hooks/use-fetch-models";
-import { DelayedLoadingAndErrorWrapper } from "metabase/components/LoadingAndErrorWrapper/DelayedLoadingAndErrorWrapper";
-import {
-  PLUGIN_COLLECTIONS,
-  PLUGIN_CONTENT_VERIFICATION,
-} from "metabase/plugins";
-import { Box, Flex, Group, Icon, Stack, Title } from "metabase/ui";
-
-import type { ModelResult } from "../types";
-import { isRecentModel } from "../types";
-import { filterModels } from "../utils";
-
-import {
-  BrowseContainer,
-  BrowseHeader,
-  BrowseMain,
-  BrowseSection,
-  CenteredEmptyState,
-} from "./BrowseContainer.styled";
-import { ModelExplanationBanner } from "./ModelExplanationBanner";
-import { ModelsTable } from "./ModelsTable";
-import { RecentModels } from "./RecentModels";
-import { getMaxRecentModelCount } from "./utils";
-
-const { availableModelFilters, useModelFilterSettings, ModelFilterControls } =
-  PLUGIN_CONTENT_VERIFICATION;
-
-export const BrowseModels = () => {
-  /** Mapping of filter names to true if the filter is active or false if it is inactive */
-  const [actualModelFilters, setActualModelFilters] = useModelFilterSettings();
-
-  const modelsResult = useFetchModels({ model_ancestors: true });
-
-  const { models, doVerifiedModelsExist } = useMemo(() => {
-    const unfilteredModels =
-      (modelsResult.data?.data as ModelResult[] | undefined) ?? [];
-    const doVerifiedModelsExist = unfilteredModels.some(
-      model => model.moderated_status === "verified",
-    );
-    const models =
-      PLUGIN_COLLECTIONS.filterOutItemsFromInstanceAnalytics(unfilteredModels);
-    return { models, doVerifiedModelsExist };
-  }, [modelsResult]);
-
-  const { filteredModels } = useMemo(() => {
-    const filteredModels = filterModels(
-      models,
-      // If no models are verified, don't filter them
-      doVerifiedModelsExist ? actualModelFilters : {},
-      availableModelFilters,
-    );
-    return { filteredModels };
-  }, [actualModelFilters, models, doVerifiedModelsExist]);
-
-  const recentModelsResult = useListRecentsQuery(undefined, {
-    refetchOnMountOrArgChange: true,
-  });
-
-  const filteredRecentModels = useMemo(
-    () =>
-      filterModels(
-        recentModelsResult.data?.filter(isRecentModel),
-        // If no models are verified, don't filter them
-        doVerifiedModelsExist ? actualModelFilters : {},
-        availableModelFilters,
-      ),
-    [recentModelsResult.data, actualModelFilters, doVerifiedModelsExist],
-  );
-
-  const recentModels = useMemo(() => {
-    const cap = getMaxRecentModelCount(models.length);
-    return filteredRecentModels.slice(0, cap);
-  }, [filteredRecentModels, models.length]);
-
-  const isEmpty =
-    !recentModelsResult.isLoading &&
-    !modelsResult.isLoading &&
-    !filteredModels.length;
-
-  return (
-    <BrowseContainer>
-      <BrowseHeader role="heading" data-testid="browse-models-header">
-        <BrowseSection>
-          <Flex
-            w="100%"
-            h="2.25rem"
-            direction="row"
-            justify="space-between"
-            align="center"
-          >
-            <Title order={1} color="text-dark">
-              <Group spacing="sm">
-                <Icon
-                  size={24}
-                  color="var(--mb-color-icon-primary)"
-                  name="model"
-                />
-                {t`Models`}
-              </Group>
-            </Title>
-            {doVerifiedModelsExist && (
-              <ModelFilterControls
-                actualModelFilters={actualModelFilters}
-                setActualModelFilters={setActualModelFilters}
-              />
-            )}
-          </Flex>
-        </BrowseSection>
-      </BrowseHeader>
-      <BrowseMain>
-        <BrowseSection>
-          <Stack mb="lg" spacing="md" w="100%">
-            {isEmpty ? (
-              <CenteredEmptyState
-                title={<Box mb=".5rem">{t`No models here yet`}</Box>}
-                message={
-                  <Box maw="24rem">{t`Models help curate data to make it easier to find answers to questions all in one place.`}</Box>
-                }
-                illustrationElement={
-                  <Box mb=".5rem">
-                    <img src={NoResults} />
-                  </Box>
-                }
-              />
-            ) : (
-              <>
-                <ModelExplanationBanner />
-                <DelayedLoadingAndErrorWrapper
-                  error={recentModelsResult.error}
-                  loading={
-                    // If the main models result is still pending, the list of recently viewed
-                    // models isn't ready yet, since the number of recently viewed models is
-                    // capped according to the size of the main models result
-                    recentModelsResult.isLoading || modelsResult.isLoading
-                  }
-                  style={{ flex: 1 }}
-                  loader={<RecentModels skeleton />}
-                >
-                  <RecentModels models={recentModels} />
-                </DelayedLoadingAndErrorWrapper>
-                <DelayedLoadingAndErrorWrapper
-                  error={modelsResult.error}
-                  loading={modelsResult.isLoading}
-                  style={{ flex: 1 }}
-                  loader={<ModelsTable skeleton />}
-                >
-                  <ModelsTable models={filteredModels} />
-                </DelayedLoadingAndErrorWrapper>
-              </>
-            )}
-          </Stack>
-        </BrowseSection>
-      </BrowseMain>
-    </BrowseContainer>
-  );
-};
diff --git a/frontend/src/metabase/browse/containers/TableBrowser/TableBrowser.jsx b/frontend/src/metabase/browse/containers/TableBrowser/TableBrowser.jsx
index f762df7e2a1105c5328731b08b6bbbeaa85c025a..37ea6879b89cb6a413819e9be23b698c78556c31 100644
--- a/frontend/src/metabase/browse/containers/TableBrowser/TableBrowser.jsx
+++ b/frontend/src/metabase/browse/containers/TableBrowser/TableBrowser.jsx
@@ -9,8 +9,8 @@ import { getSetting } from "metabase/selectors/settings";
 import { SAVED_QUESTIONS_VIRTUAL_DB_ID } from "metabase-lib/v1/metadata/utils/saved-questions";
 import * as ML_Urls from "metabase-lib/v1/urls";
 
-import TableBrowser from "../../components/TableBrowser";
 import { RELOAD_INTERVAL } from "../../constants";
+import TableBrowser from "../../tables/TableBrowser";
 
 const getDatabaseId = (props, { includeVirtual } = {}) => {
   const { params } = props;
diff --git a/frontend/src/metabase/browse/components/BrowseDatabases.styled.tsx b/frontend/src/metabase/browse/databases/BrowseDatabases.styled.tsx
similarity index 86%
rename from frontend/src/metabase/browse/components/BrowseDatabases.styled.tsx
rename to frontend/src/metabase/browse/databases/BrowseDatabases.styled.tsx
index 7ed6b06559958d44142eb0c882afae2022f5bc09..87a3679a3471e7b885d6e53b34519df14384ee81 100644
--- a/frontend/src/metabase/browse/components/BrowseDatabases.styled.tsx
+++ b/frontend/src/metabase/browse/databases/BrowseDatabases.styled.tsx
@@ -3,7 +3,7 @@ import { Link } from "react-router";
 
 import Card from "metabase/components/Card";
 
-import { BrowseGrid } from "./BrowseContainer.styled";
+import { BrowseGrid } from "../components/BrowseContainer.styled";
 
 export const DatabaseGrid = styled(BrowseGrid)``;
 
diff --git a/frontend/src/metabase/browse/components/BrowseDatabases.tsx b/frontend/src/metabase/browse/databases/BrowseDatabases.tsx
similarity index 94%
rename from frontend/src/metabase/browse/components/BrowseDatabases.tsx
rename to frontend/src/metabase/browse/databases/BrowseDatabases.tsx
index 1690c1cb420cd5104553b3aaa6fe750d6dca4a4d..93d61a1bd22bbfcfd0fa58b93e6b364ba441e2a2 100644
--- a/frontend/src/metabase/browse/components/BrowseDatabases.tsx
+++ b/frontend/src/metabase/browse/databases/BrowseDatabases.tsx
@@ -13,8 +13,9 @@ import {
   BrowseMain,
   BrowseSection,
   CenteredEmptyState,
-} from "./BrowseContainer.styled";
-import { BrowseDataHeader } from "./BrowseDataHeader";
+} from "../components/BrowseContainer.styled";
+import { BrowseDataHeader } from "../components/BrowseDataHeader";
+
 import {
   DatabaseCard,
   DatabaseCardLink,
diff --git a/frontend/src/metabase/browse/components/BrowseDatabases.unit.spec.tsx b/frontend/src/metabase/browse/databases/BrowseDatabases.unit.spec.tsx
similarity index 100%
rename from frontend/src/metabase/browse/components/BrowseDatabases.unit.spec.tsx
rename to frontend/src/metabase/browse/databases/BrowseDatabases.unit.spec.tsx
diff --git a/frontend/src/metabase/browse/databases/index.tsx b/frontend/src/metabase/browse/databases/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7529e040d02997291f914c3dd88ca41e776c4bc6
--- /dev/null
+++ b/frontend/src/metabase/browse/databases/index.tsx
@@ -0,0 +1 @@
+export { BrowseDatabases } from "./BrowseDatabases";
diff --git a/frontend/src/metabase/browse/index.tsx b/frontend/src/metabase/browse/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a9e26c2d9a22fcbfd2f96bf5a6b1e1d132610ae7
--- /dev/null
+++ b/frontend/src/metabase/browse/index.tsx
@@ -0,0 +1,5 @@
+export { BrowseMetrics } from "./metrics";
+export { BrowseModels } from "./models";
+export { BrowseDatabases } from "./databases";
+export { BrowseTables } from "./tables";
+export { BrowseSchemas } from "./schemas";
diff --git a/frontend/src/metabase/browse/components/BrowseMetrics.tsx b/frontend/src/metabase/browse/metrics/BrowseMetrics.tsx
similarity index 97%
rename from frontend/src/metabase/browse/components/BrowseMetrics.tsx
rename to frontend/src/metabase/browse/metrics/BrowseMetrics.tsx
index 4a8c48f0421aaece1d309bbac7e3ab9534e61122..66264f2a439198088f8539b597ec2fbaf6f7cd31 100644
--- a/frontend/src/metabase/browse/components/BrowseMetrics.tsx
+++ b/frontend/src/metabase/browse/metrics/BrowseMetrics.tsx
@@ -10,16 +10,15 @@ import { useSelector } from "metabase/lib/redux";
 import { PLUGIN_CONTENT_VERIFICATION } from "metabase/plugins";
 import { Box, Flex, Group, Icon, Stack, Text, Title } from "metabase/ui";
 
-import type { MetricResult } from "../types";
-import type { MetricFilterSettings } from "../utils";
-
 import {
   BrowseContainer,
   BrowseHeader,
   BrowseMain,
   BrowseSection,
-} from "./BrowseContainer.styled";
+} from "../components/BrowseContainer.styled";
+
 import { MetricsTable } from "./MetricsTable";
+import type { MetricFilterSettings, MetricResult } from "./types";
 
 const {
   contentVerificationEnabled,
diff --git a/frontend/src/metabase/browse/components/BrowseMetrics.unit.spec.tsx b/frontend/src/metabase/browse/metrics/BrowseMetrics.unit.spec.tsx
similarity index 98%
rename from frontend/src/metabase/browse/components/BrowseMetrics.unit.spec.tsx
rename to frontend/src/metabase/browse/metrics/BrowseMetrics.unit.spec.tsx
index b5335e1e03d1c362304dd7113509e0289cacf2f7..d7a5c4d28f1e53af51f2a695e322fda18e8f8d37 100644
--- a/frontend/src/metabase/browse/components/BrowseMetrics.unit.spec.tsx
+++ b/frontend/src/metabase/browse/metrics/BrowseMetrics.unit.spec.tsx
@@ -14,10 +14,9 @@ import {
 } from "metabase-types/api/mocks";
 import { createMockSetupState } from "metabase-types/store/mocks";
 
-import { createMockMetricResult, createMockRecentMetric } from "../test-utils";
-import type { MetricResult, RecentMetric } from "../types";
-
 import { BrowseMetrics } from "./BrowseMetrics";
+import { createMockMetricResult, createMockRecentMetric } from "./test-utils";
+import type { MetricResult, RecentMetric } from "./types";
 
 type SetupOpts = {
   metricCount?: number;
diff --git a/frontend/src/metabase/browse/components/MetricsTable.tsx b/frontend/src/metabase/browse/metrics/MetricsTable.tsx
similarity index 98%
rename from frontend/src/metabase/browse/components/MetricsTable.tsx
rename to frontend/src/metabase/browse/metrics/MetricsTable.tsx
index 7721eadb578fc46b49e779bc2d6312c219e3df9c..07971547644a244af7abb4d90cc17248c922582f 100644
--- a/frontend/src/metabase/browse/components/MetricsTable.tsx
+++ b/frontend/src/metabase/browse/metrics/MetricsTable.tsx
@@ -42,8 +42,6 @@ import {
 import { Repeat } from "metabase/ui/components/feedback/Skeleton/Repeat";
 import { SortDirection, type SortingOptions } from "metabase-types/api/sorting";
 
-import type { MetricResult } from "../types";
-
 import {
   Cell,
   CollectionLink,
@@ -53,11 +51,13 @@ import {
   Value,
   ValueTableCell,
   ValueWrapper,
-} from "./BrowseTable.styled";
+} from "../components/BrowseTable.styled";
+
+import type { MetricResult } from "./types";
 import {
   getDatasetValueForMetric,
   getMetricDescription,
-  sortModelOrMetric,
+  sortMetrics,
 } from "./utils";
 
 type MetricsTableProps = {
@@ -109,7 +109,7 @@ export function MetricsTable({
   );
 
   const locale = useLocale();
-  const sortedMetrics = sortModelOrMetric(metrics, sortingOptions, locale);
+  const sortedMetrics = sortMetrics(metrics, sortingOptions, locale);
 
   const handleSortingOptionsChange = skeleton ? undefined : setSortingOptions;
 
diff --git a/frontend/src/metabase/browse/metrics/index.tsx b/frontend/src/metabase/browse/metrics/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..9eefac1ac955fed05b847ef5bac3663021ce8034
--- /dev/null
+++ b/frontend/src/metabase/browse/metrics/index.tsx
@@ -0,0 +1,6 @@
+export { BrowseMetrics } from "./BrowseMetrics";
+export type {
+  MetricFilterControlsProps,
+  MetricFilterSettings,
+  RecentMetric,
+} from "./types";
diff --git a/frontend/src/metabase/browse/metrics/test-utils.ts b/frontend/src/metabase/browse/metrics/test-utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..a420b268588a0fa164193c15e15783e9353d370d
--- /dev/null
+++ b/frontend/src/metabase/browse/metrics/test-utils.ts
@@ -0,0 +1,19 @@
+import {
+  createMockRecentCollectionItem,
+  createMockSearchResult,
+} from "metabase-types/api/mocks";
+
+import type { MetricResult, RecentMetric } from "./types";
+
+export const createMockMetricResult = (
+  metric: Partial<MetricResult> = {},
+): MetricResult =>
+  createMockSearchResult({ ...metric, model: "metric" }) as MetricResult;
+
+export const createMockRecentMetric = (
+  metric: Partial<RecentMetric>,
+): RecentMetric =>
+  createMockRecentCollectionItem({
+    ...metric,
+    model: "metric",
+  }) as RecentMetric;
diff --git a/frontend/src/metabase/browse/metrics/types.tsx b/frontend/src/metabase/browse/metrics/types.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f3ba40104fcaced1a0e98079a8487908fea0f9ff
--- /dev/null
+++ b/frontend/src/metabase/browse/metrics/types.tsx
@@ -0,0 +1,19 @@
+import type { RecentCollectionItem, SearchResult } from "metabase-types/api";
+
+/**
+ * Metric retrieved through the search endpoint
+ */
+export type MetricResult = SearchResult<number, "metric">;
+
+export interface RecentMetric extends RecentCollectionItem {
+  model: "metric";
+}
+
+export type MetricFilterSettings = {
+  verified?: boolean;
+};
+
+export type MetricFilterControlsProps = {
+  metricFilters: MetricFilterSettings;
+  setMetricFilters: (settings: MetricFilterSettings) => void;
+};
diff --git a/frontend/src/metabase/browse/components/utils.tsx b/frontend/src/metabase/browse/metrics/utils.tsx
similarity index 68%
rename from frontend/src/metabase/browse/components/utils.tsx
rename to frontend/src/metabase/browse/metrics/utils.tsx
index c12fb60054eca2c12576fa2023f61a580929e99c..919e223535fdb02e2bd8aea017b7714fc0c8b1d5 100644
--- a/frontend/src/metabase/browse/components/utils.tsx
+++ b/frontend/src/metabase/browse/metrics/utils.tsx
@@ -3,24 +3,10 @@ import { t } from "ttag";
 import { getCollectionPathAsString } from "metabase/collections/utils";
 import { formatValue } from "metabase/lib/formatting";
 import { isDate } from "metabase-lib/v1/types/utils/isa";
-import type { Dataset, SearchResult } from "metabase-types/api";
+import type { Dataset } from "metabase-types/api";
 import { SortDirection, type SortingOptions } from "metabase-types/api/sorting";
 
-import type { MetricResult, ModelResult } from "../types";
-
-export type ModelOrMetricResult = ModelResult | MetricResult;
-
-export const isModel = (item: SearchResult) => item.model === "dataset";
-
-export const getModelDescription = (item: ModelResult) => {
-  if (item.collection && !item.description?.trim()) {
-    return t`A model`;
-  } else {
-    return item.description;
-  }
-};
-
-export const isMetric = (item: SearchResult) => item.model === "metric";
+import type { MetricResult } from "./types";
 
 export const getMetricDescription = (item: MetricResult) => {
   if (item.collection && !item.description?.trim()) {
@@ -31,30 +17,30 @@ export const getMetricDescription = (item: MetricResult) => {
 };
 
 const getValueForSorting = (
-  model: ModelResult | MetricResult,
-  sort_column: keyof ModelResult,
+  metric: MetricResult,
+  sort_column: keyof MetricResult,
 ): string => {
   if (sort_column === "collection") {
-    return getCollectionPathAsString(model.collection) ?? "";
+    return getCollectionPathAsString(metric.collection) ?? "";
   } else {
-    return model[sort_column] ?? "";
+    return metric[sort_column] ?? "";
   }
 };
 
 export const isValidSortColumn = (
   sort_column: string,
-): sort_column is keyof ModelResult => {
+): sort_column is keyof MetricResult => {
   return ["name", "collection", "description"].includes(sort_column);
 };
 
 export const getSecondarySortColumn = (
   sort_column: string,
-): keyof ModelResult => {
+): keyof MetricResult => {
   return sort_column === "name" ? "collection" : "name";
 };
 
-export function sortModelOrMetric<T extends ModelOrMetricResult>(
-  modelsOrMetrics: T[],
+export function sortMetrics(
+  metrics: MetricResult[],
   sortingOptions: SortingOptions,
   localeCode: string = "en",
 ) {
@@ -62,21 +48,21 @@ export function sortModelOrMetric<T extends ModelOrMetricResult>(
 
   if (!isValidSortColumn(sort_column)) {
     console.error("Invalid sort column", sort_column);
-    return modelsOrMetrics;
+    return metrics;
   }
 
   const compare = (a: string, b: string) =>
     a.localeCompare(b, localeCode, { sensitivity: "base" });
 
-  return [...modelsOrMetrics].sort((modelOrMetricA, modelOrMetricB) => {
-    const a = getValueForSorting(modelOrMetricA, sort_column);
-    const b = getValueForSorting(modelOrMetricB, sort_column);
+  return [...metrics].sort((metricA, metricB) => {
+    const a = getValueForSorting(metricA, sort_column);
+    const b = getValueForSorting(metricB, sort_column);
 
     let result = compare(a, b);
     if (result === 0) {
       const sort_column2 = getSecondarySortColumn(sort_column);
-      const a2 = getValueForSorting(modelOrMetricA, sort_column2);
-      const b2 = getValueForSorting(modelOrMetricB, sort_column2);
+      const a2 = getValueForSorting(metricA, sort_column2);
+      const b2 = getValueForSorting(metricB, sort_column2);
       result = compare(a2, b2);
     }
 
@@ -84,22 +70,6 @@ export function sortModelOrMetric<T extends ModelOrMetricResult>(
   });
 }
 
-/** Find the maximum number of recently viewed models to show.
- * This is roughly proportional to the number of models the user
- * has permission to see */
-export const getMaxRecentModelCount = (
-  /** How many models the user has permission to see */
-  modelCount: number,
-) => {
-  if (modelCount > 20) {
-    return 8;
-  }
-  if (modelCount > 9) {
-    return 4;
-  }
-  return 0;
-};
-
 export function isDatasetScalar(dataset: Dataset) {
   if (dataset.error) {
     return false;
diff --git a/frontend/src/metabase/browse/components/utils.unit.spec.tsx b/frontend/src/metabase/browse/metrics/utils.unit.spec.tsx
similarity index 72%
rename from frontend/src/metabase/browse/components/utils.unit.spec.tsx
rename to frontend/src/metabase/browse/metrics/utils.unit.spec.tsx
index 1c22219bead8eb4dd058f3473df03c36b7e34a72..325dd859a520f93924d1d38936430055fd685cd2 100644
--- a/frontend/src/metabase/browse/components/utils.unit.spec.tsx
+++ b/frontend/src/metabase/browse/metrics/utils.unit.spec.tsx
@@ -6,20 +6,18 @@ import {
 } from "metabase-types/api/mocks";
 import { SortDirection } from "metabase-types/api/sorting";
 
-import { createMockModelResult } from "../test-utils";
-import type { ModelResult } from "../types";
-
+import { createMockMetricResult } from "./test-utils";
+import type { MetricResult } from "./types";
 import {
   getDatasetValueForMetric,
-  getMaxRecentModelCount,
   isDatasetScalar,
-  sortModelOrMetric,
+  sortMetrics,
 } from "./utils";
 
-describe("sortModels", () => {
+describe("sortMetrics", () => {
   let id = 0;
-  const modelMap: Record<string, ModelResult> = {
-    "model named A, with collection path X / Y / Z": createMockModelResult({
+  const metricMap: Record<string, MetricResult> = {
+    "model named A, with collection path X / Y / Z": createMockMetricResult({
       id: id++,
       name: "A",
       collection: createMockCollection({
@@ -30,12 +28,12 @@ describe("sortModels", () => {
         ],
       }),
     }),
-    "model named C, with collection path Y": createMockModelResult({
+    "model named C, with collection path Y": createMockMetricResult({
       id: id++,
       name: "C",
       collection: createMockCollection({ name: "Y" }),
     }),
-    "model named B, with collection path D / E / F": createMockModelResult({
+    "model named B, with collection path D / E / F": createMockMetricResult({
       id: id++,
       name: "B",
       collection: createMockCollection({
@@ -47,14 +45,14 @@ describe("sortModels", () => {
       }),
     }),
   };
-  const mockSearchResults = Object.values(modelMap);
+  const mockSearchResults = Object.values(metricMap);
 
   it("can sort by name in ascending order", () => {
     const sortingOptions = {
       sort_column: "name",
       sort_direction: SortDirection.Asc,
     } as const;
-    const sorted = sortModelOrMetric(mockSearchResults, sortingOptions);
+    const sorted = sortMetrics(mockSearchResults, sortingOptions);
     expect(sorted?.map(model => model.name)).toEqual(["A", "B", "C"]);
   });
 
@@ -63,7 +61,7 @@ describe("sortModels", () => {
       sort_column: "name",
       sort_direction: SortDirection.Desc,
     } as const;
-    const sorted = sortModelOrMetric(mockSearchResults, sortingOptions);
+    const sorted = sortMetrics(mockSearchResults, sortingOptions);
     expect(sorted?.map(model => model.name)).toEqual(["C", "B", "A"]);
   });
 
@@ -72,7 +70,7 @@ describe("sortModels", () => {
       sort_column: "collection",
       sort_direction: SortDirection.Asc,
     } as const;
-    const sorted = sortModelOrMetric(mockSearchResults, sortingOptions);
+    const sorted = sortMetrics(mockSearchResults, sortingOptions);
     expect(sorted?.map(model => model.name)).toEqual(["B", "A", "C"]);
   });
 
@@ -81,17 +79,19 @@ describe("sortModels", () => {
       sort_column: "collection",
       sort_direction: SortDirection.Desc,
     } as const;
-    const sorted = sortModelOrMetric(mockSearchResults, sortingOptions);
+    const sorted = sortMetrics(mockSearchResults, sortingOptions);
     expect(sorted?.map(model => model.name)).toEqual(["C", "A", "B"]);
   });
 
   describe("secondary sort", () => {
-    modelMap["model named C, with collection path Z"] = createMockModelResult({
-      name: "C",
-      collection: createMockCollection({ name: "Z" }),
-    });
-    modelMap["model named Bz, with collection path D / E / F"] =
-      createMockModelResult({
+    metricMap["model named C, with collection path Z"] = createMockMetricResult(
+      {
+        name: "C",
+        collection: createMockCollection({ name: "Z" }),
+      },
+    );
+    metricMap["model named Bz, with collection path D / E / F"] =
+      createMockMetricResult({
         name: "Bz",
         collection: createMockCollection({
           name: "F",
@@ -101,20 +101,20 @@ describe("sortModels", () => {
           ],
         }),
       });
-    const mockSearchResults = Object.values(modelMap);
+    const mockSearchResults = Object.values(metricMap);
 
     it("can sort by collection path, ascending, and then does a secondary sort by name", () => {
       const sortingOptions = {
         sort_column: "collection",
         sort_direction: SortDirection.Asc,
       } as const;
-      const sorted = sortModelOrMetric(mockSearchResults, sortingOptions);
+      const sorted = sortMetrics(mockSearchResults, sortingOptions);
       expect(sorted).toEqual([
-        modelMap["model named B, with collection path D / E / F"],
-        modelMap["model named Bz, with collection path D / E / F"],
-        modelMap["model named A, with collection path X / Y / Z"],
-        modelMap["model named C, with collection path Y"],
-        modelMap["model named C, with collection path Z"],
+        metricMap["model named B, with collection path D / E / F"],
+        metricMap["model named Bz, with collection path D / E / F"],
+        metricMap["model named A, with collection path X / Y / Z"],
+        metricMap["model named C, with collection path Y"],
+        metricMap["model named C, with collection path Z"],
       ]);
     });
 
@@ -123,13 +123,13 @@ describe("sortModels", () => {
         sort_column: "collection",
         sort_direction: SortDirection.Desc,
       } as const;
-      const sorted = sortModelOrMetric(mockSearchResults, sortingOptions);
+      const sorted = sortMetrics(mockSearchResults, sortingOptions);
       expect(sorted).toEqual([
-        modelMap["model named C, with collection path Z"],
-        modelMap["model named C, with collection path Y"],
-        modelMap["model named A, with collection path X / Y / Z"],
-        modelMap["model named Bz, with collection path D / E / F"],
-        modelMap["model named B, with collection path D / E / F"],
+        metricMap["model named C, with collection path Z"],
+        metricMap["model named C, with collection path Y"],
+        metricMap["model named A, with collection path X / Y / Z"],
+        metricMap["model named Bz, with collection path D / E / F"],
+        metricMap["model named B, with collection path D / E / F"],
       ]);
     });
 
@@ -139,7 +139,7 @@ describe("sortModels", () => {
         sort_direction: SortDirection.Asc,
       } as const;
 
-      const addUmlauts = (model: ModelResult): ModelResult => ({
+      const addUmlauts = (model: MetricResult): MetricResult => ({
         ...model,
         name: model.name.replace(/^B$/g, "Bä"),
         collection: {
@@ -153,63 +153,45 @@ describe("sortModels", () => {
         },
       });
 
-      const swedishModelMap = {
+      const swedishmetricMap = {
         "model named A, with collection path Ä / Y / Z": addUmlauts(
-          modelMap["model named A, with collection path X / Y / Z"],
+          metricMap["model named A, with collection path X / Y / Z"],
         ),
         "model named Bä, with collection path D / E / F": addUmlauts(
-          modelMap["model named B, with collection path D / E / F"],
+          metricMap["model named B, with collection path D / E / F"],
         ),
         "model named Bz, with collection path D / E / F": addUmlauts(
-          modelMap["model named Bz, with collection path D / E / F"],
+          metricMap["model named Bz, with collection path D / E / F"],
         ),
         "model named C, with collection path Y": addUmlauts(
-          modelMap["model named C, with collection path Y"],
+          metricMap["model named C, with collection path Y"],
         ),
         "model named C, with collection path Z": addUmlauts(
-          modelMap["model named C, with collection path Z"],
+          metricMap["model named C, with collection path Z"],
         ),
       };
 
-      const swedishResults = Object.values(swedishModelMap);
+      const swedishResults = Object.values(swedishmetricMap);
 
       // When sorting in Swedish, z comes before ä
       const swedishLocaleCode = "sv";
-      const sorted = sortModelOrMetric(
+      const sorted = sortMetrics(
         swedishResults,
         sortingOptions,
         swedishLocaleCode,
       );
       expect("ä".localeCompare("z", "sv", { sensitivity: "base" })).toEqual(1);
       expect(sorted).toEqual([
-        swedishModelMap["model named Bz, with collection path D / E / F"], // Model Bz sorts before Bä
-        swedishModelMap["model named Bä, with collection path D / E / F"],
-        swedishModelMap["model named C, with collection path Y"],
-        swedishModelMap["model named C, with collection path Z"], // Collection Z sorts before Ä
-        swedishModelMap["model named A, with collection path Ä / Y / Z"],
+        swedishmetricMap["model named Bz, with collection path D / E / F"], // Model Bz sorts before Bä
+        swedishmetricMap["model named Bä, with collection path D / E / F"],
+        swedishmetricMap["model named C, with collection path Y"],
+        swedishmetricMap["model named C, with collection path Z"], // Collection Z sorts before Ä
+        swedishmetricMap["model named A, with collection path Ä / Y / Z"],
       ]);
     });
   });
 });
 
-describe("getMaxRecentModelCount", () => {
-  it("returns 8 for modelCount greater than 20", () => {
-    expect(getMaxRecentModelCount(21)).toBe(8);
-    expect(getMaxRecentModelCount(100)).toBe(8);
-  });
-
-  it("returns 4 for modelCount greater than 9 and less than or equal to 20", () => {
-    expect(getMaxRecentModelCount(10)).toBe(4);
-    expect(getMaxRecentModelCount(20)).toBe(4);
-  });
-
-  it("returns 0 for modelCount of 9 or less", () => {
-    expect(getMaxRecentModelCount(0)).toBe(0);
-    expect(getMaxRecentModelCount(5)).toBe(0);
-    expect(getMaxRecentModelCount(9)).toBe(0);
-  });
-});
-
 describe("isDatasetScalar", () => {
   it("should return true for a dataset with a single column and a single row", () => {
     const dataset = createMockDataset({
diff --git a/frontend/src/metabase/browse/components/BrowseModels.styled.tsx b/frontend/src/metabase/browse/models/BrowseModels.styled.tsx
similarity index 98%
rename from frontend/src/metabase/browse/components/BrowseModels.styled.tsx
rename to frontend/src/metabase/browse/models/BrowseModels.styled.tsx
index dda35826be06393c48cb57e594f1bf7fb2c25ad0..720e82f301fcaf8149d2312c46df72603d443520 100644
--- a/frontend/src/metabase/browse/components/BrowseModels.styled.tsx
+++ b/frontend/src/metabase/browse/models/BrowseModels.styled.tsx
@@ -7,7 +7,7 @@ import { Ellipsified } from "metabase/core/components/Ellipsified";
 import Link from "metabase/core/components/Link";
 import { Box, type ButtonProps, Collapse, Icon } from "metabase/ui";
 
-import { BrowseGrid } from "./BrowseContainer.styled";
+import { BrowseGrid } from "../components/BrowseContainer.styled";
 
 export const ModelCardLink = styled(Link)`
   margin: 0.5rem 0;
diff --git a/frontend/src/metabase/browse/models/BrowseModels.tsx b/frontend/src/metabase/browse/models/BrowseModels.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..afc510f1e4e6d03b490106f0d6448be8bf819945
--- /dev/null
+++ b/frontend/src/metabase/browse/models/BrowseModels.tsx
@@ -0,0 +1,209 @@
+import { useState } from "react";
+import { t } from "ttag";
+
+import NoResults from "assets/img/no_results.svg";
+import { skipToken, useListRecentsQuery } from "metabase/api";
+import { useFetchModels } from "metabase/common/hooks/use-fetch-models";
+import { DelayedLoadingAndErrorWrapper } from "metabase/components/LoadingAndErrorWrapper/DelayedLoadingAndErrorWrapper";
+import { useSelector } from "metabase/lib/redux";
+import {
+  PLUGIN_COLLECTIONS,
+  PLUGIN_CONTENT_VERIFICATION,
+} from "metabase/plugins";
+import { Box, Flex, Group, Icon, Stack, Title } from "metabase/ui";
+
+import {
+  BrowseContainer,
+  BrowseHeader,
+  BrowseMain,
+  BrowseSection,
+  CenteredEmptyState,
+} from "../components/BrowseContainer.styled";
+
+import { ModelExplanationBanner } from "./ModelExplanationBanner";
+import { ModelsTable } from "./ModelsTable";
+import { RecentModels } from "./RecentModels";
+import type { ModelFilterSettings, ModelResult } from "./types";
+import { getMaxRecentModelCount, isRecentModel } from "./utils";
+
+const {
+  contentVerificationEnabled,
+  ModelFilterControls,
+  getDefaultModelFilters,
+} = PLUGIN_CONTENT_VERIFICATION;
+
+export const BrowseModels = () => {
+  const [modelFilters, setModelFilters] = useModelFilterSettings();
+  const { isLoading, error, models, recentModels, hasVerifiedModels } =
+    useFilteredModels(modelFilters);
+
+  const isEmpty = !isLoading && models.length === 0;
+
+  return (
+    <BrowseContainer>
+      <BrowseHeader role="heading" data-testid="browse-models-header">
+        <BrowseSection>
+          <Flex
+            w="100%"
+            h="2.25rem"
+            direction="row"
+            justify="space-between"
+            align="center"
+          >
+            <Title order={1} color="text-dark">
+              <Group spacing="sm">
+                <Icon
+                  size={24}
+                  color="var(--mb-color-icon-primary)"
+                  name="model"
+                />
+                {t`Models`}
+              </Group>
+            </Title>
+            {hasVerifiedModels && (
+              <ModelFilterControls
+                modelFilters={modelFilters}
+                setModelFilters={setModelFilters}
+              />
+            )}
+          </Flex>
+        </BrowseSection>
+      </BrowseHeader>
+      <BrowseMain>
+        <BrowseSection>
+          <Stack mb="lg" spacing="md" w="100%">
+            {isEmpty ? (
+              <CenteredEmptyState
+                title={<Box mb=".5rem">{t`No models here yet`}</Box>}
+                message={
+                  <Box maw="24rem">{t`Models help curate data to make it easier to find answers to questions all in one place.`}</Box>
+                }
+                illustrationElement={
+                  <Box mb=".5rem">
+                    <img src={NoResults} />
+                  </Box>
+                }
+              />
+            ) : (
+              <>
+                <ModelExplanationBanner />
+                <DelayedLoadingAndErrorWrapper
+                  error={error}
+                  loading={isLoading}
+                  style={{ flex: 1 }}
+                  loader={<RecentModels skeleton />}
+                >
+                  <RecentModels models={recentModels} />
+                </DelayedLoadingAndErrorWrapper>
+                <DelayedLoadingAndErrorWrapper
+                  error={error}
+                  loading={isLoading}
+                  style={{ flex: 1 }}
+                  loader={<ModelsTable skeleton />}
+                >
+                  <ModelsTable models={models} />
+                </DelayedLoadingAndErrorWrapper>
+              </>
+            )}
+          </Stack>
+        </BrowseSection>
+      </BrowseMain>
+    </BrowseContainer>
+  );
+};
+
+function useModelFilterSettings() {
+  const defaultModelFilters = useSelector(getDefaultModelFilters);
+  return useState(defaultModelFilters);
+}
+
+function useHasVerifiedModels() {
+  const result = useFetchModels(
+    contentVerificationEnabled
+      ? {
+          filter_items_in_personal_collection: "exclude",
+          model_ancestors: false,
+          limit: 0,
+          verified: true,
+        }
+      : skipToken,
+  );
+
+  if (!contentVerificationEnabled) {
+    return {
+      isLoading: false,
+      error: null,
+      result: false,
+    };
+  }
+
+  const total = result.data?.total ?? 0;
+
+  return {
+    isLoading: result.isLoading,
+    error: result.error,
+    result: total > 0,
+  };
+}
+
+function useFilteredModels(modelFilters: ModelFilterSettings) {
+  const hasVerifiedModels = useHasVerifiedModels();
+
+  const filters = cleanModelFilters(modelFilters, hasVerifiedModels.result);
+
+  const modelsResult = useFetchModels(
+    hasVerifiedModels.isLoading || hasVerifiedModels.error
+      ? skipToken
+      : {
+          filter_items_in_personal_collection: "exclude",
+          model_ancestors: false,
+          ...filters,
+        },
+  );
+
+  const models = modelsResult.data?.data as ModelResult[] | undefined;
+
+  const recentsCap = getMaxRecentModelCount(models?.length ?? 0);
+
+  const recentModelsResult = useListRecentsQuery(undefined, {
+    refetchOnMountOrArgChange: true,
+    skip: recentsCap === 0,
+  });
+
+  const isLoading =
+    hasVerifiedModels.isLoading ||
+    modelsResult.isLoading ||
+    recentModelsResult.isLoading;
+
+  const error =
+    hasVerifiedModels.error || modelsResult.error || recentModelsResult.error;
+
+  return {
+    isLoading,
+    error,
+    hasVerifiedModels: hasVerifiedModels.result,
+    models: PLUGIN_COLLECTIONS.filterOutItemsFromInstanceAnalytics(
+      models ?? [],
+    ),
+
+    recentModels: (recentModelsResult.data ?? [])
+      .filter(isRecentModel)
+      .filter(
+        model => !filters.verified || model.moderated_status === "verified",
+      )
+      .slice(0, recentsCap),
+  };
+}
+
+function cleanModelFilters(
+  modelFilters: ModelFilterSettings,
+  hasVerifiedModels: boolean,
+) {
+  const filters = { ...modelFilters };
+  if (!hasVerifiedModels || !filters.verified) {
+    // we cannot pass false or undefined to the backend
+    // delete the key instead
+    delete filters.verified;
+  }
+  return filters;
+}
diff --git a/frontend/src/metabase/browse/components/BrowseModels.unit.spec.tsx b/frontend/src/metabase/browse/models/BrowseModels.unit.spec.tsx
similarity index 99%
rename from frontend/src/metabase/browse/components/BrowseModels.unit.spec.tsx
rename to frontend/src/metabase/browse/models/BrowseModels.unit.spec.tsx
index e05f459ff2e5147c0f6b411fd317ef5667de8f08..d5d8969d015ed376d839d3a6d4b2d4201d613d91 100644
--- a/frontend/src/metabase/browse/components/BrowseModels.unit.spec.tsx
+++ b/frontend/src/metabase/browse/models/BrowseModels.unit.spec.tsx
@@ -10,9 +10,8 @@ import {
 } from "metabase-types/api/mocks";
 import { createMockSetupState } from "metabase-types/store/mocks";
 
-import { createMockModelResult, createMockRecentModel } from "../test-utils";
-
 import { BrowseModels } from "./BrowseModels";
+import { createMockModelResult, createMockRecentModel } from "./test-utils";
 
 const defaultRootCollection = createMockCollection({
   id: "root",
diff --git a/frontend/src/metabase/browse/components/ModelExplanationBanner.tsx b/frontend/src/metabase/browse/models/ModelExplanationBanner.tsx
similarity index 100%
rename from frontend/src/metabase/browse/components/ModelExplanationBanner.tsx
rename to frontend/src/metabase/browse/models/ModelExplanationBanner.tsx
diff --git a/frontend/src/metabase/browse/components/ModelsTable.tsx b/frontend/src/metabase/browse/models/ModelsTable.tsx
similarity index 96%
rename from frontend/src/metabase/browse/components/ModelsTable.tsx
rename to frontend/src/metabase/browse/models/ModelsTable.tsx
index 815dd8619795274863ab907bac71b803fa17a9bf..8b4376eb5c7f2f4d92d1b211e72fc7726c06ffcb 100644
--- a/frontend/src/metabase/browse/components/ModelsTable.tsx
+++ b/frontend/src/metabase/browse/models/ModelsTable.tsx
@@ -24,18 +24,17 @@ import { FixedSizeIcon, Flex, Icon, Skeleton } from "metabase/ui";
 import { Repeat } from "metabase/ui/components/feedback/Skeleton/Repeat";
 import { SortDirection, type SortingOptions } from "metabase-types/api/sorting";
 
-import { trackModelClick } from "../analytics";
-import type { ModelResult } from "../types";
-import { getIcon } from "../utils";
-
 import {
   Cell,
   CollectionLink,
   CollectionTableCell,
   NameColumn,
   TableRow,
-} from "./BrowseTable.styled";
-import { getModelDescription, sortModelOrMetric } from "./utils";
+} from "../components/BrowseTable.styled";
+
+import { trackModelClick } from "./analytics";
+import type { ModelResult } from "./types";
+import { getIcon, getModelDescription, sortModels } from "./utils";
 
 export interface ModelsTableProps {
   models?: ModelResult[];
@@ -69,7 +68,7 @@ export const ModelsTable = ({
   );
 
   const locale = useLocale();
-  const sortedModels = sortModelOrMetric(models, sortingOptions, locale);
+  const sortedModels = sortModels(models, sortingOptions, locale);
 
   /** The name column has an explicitly set width. The remaining columns divide the remaining width. This is the percentage allocated to the collection column */
   const collectionWidth = 38.5;
diff --git a/frontend/src/metabase/browse/components/RecentModels.styled.tsx b/frontend/src/metabase/browse/models/RecentModels.styled.tsx
similarity index 100%
rename from frontend/src/metabase/browse/components/RecentModels.styled.tsx
rename to frontend/src/metabase/browse/models/RecentModels.styled.tsx
diff --git a/frontend/src/metabase/browse/components/RecentModels.tsx b/frontend/src/metabase/browse/models/RecentModels.tsx
similarity index 96%
rename from frontend/src/metabase/browse/components/RecentModels.tsx
rename to frontend/src/metabase/browse/models/RecentModels.tsx
index 66b750040c38d112f0bbb2856a4232e1954d98bf..c4aa34dd730b3218bb4e81c876a11ed914e8a78c 100644
--- a/frontend/src/metabase/browse/components/RecentModels.tsx
+++ b/frontend/src/metabase/browse/models/RecentModels.tsx
@@ -5,9 +5,8 @@ import { Box, Text } from "metabase/ui";
 import { Repeat } from "metabase/ui/components/feedback/Skeleton/Repeat";
 import type { RecentCollectionItem } from "metabase-types/api";
 
-import { trackModelClick } from "../analytics";
-
 import { RecentModelsGrid } from "./RecentModels.styled";
+import { trackModelClick } from "./analytics";
 
 export function RecentModels({
   models = [],
diff --git a/frontend/src/metabase/browse/models/analytics.ts b/frontend/src/metabase/browse/models/analytics.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f176dabfda3f97369627d3ea09e8b4696fafd501
--- /dev/null
+++ b/frontend/src/metabase/browse/models/analytics.ts
@@ -0,0 +1,8 @@
+import { trackSchemaEvent } from "metabase/lib/analytics";
+import type { CardId } from "metabase-types/api";
+
+export const trackModelClick = (modelId: CardId) =>
+  trackSchemaEvent("browse_data", {
+    event: "browse_data_model_clicked",
+    model_id: modelId,
+  });
diff --git a/frontend/src/metabase/browse/models/index.tsx b/frontend/src/metabase/browse/models/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..5ac8edc8ec027f65f3c0bfcfe615ac6576c40437
--- /dev/null
+++ b/frontend/src/metabase/browse/models/index.tsx
@@ -0,0 +1,7 @@
+export { BrowseModels } from "./BrowseModels";
+export type {
+  ModelFilterSettings,
+  ModelFilterControlsProps,
+  ModelResult,
+  RecentModel,
+} from "./types";
diff --git a/frontend/src/metabase/browse/test-utils.ts b/frontend/src/metabase/browse/models/test-utils.ts
similarity index 53%
rename from frontend/src/metabase/browse/test-utils.ts
rename to frontend/src/metabase/browse/models/test-utils.ts
index 38ee0947246e2cabf0ed92458fb8c0b0d4a5e1d3..c3b0e8c7635df326386a8be0673f193d902d16ee 100644
--- a/frontend/src/metabase/browse/test-utils.ts
+++ b/frontend/src/metabase/browse/models/test-utils.ts
@@ -4,12 +4,7 @@ import {
   createMockSearchResult,
 } from "metabase-types/api/mocks";
 
-import type {
-  MetricResult,
-  ModelResult,
-  RecentMetric,
-  RecentModel,
-} from "./types";
+import type { ModelResult, RecentModel } from "./types";
 
 export const createMockModelResult = (
   model: Partial<ModelResult> = {},
@@ -20,16 +15,3 @@ export const createMockRecentModel = (
   model: Partial<RecentCollectionItem>,
 ): RecentModel =>
   createMockRecentCollectionItem({ ...model, model: "dataset" }) as RecentModel;
-
-export const createMockMetricResult = (
-  metric: Partial<MetricResult> = {},
-): MetricResult =>
-  createMockSearchResult({ ...metric, model: "metric" }) as MetricResult;
-
-export const createMockRecentMetric = (
-  metric: Partial<RecentMetric>,
-): RecentMetric =>
-  createMockRecentCollectionItem({
-    ...metric,
-    model: "metric",
-  }) as RecentMetric;
diff --git a/frontend/src/metabase/browse/models/types.tsx b/frontend/src/metabase/browse/models/types.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..ac0b4db850aaf148d3489fbea0e9dc0d6fed4f71
--- /dev/null
+++ b/frontend/src/metabase/browse/models/types.tsx
@@ -0,0 +1,22 @@
+import type { RecentCollectionItem, SearchResult } from "metabase-types/api";
+
+/**
+ * Model retrieved through the search endpoint
+ */
+export type ModelResult = SearchResult<number, "dataset">;
+
+/**
+ * Model retrieved through the recent views endpoint
+ */
+export interface RecentModel extends RecentCollectionItem {
+  model: "dataset";
+}
+
+export type ModelFilterSettings = {
+  verified?: boolean;
+};
+
+export type ModelFilterControlsProps = {
+  modelFilters: ModelFilterSettings;
+  setModelFilters: (settings: ModelFilterSettings) => void;
+};
diff --git a/frontend/src/metabase/browse/models/utils.ts b/frontend/src/metabase/browse/models/utils.ts
new file mode 100644
index 0000000000000000000000000000000000000000..e35852bc23e26f318d053a612b4a168613463414
--- /dev/null
+++ b/frontend/src/metabase/browse/models/utils.ts
@@ -0,0 +1,98 @@
+import { t } from "ttag";
+import _ from "underscore";
+
+import { getCollectionPathAsString } from "metabase/collections/utils";
+import { entityForObject } from "metabase/lib/schema";
+import type { IconName } from "metabase/ui";
+import type { RecentItem, SearchResult } from "metabase-types/api";
+import { SortDirection, type SortingOptions } from "metabase-types/api/sorting";
+
+import type { ModelResult, RecentModel } from "./types";
+
+export const isModel = (item: SearchResult) => item.model === "dataset";
+
+export const isRecentModel = (item: RecentItem): item is RecentModel =>
+  item.model === "dataset";
+
+export const getModelDescription = (item: ModelResult) => {
+  if (item.collection && !item.description?.trim()) {
+    return t`A model`;
+  } else {
+    return item.description;
+  }
+};
+
+const getValueForSorting = (
+  model: ModelResult,
+  sort_column: keyof ModelResult,
+): string => {
+  if (sort_column === "collection") {
+    return getCollectionPathAsString(model.collection) ?? "";
+  } else {
+    return model[sort_column] ?? "";
+  }
+};
+
+export const isValidSortColumn = (
+  sort_column: string,
+): sort_column is keyof ModelResult => {
+  return ["name", "collection", "description"].includes(sort_column);
+};
+
+export const getSecondarySortColumn = (
+  sort_column: string,
+): keyof ModelResult => {
+  return sort_column === "name" ? "collection" : "name";
+};
+
+export function sortModels(
+  models: ModelResult[],
+  sortingOptions: SortingOptions,
+  localeCode: string = "en",
+) {
+  const { sort_column, sort_direction } = sortingOptions;
+
+  if (!isValidSortColumn(sort_column)) {
+    console.error("Invalid sort column", sort_column);
+    return models;
+  }
+
+  const compare = (a: string, b: string) =>
+    a.localeCompare(b, localeCode, { sensitivity: "base" });
+
+  return [...models].sort((modelA, modelB) => {
+    const a = getValueForSorting(modelA, sort_column);
+    const b = getValueForSorting(modelB, sort_column);
+
+    let result = compare(a, b);
+    if (result === 0) {
+      const sort_column2 = getSecondarySortColumn(sort_column);
+      const a2 = getValueForSorting(modelA, sort_column2);
+      const b2 = getValueForSorting(modelB, sort_column2);
+      result = compare(a2, b2);
+    }
+
+    return sort_direction === SortDirection.Asc ? result : -result;
+  });
+}
+
+/** Find the maximum number of recently viewed models to show.
+ * This is roughly proportional to the number of models the user
+ * has permission to see */
+export const getMaxRecentModelCount = (
+  /** How many models the user has permission to see */
+  modelCount: number,
+) => {
+  if (modelCount > 20) {
+    return 8;
+  }
+  if (modelCount > 9) {
+    return 4;
+  }
+  return 0;
+};
+
+export const getIcon = (item: unknown): { name: IconName; color: string } => {
+  const entity = entityForObject(item);
+  return entity?.objectSelectors?.getIcon?.(item) || { name: "folder" };
+};
diff --git a/frontend/src/metabase/browse/models/utils.unit.spec.tsx b/frontend/src/metabase/browse/models/utils.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a33bd9014f67475091d0c78a21a38e1184eed25f
--- /dev/null
+++ b/frontend/src/metabase/browse/models/utils.unit.spec.tsx
@@ -0,0 +1,200 @@
+import { createMockCollection } from "metabase-types/api/mocks";
+import { SortDirection } from "metabase-types/api/sorting";
+
+import { createMockModelResult } from "./test-utils";
+import type { ModelResult } from "./types";
+import { getMaxRecentModelCount, sortModels } from "./utils";
+
+describe("sortModels", () => {
+  let id = 0;
+  const modelMap: Record<string, ModelResult> = {
+    "model named A, with collection path X / Y / Z": createMockModelResult({
+      id: id++,
+      name: "A",
+      collection: createMockCollection({
+        name: "Z",
+        effective_ancestors: [
+          createMockCollection({ name: "X" }),
+          createMockCollection({ name: "Y" }),
+        ],
+      }),
+    }),
+    "model named C, with collection path Y": createMockModelResult({
+      id: id++,
+      name: "C",
+      collection: createMockCollection({ name: "Y" }),
+    }),
+    "model named B, with collection path D / E / F": createMockModelResult({
+      id: id++,
+      name: "B",
+      collection: createMockCollection({
+        name: "F",
+        effective_ancestors: [
+          createMockCollection({ name: "D" }),
+          createMockCollection({ name: "E" }),
+        ],
+      }),
+    }),
+  };
+  const mockSearchResults = Object.values(modelMap);
+
+  it("can sort by name in ascending order", () => {
+    const sortingOptions = {
+      sort_column: "name",
+      sort_direction: SortDirection.Asc,
+    } as const;
+    const sorted = sortModels(mockSearchResults, sortingOptions);
+    expect(sorted?.map(model => model.name)).toEqual(["A", "B", "C"]);
+  });
+
+  it("can sort by name in descending order", () => {
+    const sortingOptions = {
+      sort_column: "name",
+      sort_direction: SortDirection.Desc,
+    } as const;
+    const sorted = sortModels(mockSearchResults, sortingOptions);
+    expect(sorted?.map(model => model.name)).toEqual(["C", "B", "A"]);
+  });
+
+  it("can sort by collection path in ascending order", () => {
+    const sortingOptions = {
+      sort_column: "collection",
+      sort_direction: SortDirection.Asc,
+    } as const;
+    const sorted = sortModels(mockSearchResults, sortingOptions);
+    expect(sorted?.map(model => model.name)).toEqual(["B", "A", "C"]);
+  });
+
+  it("can sort by collection path in descending order", () => {
+    const sortingOptions = {
+      sort_column: "collection",
+      sort_direction: SortDirection.Desc,
+    } as const;
+    const sorted = sortModels(mockSearchResults, sortingOptions);
+    expect(sorted?.map(model => model.name)).toEqual(["C", "A", "B"]);
+  });
+
+  describe("secondary sort", () => {
+    modelMap["model named C, with collection path Z"] = createMockModelResult({
+      name: "C",
+      collection: createMockCollection({ name: "Z" }),
+    });
+    modelMap["model named Bz, with collection path D / E / F"] =
+      createMockModelResult({
+        name: "Bz",
+        collection: createMockCollection({
+          name: "F",
+          effective_ancestors: [
+            createMockCollection({ name: "D" }),
+            createMockCollection({ name: "E" }),
+          ],
+        }),
+      });
+    const mockSearchResults = Object.values(modelMap);
+
+    it("can sort by collection path, ascending, and then does a secondary sort by name", () => {
+      const sortingOptions = {
+        sort_column: "collection",
+        sort_direction: SortDirection.Asc,
+      } as const;
+      const sorted = sortModels(mockSearchResults, sortingOptions);
+      expect(sorted).toEqual([
+        modelMap["model named B, with collection path D / E / F"],
+        modelMap["model named Bz, with collection path D / E / F"],
+        modelMap["model named A, with collection path X / Y / Z"],
+        modelMap["model named C, with collection path Y"],
+        modelMap["model named C, with collection path Z"],
+      ]);
+    });
+
+    it("can sort by collection path, descending, and then does a secondary sort by name", () => {
+      const sortingOptions = {
+        sort_column: "collection",
+        sort_direction: SortDirection.Desc,
+      } as const;
+      const sorted = sortModels(mockSearchResults, sortingOptions);
+      expect(sorted).toEqual([
+        modelMap["model named C, with collection path Z"],
+        modelMap["model named C, with collection path Y"],
+        modelMap["model named A, with collection path X / Y / Z"],
+        modelMap["model named Bz, with collection path D / E / F"],
+        modelMap["model named B, with collection path D / E / F"],
+      ]);
+    });
+
+    it("can sort by collection path, ascending, and then does a secondary sort by name - with a localized sort order", () => {
+      const sortingOptions = {
+        sort_column: "collection",
+        sort_direction: SortDirection.Asc,
+      } as const;
+
+      const addUmlauts = (model: ModelResult): ModelResult => ({
+        ...model,
+        name: model.name.replace(/^B$/g, "Bä"),
+        collection: {
+          ...model.collection,
+          effective_ancestors: model.collection?.effective_ancestors?.map(
+            ancestor => ({
+              ...ancestor,
+              name: ancestor.name.replace("X", "Ä"),
+            }),
+          ),
+        },
+      });
+
+      const swedishModelMap = {
+        "model named A, with collection path Ä / Y / Z": addUmlauts(
+          modelMap["model named A, with collection path X / Y / Z"],
+        ),
+        "model named Bä, with collection path D / E / F": addUmlauts(
+          modelMap["model named B, with collection path D / E / F"],
+        ),
+        "model named Bz, with collection path D / E / F": addUmlauts(
+          modelMap["model named Bz, with collection path D / E / F"],
+        ),
+        "model named C, with collection path Y": addUmlauts(
+          modelMap["model named C, with collection path Y"],
+        ),
+        "model named C, with collection path Z": addUmlauts(
+          modelMap["model named C, with collection path Z"],
+        ),
+      };
+
+      const swedishResults = Object.values(swedishModelMap);
+
+      // When sorting in Swedish, z comes before ä
+      const swedishLocaleCode = "sv";
+      const sorted = sortModels(
+        swedishResults,
+        sortingOptions,
+        swedishLocaleCode,
+      );
+      expect("ä".localeCompare("z", "sv", { sensitivity: "base" })).toEqual(1);
+      expect(sorted).toEqual([
+        swedishModelMap["model named Bz, with collection path D / E / F"], // Model Bz sorts before Bä
+        swedishModelMap["model named Bä, with collection path D / E / F"],
+        swedishModelMap["model named C, with collection path Y"],
+        swedishModelMap["model named C, with collection path Z"], // Collection Z sorts before Ä
+        swedishModelMap["model named A, with collection path Ä / Y / Z"],
+      ]);
+    });
+  });
+});
+
+describe("getMaxRecentModelCount", () => {
+  it("returns 8 for modelCount greater than 20", () => {
+    expect(getMaxRecentModelCount(21)).toBe(8);
+    expect(getMaxRecentModelCount(100)).toBe(8);
+  });
+
+  it("returns 4 for modelCount greater than 9 and less than or equal to 20", () => {
+    expect(getMaxRecentModelCount(10)).toBe(4);
+    expect(getMaxRecentModelCount(20)).toBe(4);
+  });
+
+  it("returns 0 for modelCount of 9 or less", () => {
+    expect(getMaxRecentModelCount(0)).toBe(0);
+    expect(getMaxRecentModelCount(5)).toBe(0);
+    expect(getMaxRecentModelCount(9)).toBe(0);
+  });
+});
diff --git a/frontend/src/metabase/browse/components/BrowseSchemas.styled.tsx b/frontend/src/metabase/browse/schemas/BrowseSchemas.styled.tsx
similarity index 100%
rename from frontend/src/metabase/browse/components/BrowseSchemas.styled.tsx
rename to frontend/src/metabase/browse/schemas/BrowseSchemas.styled.tsx
diff --git a/frontend/src/metabase/browse/components/BrowseSchemas.tsx b/frontend/src/metabase/browse/schemas/BrowseSchemas.tsx
similarity index 90%
rename from frontend/src/metabase/browse/components/BrowseSchemas.tsx
rename to frontend/src/metabase/browse/schemas/BrowseSchemas.tsx
index b59c8cc706c87387f5c66df7918f85b557060bd6..1c9922ffec7042c180047c964516cc0d547302e4 100644
--- a/frontend/src/metabase/browse/components/BrowseSchemas.tsx
+++ b/frontend/src/metabase/browse/schemas/BrowseSchemas.tsx
@@ -16,12 +16,13 @@ import {
   BrowseContainer,
   BrowseMain,
   BrowseSection,
-} from "./BrowseContainer.styled";
-import { BrowseDataHeader } from "./BrowseDataHeader";
-import { BrowseHeaderContent } from "./BrowseHeader.styled";
+} from "../components/BrowseContainer.styled";
+import { BrowseDataHeader } from "../components/BrowseDataHeader";
+import { BrowseHeaderContent } from "../components/BrowseHeader.styled";
+
 import { SchemaGridItem, SchemaLink } from "./BrowseSchemas.styled";
 
-const BrowseSchemas = ({
+const BrowseSchemasContainer = ({
   schemas,
   params,
 }: {
@@ -90,9 +91,8 @@ const BrowseSchemas = ({
   );
 };
 
-// eslint-disable-next-line import/no-default-export -- deprecated usage
-export default Schema.loadList({
+export const BrowseSchemas = Schema.loadList({
   query: (state: any, { params: { slug } }: { params: { slug: string } }) => ({
     dbId: Urls.extractEntityId(slug),
   }),
-})(BrowseSchemas);
+})(BrowseSchemasContainer);
diff --git a/frontend/src/metabase/browse/schemas/index.tsx b/frontend/src/metabase/browse/schemas/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..36acba3f3707bad8613c4dc9beaed176e8d76db8
--- /dev/null
+++ b/frontend/src/metabase/browse/schemas/index.tsx
@@ -0,0 +1 @@
+export { BrowseSchemas } from "./BrowseSchemas";
diff --git a/frontend/src/metabase/browse/components/BrowseTables.tsx b/frontend/src/metabase/browse/tables/BrowseTables.tsx
similarity index 81%
rename from frontend/src/metabase/browse/components/BrowseTables.tsx
rename to frontend/src/metabase/browse/tables/BrowseTables.tsx
index 9007610cfe9664b7a824117684d4a0bfbddc6c10..409fe3104f0748c4cae9a091fd969e539441be04 100644
--- a/frontend/src/metabase/browse/components/BrowseTables.tsx
+++ b/frontend/src/metabase/browse/tables/BrowseTables.tsx
@@ -1,11 +1,10 @@
-import TableBrowser from "../containers/TableBrowser";
-
 import {
   BrowseContainer,
   BrowseMain,
   BrowseSection,
-} from "./BrowseContainer.styled";
-import { BrowseDataHeader } from "./BrowseDataHeader";
+} from "../components/BrowseContainer.styled";
+import { BrowseDataHeader } from "../components/BrowseDataHeader";
+import TableBrowser from "../containers/TableBrowser";
 
 export const BrowseTables = ({
   params: { dbId, schemaName },
diff --git a/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.jsx b/frontend/src/metabase/browse/tables/TableBrowser/TableBrowser.jsx
similarity index 97%
rename from frontend/src/metabase/browse/components/TableBrowser/TableBrowser.jsx
rename to frontend/src/metabase/browse/tables/TableBrowser/TableBrowser.jsx
index 468c9515960df0a248db5ef7f92e2ed7facb1103..60358f0368585130c36d0a1df5b33fe76d85f13b 100644
--- a/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.jsx
+++ b/frontend/src/metabase/browse/tables/TableBrowser/TableBrowser.jsx
@@ -14,8 +14,8 @@ import {
   isVirtualCardId,
 } from "metabase-lib/v1/metadata/utils/saved-questions";
 
-import { trackTableClick } from "../../analytics";
-import { BrowseHeaderContent } from "../BrowseHeader.styled";
+import { BrowseHeaderContent } from "../../components/BrowseHeader.styled";
+import { trackTableClick } from "../analytics";
 
 import {
   TableActionLink,
diff --git a/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.styled.tsx b/frontend/src/metabase/browse/tables/TableBrowser/TableBrowser.styled.tsx
similarity index 100%
rename from frontend/src/metabase/browse/components/TableBrowser/TableBrowser.styled.tsx
rename to frontend/src/metabase/browse/tables/TableBrowser/TableBrowser.styled.tsx
diff --git a/frontend/src/metabase/browse/components/TableBrowser/TableBrowser.unit.spec.js b/frontend/src/metabase/browse/tables/TableBrowser/TableBrowser.unit.spec.js
similarity index 100%
rename from frontend/src/metabase/browse/components/TableBrowser/TableBrowser.unit.spec.js
rename to frontend/src/metabase/browse/tables/TableBrowser/TableBrowser.unit.spec.js
diff --git a/frontend/src/metabase/browse/components/TableBrowser/index.js b/frontend/src/metabase/browse/tables/TableBrowser/index.js
similarity index 100%
rename from frontend/src/metabase/browse/components/TableBrowser/index.js
rename to frontend/src/metabase/browse/tables/TableBrowser/index.js
diff --git a/frontend/src/metabase/browse/analytics.ts b/frontend/src/metabase/browse/tables/analytics.ts
similarity index 50%
rename from frontend/src/metabase/browse/analytics.ts
rename to frontend/src/metabase/browse/tables/analytics.ts
index ffa3dcd1c64a1f2733a8588d998f23ace01ca83d..0e2fb444b7f90fa81a36dd04303f550c8af6a836 100644
--- a/frontend/src/metabase/browse/analytics.ts
+++ b/frontend/src/metabase/browse/tables/analytics.ts
@@ -1,11 +1,5 @@
 import { trackSchemaEvent } from "metabase/lib/analytics";
-import type { CardId, ConcreteTableId } from "metabase-types/api";
-
-export const trackModelClick = (modelId: CardId) =>
-  trackSchemaEvent("browse_data", {
-    event: "browse_data_model_clicked",
-    model_id: modelId,
-  });
+import type { ConcreteTableId } from "metabase-types/api";
 
 export const trackTableClick = (tableId: ConcreteTableId) =>
   trackSchemaEvent("browse_data", {
diff --git a/frontend/src/metabase/browse/tables/index.tsx b/frontend/src/metabase/browse/tables/index.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..0d1921cbd3703f5c7f40a1e02c008b3f4bd7b389
--- /dev/null
+++ b/frontend/src/metabase/browse/tables/index.tsx
@@ -0,0 +1 @@
+export { BrowseTables } from "./BrowseTables";
diff --git a/frontend/src/metabase/browse/types.tsx b/frontend/src/metabase/browse/types.tsx
deleted file mode 100644
index 7ecc3a879b6ab0dc61742e997a7a8746788412ee..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/browse/types.tsx
+++ /dev/null
@@ -1,28 +0,0 @@
-import type {
-  RecentCollectionItem,
-  RecentItem,
-  SearchResult,
-} from "metabase-types/api";
-
-/** Model retrieved through the search endpoint */
-export type ModelResult = SearchResult<number, "dataset">;
-
-/** Model retrieved through the recent views endpoint */
-export interface RecentModel extends RecentCollectionItem {
-  model: "dataset";
-}
-
-export const isRecentModel = (item: RecentItem): item is RecentModel =>
-  item.model === "dataset";
-
-/** A model retrieved through either endpoint.
- * This type is needed so that our filtering functions can
- * filter arrays of models retrieved from either endpoint. */
-export type FilterableModel = ModelResult | RecentModel;
-
-/** Metric retrieved through the search endpoint */
-export type MetricResult = SearchResult<number, "metric">;
-
-export interface RecentMetric extends RecentCollectionItem {
-  model: "metric";
-}
diff --git a/frontend/src/metabase/browse/utils.ts b/frontend/src/metabase/browse/utils.ts
deleted file mode 100644
index 4d0f22bf4100ba3d52fd3061a4e50a5e8e81e2d2..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/browse/utils.ts
+++ /dev/null
@@ -1,73 +0,0 @@
-import type { Dispatch, SetStateAction } from "react";
-import { t } from "ttag";
-import _ from "underscore";
-
-import {
-  canonicalCollectionId,
-  coerceCollectionId,
-  isRootCollection,
-} from "metabase/collections/utils";
-import { entityForObject } from "metabase/lib/schema";
-import type { IconName } from "metabase/ui";
-import type { CollectionEssentials } from "metabase-types/api";
-
-import type { FilterableModel } from "./types";
-
-export const getCollectionName = (collection: CollectionEssentials) => {
-  if (isRootCollection(collection)) {
-    return t`Our analytics`;
-  }
-  return collection?.name || t`Untitled collection`;
-};
-
-/** The root collection's id might be null or 'root' in different contexts.
- * Use 'root' instead of null, for the sake of sorting */
-export const getCollectionIdForSorting = (collection: CollectionEssentials) => {
-  return coerceCollectionId(canonicalCollectionId(collection.id));
-};
-
-export type AvailableModelFilters = Record<
-  string,
-  {
-    predicate: (value: FilterableModel) => boolean;
-    activeByDefault: boolean;
-  }
->;
-
-export type ModelFilterControlsProps = {
-  actualModelFilters: ActualModelFilters;
-  setActualModelFilters: Dispatch<SetStateAction<ActualModelFilters>>;
-};
-
-export type MetricFilterSettings = {
-  verified?: boolean;
-};
-
-export type MetricFilterControlsProps = {
-  metricFilters: MetricFilterSettings;
-  setMetricFilters: (settings: MetricFilterSettings) => void;
-};
-
-/** Mapping of filter names to true if the filter is active
- * or false if it is inactive */
-export type ActualModelFilters = Record<string, boolean>;
-
-export const filterModels = <T extends FilterableModel>(
-  unfilteredModels: T[] | undefined,
-  actualModelFilters: ActualModelFilters,
-  availableModelFilters: AvailableModelFilters,
-): T[] => {
-  return _.reduce(
-    actualModelFilters,
-    (acc, shouldFilterBeActive, filterName) =>
-      shouldFilterBeActive
-        ? acc.filter(availableModelFilters[filterName].predicate)
-        : acc,
-    unfilteredModels || [],
-  );
-};
-
-export const getIcon = (item: unknown): { name: IconName; color: string } => {
-  const entity = entityForObject(item);
-  return entity?.objectSelectors?.getIcon?.(item) || { name: "folder" };
-};
diff --git a/frontend/src/metabase/browse/utils.unit.spec.ts b/frontend/src/metabase/browse/utils.unit.spec.ts
deleted file mode 100644
index 97e058c0684dc1680411f939ed3318bedd471e3d..0000000000000000000000000000000000000000
--- a/frontend/src/metabase/browse/utils.unit.spec.ts
+++ /dev/null
@@ -1,238 +0,0 @@
-import { defaultRootCollection } from "metabase/admin/permissions/pages/CollectionPermissionsPage/tests/setup";
-import type { SearchResult } from "metabase-types/api";
-import { createMockCollection } from "metabase-types/api/mocks";
-
-import { createMockModelResult } from "./test-utils";
-import type { ModelResult } from "./types";
-import type { ActualModelFilters, AvailableModelFilters } from "./utils";
-import { filterModels } from "./utils";
-
-const collectionAlpha = createMockCollection({ id: 0, name: "Alpha" });
-const collectionBeta = createMockCollection({ id: 1, name: "Beta" });
-const collectionCharlie = createMockCollection({ id: 2, name: "Charlie" });
-const collectionDelta = createMockCollection({ id: 3, name: "Delta" });
-const collectionZulu = createMockCollection({ id: 4, name: "Zulu" });
-const collectionAngstrom = createMockCollection({ id: 5, name: "Ångström" });
-const collectionOzgur = createMockCollection({ id: 6, name: "Özgür" });
-
-const mockModels: ModelResult[] = [
-  {
-    id: 0,
-    name: "Model 0",
-    collection: collectionAlpha,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-12-15T11:59:59.000Z",
-  },
-  {
-    id: 1,
-    name: "Model 1",
-    collection: collectionAlpha,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-12-15T11:59:30.000Z",
-  },
-  {
-    id: 2,
-    name: "Model 2",
-    collection: collectionAlpha,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-12-15T11:59:00.000Z",
-  },
-  {
-    id: 3,
-    name: "Model 3",
-    collection: collectionBeta,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-12-15T11:50:00.000Z",
-  },
-  {
-    id: 4,
-    name: "Model 4",
-    collection: collectionBeta,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-12-15T11:00:00.000Z",
-  },
-  {
-    id: 5,
-    name: "Model 5",
-    collection: collectionBeta,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-12-14T22:00:00.000Z",
-  },
-  {
-    id: 6,
-    name: "Model 6",
-    collection: collectionCharlie,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-12-14T12:00:00.000Z",
-  },
-  {
-    id: 7,
-    name: "Model 7",
-    collection: collectionCharlie,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-12-10T12:00:00.000Z",
-  },
-  {
-    id: 8,
-    name: "Model 8",
-    collection: collectionCharlie,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-11-15T12:00:00.000Z",
-  },
-  {
-    id: 9,
-    name: "Model 9",
-    collection: collectionDelta,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2024-02-15T12:00:00.000Z",
-  },
-  {
-    id: 10,
-    name: "Model 10",
-    collection: collectionDelta,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2023-12-15T12:00:00.000Z",
-  },
-  {
-    id: 11,
-    name: "Model 11",
-    collection: collectionDelta,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2020-01-01T00:00:00.000Z",
-  },
-  {
-    id: 12,
-    name: "Model 12",
-    collection: collectionZulu,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 13,
-    name: "Model 13",
-    collection: collectionZulu,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 14,
-    name: "Model 14",
-    collection: collectionZulu,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 15,
-    name: "Model 15",
-    collection: collectionAngstrom,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 16,
-    name: "Model 16",
-    collection: collectionAngstrom,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 17,
-    name: "Model 17",
-    collection: collectionAngstrom,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 18,
-    name: "Model 18",
-    collection: collectionOzgur,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 19,
-    name: "Model 19",
-    collection: collectionOzgur,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 20,
-    name: "Model 20",
-    collection: collectionOzgur,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 21,
-    name: "Model 20",
-    collection: defaultRootCollection,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-  {
-    id: 22,
-    name: "Model 21",
-    collection: defaultRootCollection,
-    last_editor_common_name: "Bobby",
-    last_edited_at: "2000-01-01T00:00:00.000Z",
-  },
-].map(model => createMockModelResult(model));
-
-describe("Browse utils", () => {
-  const diverseModels = mockModels.map((model, index) => ({
-    ...model,
-    name: index % 2 === 0 ? `red ${index}` : `blue ${index}`,
-    moderated_status: index % 3 === 0 ? `good ${index}` : `bad ${index}`,
-  }));
-  const availableModelFilters: AvailableModelFilters = {
-    onlyRed: {
-      predicate: model => model.name.startsWith("red"),
-      activeByDefault: false,
-    },
-    onlyGood: {
-      predicate: model => Boolean(model.moderated_status?.startsWith("good")),
-      activeByDefault: false,
-    },
-    onlyBig: {
-      predicate: model => Boolean(model.description?.startsWith("big")),
-      activeByDefault: true,
-    },
-  };
-
-  it("include a function that filters models, based on the object provided", () => {
-    const onlyRedAndGood: ActualModelFilters = {
-      onlyRed: true,
-      onlyGood: true,
-      onlyBig: false,
-    };
-    const onlyRedAndGoodModels = filterModels(
-      diverseModels,
-      onlyRedAndGood,
-      availableModelFilters,
-    );
-    const everySixthModel = diverseModels.reduce<SearchResult[]>(
-      (acc, model, index) => {
-        return index % 6 === 0 ? [...acc, model] : acc;
-      },
-      [],
-    );
-    // Since every other model is red and every third model is good,
-    // we expect every sixth model to be both red and good
-    expect(onlyRedAndGoodModels).toEqual(everySixthModel);
-  });
-
-  it("filterModels does not filter out models if no filters are active", () => {
-    const noActiveFilters: ActualModelFilters = {
-      onlyRed: false,
-      onlyGood: false,
-      onlyBig: false,
-    };
-    const filteredModels = filterModels(
-      diverseModels,
-      noActiveFilters,
-      availableModelFilters,
-    );
-    expect(filteredModels).toEqual(diverseModels);
-  });
-});
diff --git a/frontend/src/metabase/common/hooks/use-fetch-models.tsx b/frontend/src/metabase/common/hooks/use-fetch-models.tsx
index 3a52f8feeef1f0b8d6b778a82eb20178dc7bcd36..931e4d9ca83a0c70b20cb97249df9ecb968a5617 100644
--- a/frontend/src/metabase/common/hooks/use-fetch-models.tsx
+++ b/frontend/src/metabase/common/hooks/use-fetch-models.tsx
@@ -1,12 +1,18 @@
-import { useSearchQuery } from "metabase/api";
+import { skipToken, useSearchQuery } from "metabase/api";
 import type { SearchRequest } from "metabase-types/api";
 
-export const useFetchModels = (req: Partial<SearchRequest> = {}) => {
-  const modelsResult = useSearchQuery({
-    models: ["dataset"], // 'model' in the sense of 'type of thing'
-    filter_items_in_personal_collection: "exclude",
-    model_ancestors: false,
-    ...req,
-  });
+export const useFetchModels = (
+  req: Partial<SearchRequest> | typeof skipToken = {},
+) => {
+  const modelsResult = useSearchQuery(
+    req === skipToken
+      ? req
+      : {
+          models: ["dataset"], // 'model' in the sense of 'type of thing'
+          filter_items_in_personal_collection: "exclude",
+          model_ancestors: false,
+          ...req,
+        },
+  );
   return modelsResult;
 };
diff --git a/frontend/src/metabase/nav/containers/MainNavbar/MainNavbar.unit.spec.tsx b/frontend/src/metabase/nav/containers/MainNavbar/MainNavbar.unit.spec.tsx
index cec4a46cbf02b8bbd0d71537efffa055df6fb12a..65ae305a394ce75303b4f4533e84f7332c6f0337 100644
--- a/frontend/src/metabase/nav/containers/MainNavbar/MainNavbar.unit.spec.tsx
+++ b/frontend/src/metabase/nav/containers/MainNavbar/MainNavbar.unit.spec.tsx
@@ -15,8 +15,8 @@ import {
   waitForLoaderToBeRemoved,
   within,
 } from "__support__/ui";
-import { createMockModelResult } from "metabase/browse/test-utils";
-import type { ModelResult } from "metabase/browse/types";
+import type { ModelResult } from "metabase/browse/models";
+import { createMockModelResult } from "metabase/browse/models/test-utils";
 import { ROOT_COLLECTION } from "metabase/entities/collections";
 import * as Urls from "metabase/lib/urls";
 import type { Card, Dashboard, DashboardId, User } from "metabase-types/api";
diff --git a/frontend/src/metabase/plugins/index.ts b/frontend/src/metabase/plugins/index.ts
index f73face54ac2b97823d6de8eea27581aae700249..63a8579decebf1bd16e71127f91573e7b8b225de 100644
--- a/frontend/src/metabase/plugins/index.ts
+++ b/frontend/src/metabase/plugins/index.ts
@@ -25,12 +25,13 @@ import {
 } from "metabase/admin/permissions/types";
 import type { ADMIN_SETTINGS_SECTIONS } from "metabase/admin/settings/selectors";
 import type {
-  ActualModelFilters,
-  AvailableModelFilters,
   MetricFilterControlsProps,
   MetricFilterSettings,
+} from "metabase/browse/metrics";
+import type {
   ModelFilterControlsProps,
-} from "metabase/browse/utils";
+  ModelFilterSettings,
+} from "metabase/browse/models";
 import { getIconBase } from "metabase/lib/icon";
 import PluginPlaceholder from "metabase/plugins/components/PluginPlaceholder";
 import type { SearchFilterComponent } from "metabase/search/types";
@@ -54,7 +55,6 @@ import type {
   GroupsPermissions,
   ModelCacheRefreshStatus,
   Revision,
-  SearchResult,
   User,
   UserListResult,
 } from "metabase-types/api";
@@ -506,21 +506,18 @@ export const PLUGIN_EMBEDDING = {
 };
 
 export const PLUGIN_CONTENT_VERIFICATION = {
+  contentVerificationEnabled: false,
   VerifiedFilter: {} as SearchFilterComponent<"verified">,
-  availableModelFilters: {} as AvailableModelFilters,
-  ModelFilterControls: (() => null) as ComponentType<ModelFilterControlsProps>,
-  sortModelsByVerification: (_a: SearchResult, _b: SearchResult) => 0,
   sortCollectionsByVerification: (
     _a: CollectionEssentials,
     _b: CollectionEssentials,
   ) => 0,
-  useModelFilterSettings: () =>
-    [{}, _.noop] as [
-      ActualModelFilters,
-      Dispatch<SetStateAction<ActualModelFilters>>,
-    ],
 
-  contentVerificationEnabled: false,
+  ModelFilterControls: (_props: ModelFilterControlsProps) => null,
+  getDefaultModelFilters: (_state: State): ModelFilterSettings => ({
+    verified: false,
+  }),
+
   getDefaultMetricFilters: (_state: State): MetricFilterSettings => ({
     verified: false,
   }),
diff --git a/frontend/src/metabase/querying/notebook/components/Notebook/Notebook.unit.spec.tsx b/frontend/src/metabase/querying/notebook/components/Notebook/Notebook.unit.spec.tsx
index e0c55705ddb1e4c2344fdc66a11ff5fc2e4f9a62..66b2135c7bb11b6111cc1fb32dcb18ff84b531d1 100644
--- a/frontend/src/metabase/querying/notebook/components/Notebook/Notebook.unit.spec.tsx
+++ b/frontend/src/metabase/querying/notebook/components/Notebook/Notebook.unit.spec.tsx
@@ -16,13 +16,16 @@ import {
   waitForLoaderToBeRemoved,
   within,
 } from "__support__/ui";
+import type { RecentMetric } from "metabase/browse/metrics";
 import {
   createMockMetricResult,
-  createMockModelResult,
   createMockRecentMetric,
+} from "metabase/browse/metrics/test-utils";
+import type { RecentModel } from "metabase/browse/models";
+import {
+  createMockModelResult,
   createMockRecentModel,
-} from "metabase/browse/test-utils";
-import type { RecentMetric, RecentModel } from "metabase/browse/types";
+} from "metabase/browse/models/test-utils";
 import type { DataPickerValue } from "metabase/common/components/DataPicker";
 import { checkNotNull } from "metabase/lib/types";
 import type { IconName } from "metabase/ui";
diff --git a/frontend/src/metabase/routes.jsx b/frontend/src/metabase/routes.jsx
index 383d6822af8be6422c697cbb5e9f7ddfa0c8c824..0f133b7f557a6306a919948229cb14e5a5231fc1 100644
--- a/frontend/src/metabase/routes.jsx
+++ b/frontend/src/metabase/routes.jsx
@@ -9,6 +9,13 @@ import { ForgotPassword } from "metabase/auth/components/ForgotPassword";
 import { Login } from "metabase/auth/components/Login";
 import { Logout } from "metabase/auth/components/Logout";
 import { ResetPassword } from "metabase/auth/components/ResetPassword";
+import {
+  BrowseDatabases,
+  BrowseMetrics,
+  BrowseModels,
+  BrowseSchemas,
+  BrowseTables,
+} from "metabase/browse";
 import CollectionLanding from "metabase/collections/components/CollectionLanding";
 import { MoveCollectionModal } from "metabase/collections/components/MoveCollectionModal";
 import { TrashCollectionLanding } from "metabase/collections/components/TrashCollectionLanding";
@@ -50,11 +57,6 @@ import SearchApp from "metabase/search/containers/SearchApp";
 import { Setup } from "metabase/setup/components/Setup";
 import getCollectionTimelineRoutes from "metabase/timelines/collections/routes";
 
-import { BrowseDatabases } from "./browse/components/BrowseDatabases";
-import { BrowseMetrics } from "./browse/components/BrowseMetrics";
-import { BrowseModels } from "./browse/components/BrowseModels";
-import BrowseSchemas from "./browse/components/BrowseSchemas";
-import { BrowseTables } from "./browse/components/BrowseTables";
 import {
   CanAccessMetabot,
   CanAccessSettings,