diff --git a/enterprise/README.md b/enterprise/README.md
index 6295a227d0ce3919c37b2277e082b77bc2dd71e1..c34a7b2bf2d6f1b2fb5e4a1eb8a62dffa9143aec 100644
--- a/enterprise/README.md
+++ b/enterprise/README.md
@@ -17,6 +17,8 @@ Unless otherwise noted, all files Copyright © 2021 Metabase, Inc.
 MB_EDITION=ee yarn build-hot
 ```
 
+Clear the Webpack cache using `yarn remove-webpack-cache` if you previously ran OSS edition in dev mode to avoid unexpected application behavior.
+
 ### Back-end
 
 You need to add the `:ee` alias to the Clojure CLI command to run Metabase Enterprise Edition.
diff --git a/enterprise/frontend/src/metabase-enterprise/license/actions.ts b/enterprise/frontend/src/metabase-enterprise/license/actions.ts
new file mode 100644
index 0000000000000000000000000000000000000000..5dedb76ec597e3b509445ff07168934a479029e1
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/license/actions.ts
@@ -0,0 +1,16 @@
+import { t } from "ttag";
+import { createThunkAction } from "metabase/lib/redux";
+import { addUndo } from "metabase/redux/undo";
+
+export const SHOW_LICENSE_ACCEPTED_TOAST =
+  "metabase-enterprise/license/SHOW_LICENSE_ACCEPTED_TOAST";
+export const showLicenseAcceptedToast = createThunkAction(
+  SHOW_LICENSE_ACCEPTED_TOAST,
+  () => (dispatch: any) => {
+    dispatch(
+      addUndo({
+        message: t`Your license is active!`,
+      }),
+    );
+  },
+);
diff --git a/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/LicenseAndBillingSettings.tsx b/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/LicenseAndBillingSettings.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..e8f8e452cf3bb3038abc226036f96a26c145e777
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/LicenseAndBillingSettings.tsx
@@ -0,0 +1,124 @@
+import React from "react";
+import { t, jt } from "ttag";
+import { connect } from "react-redux";
+import moment from "moment";
+import { showLicenseAcceptedToast } from "metabase-enterprise/license/actions";
+import {
+  TokenStatus,
+  useLicense,
+} from "metabase/admin/settings/hooks/use-license";
+import {
+  LoaderContainer,
+  SectionDescription,
+  SectionHeader,
+  SettingsLicenseContainer,
+} from "metabase/admin/settings/components/SettingsLicense";
+import ExternalLink from "metabase/components/ExternalLink";
+import MetabaseSettings from "metabase/lib/settings";
+import LoadingSpinner from "metabase/components/LoadingSpinner";
+import { LicenseInput } from "metabase/admin/settings/components/LicenseInput";
+
+const getDescription = (tokenStatus?: TokenStatus, hasToken?: boolean) => {
+  if (!hasToken) {
+    return t`Bought a license to unlock advanced functionality? Please enter it below.`;
+  }
+
+  if (!tokenStatus || !tokenStatus.isValid) {
+    return (
+      <>
+        {jt`Your license isn’t valid anymore. If you have a new license, please
+        enter it below, otherwise please contact ${(
+          <ExternalLink href="mailto:support@metabase.com">
+            support@metabase.com
+          </ExternalLink>
+        )}`}
+      </>
+    );
+  }
+
+  const daysRemaining = moment(tokenStatus.validUntil).diff(moment(), "days");
+
+  if (tokenStatus.isValid && tokenStatus.isTrial) {
+    return t`Your trial ends in ${daysRemaining} days. If you already have a license, please enter it below.`;
+  }
+
+  const validUntil = moment(tokenStatus.validUntil).format("MMM D, YYYY");
+  return t`Your license is active until ${validUntil}! Hope you’re enjoying it.`;
+};
+
+interface LicenseAndBillingSettingsProps {
+  showLicenseAcceptedToast: () => void;
+}
+
+const LicenseAndBillingSettings = ({
+  showLicenseAcceptedToast,
+}: LicenseAndBillingSettingsProps) => {
+  const { isLoading, error, tokenStatus, updateToken, isUpdating } = useLicense(
+    showLicenseAcceptedToast,
+  );
+
+  if (isLoading) {
+    return (
+      <SettingsLicenseContainer>
+        <LoaderContainer>
+          <LoadingSpinner />
+        </LoaderContainer>
+      </SettingsLicenseContainer>
+    );
+  }
+
+  const isStoreManagedBilling = MetabaseSettings.isStoreManaged();
+  const token = MetabaseSettings.token();
+
+  const isInvalid = !!error || (tokenStatus != null && !tokenStatus.isValid);
+  const description = getDescription(tokenStatus, !!token);
+
+  return (
+    <SettingsLicenseContainer data-testid="license-and-billing-content">
+      <>
+        <SectionHeader>{t`Billing`}</SectionHeader>
+
+        {isStoreManagedBilling && (
+          <>
+            <SectionDescription>
+              {t`Manage your Cloud account, including billing preferences, in your Metabase Store account.`}
+            </SectionDescription>
+
+            <ExternalLink
+              href={MetabaseSettings.storeUrl()}
+              className="Button Button--primary"
+            >
+              {t`Go to the Metabase Store`}
+            </ExternalLink>
+          </>
+        )}
+
+        {!isStoreManagedBilling && (
+          <SectionDescription>
+            {jt`To manage your billing preferences, please email ${(
+              <ExternalLink href="mailto:billing@metabase.com">
+                billing@metabase.com
+              </ExternalLink>
+            )}`}
+          </SectionDescription>
+        )}
+      </>
+
+      <SectionHeader>{t`License`}</SectionHeader>
+
+      <SectionDescription>{description}</SectionDescription>
+
+      <LicenseInput
+        invalid={isInvalid}
+        loading={isUpdating}
+        error={error}
+        token={token}
+        onUpdate={updateToken}
+      />
+    </SettingsLicenseContainer>
+  );
+};
+
+export default connect(null, { showLicenseAcceptedToast })(
+  LicenseAndBillingSettings,
+);
diff --git a/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/LicenseAndBillingSettings.unit.spec.tsx b/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/LicenseAndBillingSettings.unit.spec.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..178522b5d025e3bd2cfb6a36a8d2f9a00eac8fc7
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/LicenseAndBillingSettings.unit.spec.tsx
@@ -0,0 +1,179 @@
+import { act, fireEvent, screen } from "@testing-library/react";
+import React from "react";
+import xhrMock from "xhr-mock";
+import { renderWithProviders } from "__support__/ui";
+import LicenseAndBillingSettings from ".";
+import MetabaseSettings from "metabase/lib/settings";
+
+const mockSettings = (
+  isStoreManaged = true,
+  premiumEmbeddingToken?: string,
+) => {
+  const original = MetabaseSettings.get.bind(MetabaseSettings);
+  const spy = jest.spyOn(MetabaseSettings, "get");
+  spy.mockImplementation(key => {
+    if (key === "premium-embedding-token") {
+      return premiumEmbeddingToken;
+    }
+
+    if (key === "metabase-store-managed") {
+      return isStoreManaged;
+    }
+
+    return original(key);
+  });
+};
+
+const mockTokenStatus = (valid: boolean) => {
+  xhrMock.get("/api/premium-features/token/status", {
+    body: JSON.stringify({
+      valid,
+      "valid-thru": "2099-12-31T12:00:00",
+    }),
+  });
+};
+
+const mockTokenNotExist = () => {
+  xhrMock.get("/api/premium-features/token/status", {
+    status: 404,
+  });
+};
+
+const mockUpdateToken = (valid: boolean) => {
+  if (valid) {
+    xhrMock.put("/api/setting/premium-embedding-token", {
+      status: 200,
+    });
+  } else {
+    xhrMock.put("/api/setting/premium-embedding-token", {
+      status: 400,
+    });
+  }
+};
+
+describe("LicenseAndBilling", () => {
+  const originalLocation = window.location;
+
+  beforeEach(() => {
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-ignore
+    delete window.location;
+    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+    // @ts-ignore
+    window.location = { reload: jest.fn() };
+    xhrMock.setup();
+  });
+
+  afterEach(() => {
+    xhrMock.teardown();
+    jest.restoreAllMocks();
+
+    window.location = originalLocation;
+  });
+
+  it("renders settings for store managed billing with a valid token", async () => {
+    mockTokenStatus(true);
+    mockSettings(true, "token");
+
+    renderWithProviders(<LicenseAndBillingSettings />);
+
+    expect(
+      await screen.findByText(
+        "Manage your Cloud account, including billing preferences, in your Metabase Store account.",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("Go to the Metabase Store")).toBeInTheDocument();
+
+    expect(
+      screen.getByText(
+        "Your license is active until Dec 31, 2099! Hope you’re enjoying it.",
+      ),
+    ).toBeInTheDocument();
+  });
+
+  it("renders settings for non-store-managed billing with a valid token", async () => {
+    mockTokenStatus(true);
+    mockSettings(false, "token");
+
+    renderWithProviders(<LicenseAndBillingSettings />);
+
+    expect(
+      await screen.findByText(
+        "To manage your billing preferences, please email",
+      ),
+    ).toBeInTheDocument();
+    expect(screen.getByText("billing@metabase.com")).toHaveAttribute(
+      "href",
+      "mailto:billing@metabase.com",
+    );
+
+    expect(
+      screen.getByText(
+        "Your license is active until Dec 31, 2099! Hope you’re enjoying it.",
+      ),
+    ).toBeInTheDocument();
+  });
+
+  it("renders settings for unlicensed instances", async () => {
+    mockTokenNotExist();
+    renderWithProviders(<LicenseAndBillingSettings />);
+
+    expect(
+      await screen.findByText(
+        "Bought a license to unlock advanced functionality? Please enter it below.",
+      ),
+    ).toBeInTheDocument();
+  });
+
+  it("shows an error when entered license is not valid", async () => {
+    mockTokenNotExist();
+    mockUpdateToken(false);
+    renderWithProviders(<LicenseAndBillingSettings />);
+
+    expect(
+      await screen.findByText(
+        "Bought a license to unlock advanced functionality? Please enter it below.",
+      ),
+    ).toBeInTheDocument();
+
+    const licenseInput = screen.getByTestId("license-input");
+    const activateButton = screen.getByTestId("activate-button");
+
+    const token = "invalid";
+    await act(async () => {
+      await fireEvent.change(licenseInput, { target: { value: token } });
+      await fireEvent.click(activateButton);
+    });
+
+    expect(
+      await screen.findByText(
+        "This token doesn't seem to be valid. Double-check it, then contact support if you think it should be working.",
+      ),
+    ).toBeInTheDocument();
+  });
+
+  it("refreshes the page when license is accepted", async () => {
+    window.location.reload = jest.fn();
+
+    mockTokenNotExist();
+    mockUpdateToken(true);
+    renderWithProviders(<LicenseAndBillingSettings />);
+
+    expect(
+      await screen.findByText(
+        "Bought a license to unlock advanced functionality? Please enter it below.",
+      ),
+    ).toBeInTheDocument();
+
+    const licenseInput = screen.getByTestId("license-input");
+    const activateButton = screen.getByTestId("activate-button");
+
+    const token = "valid";
+    await act(async () => {
+      await fireEvent.change(licenseInput, { target: { value: token } });
+      await fireEvent.click(activateButton);
+    });
+
+    expect(window.location.reload).toHaveBeenCalled();
+  });
+});
diff --git a/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/index.ts b/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..4dc681802b36f348d474c0bb2b50a5859ea26ca4
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/license/components/LicenseAndBillingSettings/index.ts
@@ -0,0 +1 @@
+export { default } from "./LicenseAndBillingSettings";
diff --git a/enterprise/frontend/src/metabase-enterprise/license/index.ts b/enterprise/frontend/src/metabase-enterprise/license/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..ff5be9ff92b320afef4522e1508072f87e8ba681
--- /dev/null
+++ b/enterprise/frontend/src/metabase-enterprise/license/index.ts
@@ -0,0 +1,4 @@
+import { PLUGIN_LICENSE_PAGE } from "metabase/plugins";
+import LicenseAndBillingSettings from "./components/LicenseAndBillingSettings";
+
+PLUGIN_LICENSE_PAGE.LicenseAndBillingSettings = LicenseAndBillingSettings as any;
diff --git a/enterprise/frontend/src/metabase-enterprise/store/lib/services.js b/enterprise/frontend/src/metabase-enterprise/license/services.ts
similarity index 100%
rename from enterprise/frontend/src/metabase-enterprise/store/lib/services.js
rename to enterprise/frontend/src/metabase-enterprise/license/services.ts
diff --git a/enterprise/frontend/src/metabase-enterprise/plugins.js b/enterprise/frontend/src/metabase-enterprise/plugins.js
index ab5d012de7346621b37de411acce456e9f0d8e87..ed722d11a4496d5d4d04c072cfebd36ed1172a9e 100644
--- a/enterprise/frontend/src/metabase-enterprise/plugins.js
+++ b/enterprise/frontend/src/metabase-enterprise/plugins.js
@@ -15,10 +15,10 @@ import "./caching";
 import "./collections";
 import "./whitelabel";
 import "./embedding";
-import "./store";
 import "./snippets";
 import "./sharing";
 import "./moderation";
 import "./advanced_config";
 import "./advanced_permissions";
 import "./audit_app";
+import "./license";
diff --git a/enterprise/frontend/src/metabase-enterprise/store/components/StoreIcon.jsx b/enterprise/frontend/src/metabase-enterprise/store/components/StoreIcon.jsx
deleted file mode 100644
index b70fc33cd93300f68e3ae9c6905da969204ee868..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/store/components/StoreIcon.jsx
+++ /dev/null
@@ -1,30 +0,0 @@
-/* eslint-disable react/prop-types */
-import React from "react";
-import { Flex } from "grid-styled";
-import Icon from "metabase/components/Icon";
-import colors from "metabase/lib/colors";
-
-const ICON_SIZE = 22;
-const WRAPPER_SIZE = ICON_SIZE * 2.5;
-
-const StoreIconWrapper = ({ children, color }) => (
-  <Flex
-    align="center"
-    justify="center"
-    p={2}
-    bg={color || colors["brand"]}
-    color="white"
-    width={WRAPPER_SIZE}
-    style={{ borderRadius: 99, height: WRAPPER_SIZE }}
-  >
-    {children}
-  </Flex>
-);
-
-const StoreIcon = ({ color, name, ...props }) => (
-  <StoreIconWrapper color={color}>
-    <Icon name={name} size={ICON_SIZE} />
-  </StoreIconWrapper>
-);
-
-export default StoreIcon;
diff --git a/enterprise/frontend/src/metabase-enterprise/store/containers/StoreAccount.jsx b/enterprise/frontend/src/metabase-enterprise/store/containers/StoreAccount.jsx
deleted file mode 100644
index ebd9add4f70a4a453a63b11db263677502ac500c..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/store/containers/StoreAccount.jsx
+++ /dev/null
@@ -1,306 +0,0 @@
-/* eslint-disable react/prop-types */
-import React from "react";
-import { Box, Flex } from "grid-styled";
-import { t } from "ttag";
-
-import _ from "underscore";
-
-import colors from "metabase/lib/colors";
-
-import StoreIcon from "../components/StoreIcon";
-import Card from "metabase/components/Card";
-import Link from "metabase/components/Link";
-import ExternalLink from "metabase/components/ExternalLink";
-import LoadingAndErrorWrapper from "metabase/components/LoadingAndErrorWrapper";
-
-import fitViewport from "metabase/hoc/FitViewPort";
-
-import moment from "moment";
-
-import FEATURES from "../lib/features";
-import { StoreApi } from "../lib/services";
-
-@fitViewport
-export default class StoreAccount extends React.Component {
-  state = {
-    status: null,
-    error: null,
-  };
-
-  async UNSAFE_componentWillMount() {
-    try {
-      this.setState({
-        status: await StoreApi.tokenStatus(),
-      });
-    } catch (e) {
-      this.setState({
-        error: e,
-      });
-    }
-  }
-
-  render() {
-    const { status, error } = this.state;
-
-    const features =
-      status &&
-      status.features &&
-      _.object(status.features.map(f => [f, true]));
-    const expires = status && status.valid_thru && moment(status.valid_thru);
-
-    return (
-      <Flex
-        align="center"
-        justify="center"
-        flexDirection="column"
-        className={this.props.fitClassNames}
-      >
-        {error ? (
-          error.status === 404 ? (
-            <Unlicensed />
-          ) : (
-            <TokenError />
-          )
-        ) : (
-          <LoadingAndErrorWrapper loading={!status} className="full">
-            {() =>
-              status.valid && !status.trial ? (
-                <Active features={features} expires={expires} />
-              ) : !status.valid && !status.trial ? (
-                <Expired features={features} expires={expires} />
-              ) : status.valid && status.trial ? (
-                <TrialActive features={features} expires={expires} />
-              ) : !status.valid && status.trial ? (
-                <TrialExpired features={features} expires={expires} />
-              ) : (
-                <h2>{status.status}</h2>
-              )
-            }
-          </LoadingAndErrorWrapper>
-        )}
-      </Flex>
-    );
-  }
-}
-
-const TokenError = () => (
-  <Flex align="center" justify="center" flexDirection="column">
-    <h2 className="text-error">{t`We're having trouble validating your token`}</h2>
-    <h4 className="mt2">{t`Please double-check that your instance can connect to Metabase's servers`}</h4>
-    <ExternalLink
-      className="Button Button--primary mt4"
-      href="mailto:support@metabase.com"
-    >
-      {t`Get help`}
-    </ExternalLink>
-  </Flex>
-);
-
-const Unlicensed = () => (
-  <AccountStatus
-    title={t`Get even more out of Metabase with the Enterprise Edition`}
-    subtitle={
-      <h4 className="text-centered">{t`All the tools you need to quickly and easily provide reports for your customers, or to help you run and monitor Metabase in a large organization`}</h4>
-    }
-    preview
-  >
-    <Box m={4}>
-      <ExternalLink
-        className="Button Button--primary"
-        href={"http://metabase.com/enterprise/"}
-      >
-        {t`Learn more`}
-      </ExternalLink>
-      <Link className="Button ml2" to={"admin/store/activate"}>
-        {t`Activate a license`}
-      </Link>
-    </Box>
-  </AccountStatus>
-);
-
-const TrialActive = ({ features, expires }) => (
-  <AccountStatus
-    title={t`Your trial is active with these features`}
-    subtitle={expires && <h3>{t`Trial expires ${expires.fromNow()}`}</h3>}
-    features={features}
-  >
-    <CallToAction
-      title={t`Need help? Ready to buy?`}
-      buttonText={t`Talk to us`}
-      buttonLink={
-        "mailto:support@metabase.com?Subject=Metabase Enterprise Edition"
-      }
-    />
-    <Link
-      className="link"
-      to={"admin/store/activate"}
-    >{t`Activate a license`}</Link>
-  </AccountStatus>
-);
-
-const TrialExpired = ({ features }) => (
-  <AccountStatus title={t`Your trial has expired`} features={features} expired>
-    <CallToAction
-      title={t`Need more time? Ready to buy?`}
-      buttonText={t`Talk to us`}
-      buttonLink={
-        "mailto:support@metabase.com?Subject=Expired Enterprise Trial"
-      }
-    />
-    <Link
-      className="link"
-      to={"admin/store/activate"}
-    >{t`Activate a license`}</Link>
-  </AccountStatus>
-);
-
-const Active = ({ features, expires }) => (
-  <AccountStatus
-    title={t`Your features are active!`}
-    subtitle={
-      expires && (
-        <h3>{t`Your licence is valid through ${expires.format(
-          "MMMM D, YYYY",
-        )}`}</h3>
-      )
-    }
-    features={features}
-  />
-);
-
-const Expired = ({ features, expires }) => (
-  <AccountStatus
-    title={t`Your license has expired`}
-    subtitle={
-      expires && <h3>{t`It expired on ${expires.format("MMMM D, YYYY")}`}</h3>
-    }
-    features={features}
-    expired
-  >
-    <CallToAction
-      title={t`Want to renew your license?`}
-      buttonText={t`Talk to us`}
-      buttonLink={
-        "mailto:support@metabase.com?Subject=Renewing my Enterprise License"
-      }
-    />
-  </AccountStatus>
-);
-
-const AccountStatus = ({
-  title,
-  subtitle,
-  features = {},
-  expired,
-  preview,
-  children,
-  className,
-}) => {
-  // put included features first
-  const [included, notIncluded] = _.partition(
-    Object.entries(FEATURES),
-    ([id, feature]) => features[id],
-  );
-  const featuresOrdered = [...included, ...notIncluded];
-  return (
-    <Flex
-      align="center"
-      justify="center"
-      flexDirection="column"
-      className={className}
-      p={[2, 4]}
-      width="100%"
-    >
-      <Box>
-        <h2>{title}</h2>
-      </Box>
-      {subtitle && (
-        <Box mt={2} color={colors["text-medium"]} style={{ maxWidth: 500 }}>
-          {subtitle}
-        </Box>
-      )}
-      <Flex mt={4} align="center" flexWrap="wrap" width="100%">
-        {featuresOrdered.map(([id, feature]) => (
-          <Feature
-            key={id}
-            feature={feature}
-            included={features[id]}
-            expired={expired}
-            preview={preview}
-          />
-        ))}
-      </Flex>
-      {children}
-    </Flex>
-  );
-};
-
-const CallToAction = ({ title, buttonText, buttonLink }) => (
-  <Box className="rounded bg-medium m4 py3 px4 flex flex-column layout-centered">
-    <h3 className="mb3">{title}</h3>
-    <ExternalLink className="Button Button--primary" href={buttonLink}>
-      {buttonText}
-    </ExternalLink>
-  </Box>
-);
-
-const Feature = ({ feature, included, expired, preview }) => (
-  <Box width={[1, 1 / 2, 1 / 4]} p={2}>
-    <Card
-      p={[1, 2]}
-      style={{
-        opacity: expired ? 0.5 : 1,
-        width: "100%",
-        height: 260,
-        backgroundColor: included ? undefined : colors["bg-light"],
-        color: included ? colors["text-dark"] : colors["text-medium"],
-      }}
-      className="relative flex flex-column layout-centered"
-    >
-      <StoreIcon
-        name={feature.icon}
-        color={
-          preview
-            ? colors["brand"]
-            : included
-            ? colors["success"]
-            : colors["text-medium"]
-        }
-      />
-
-      <Box my={2}>
-        <h3 className="text-dark">{feature.name}</h3>
-      </Box>
-
-      {preview ? (
-        <FeatureDescription feature={feature} />
-      ) : included ? (
-        <FeatureLinks
-          links={feature.docs}
-          defaultTitle={t`Learn how to use this`}
-        />
-      ) : (
-        <FeatureLinks links={feature.info} defaultTitle={t`Learn more`} />
-      )}
-
-      {!included && !preview && (
-        <div className="spread text-centered pt2 pointer-events-none">{t`Not included in your current plan`}</div>
-      )}
-    </Card>
-  </Box>
-);
-
-const FeatureDescription = ({ feature }) => (
-  <div className="text-centered">{feature.description}</div>
-);
-
-const FeatureLinks = ({ links, defaultTitle }) => (
-  <Flex align="center">
-    {links &&
-      links.map(({ link, title }) => (
-        <ExternalLink href={link} key={link} className="mx2 link">
-          {title || defaultTitle}
-        </ExternalLink>
-      ))}
-  </Flex>
-);
diff --git a/enterprise/frontend/src/metabase-enterprise/store/containers/StoreActivate.jsx b/enterprise/frontend/src/metabase-enterprise/store/containers/StoreActivate.jsx
deleted file mode 100644
index ad29d5b1213705c9e2a5fc076e021620e471b546..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/store/containers/StoreActivate.jsx
+++ /dev/null
@@ -1,98 +0,0 @@
-/* eslint-disable react/prop-types */
-import React from "react";
-import { Box, Flex } from "grid-styled";
-import { t } from "ttag";
-
-import colors from "metabase/lib/colors";
-
-import Button from "metabase/components/Button";
-import Link from "metabase/components/Link";
-
-import ModalWithTrigger from "metabase/components/ModalWithTrigger";
-
-import fitViewport from "metabase/hoc/FitViewPort";
-
-import { SettingsApi } from "metabase/services";
-
-@fitViewport
-export default class Activate extends React.Component {
-  state = {
-    heading: t`Enter the token you received from the store`,
-    errorMessage: "",
-    showVerbose: false,
-    error: false,
-  };
-  activate = async () => {
-    const value = this._input.value.trim();
-    if (!value) {
-      return false;
-    }
-    try {
-      await SettingsApi.put({ key: "premium-embedding-token", value });
-      // set window.location so we do a hard refresh
-      window.location = "/admin/store";
-    } catch (e) {
-      console.error(e.data);
-      this.setState({
-        error: true,
-        heading: e.data.message,
-        errorMessage: e.data["error-details"],
-      });
-    }
-  };
-  render() {
-    return (
-      <Flex
-        align="center"
-        justify="center"
-        className={this.props.fitClassNames}
-      >
-        <Flex align="center" flexDirection="column">
-          <Box my={3}>
-            <h2
-              className="text-centered"
-              style={{ color: this.state.error ? colors["error"] : "inherit" }}
-            >
-              {this.state.heading}
-            </h2>
-          </Box>
-          <Box>
-            <input
-              ref={ref => (this._input = ref)}
-              type="text"
-              className="input"
-              placeholder="XXXX-XXXX-XXXX-XXXX"
-            />
-            <Button ml={1} onClick={this.activate}>{t`Activate`}</Button>
-          </Box>
-
-          {this.state.error && (
-            <ModalWithTrigger
-              triggerElement={
-                <Box mt={3}>
-                  <Link
-                    className="link"
-                    onClick={() => this.setState({ showVerbose: true })}
-                  >{t`Need help?`}</Link>
-                </Box>
-              }
-              onClose={() => this.setState({ showVerbose: false })}
-              title={t`More info about your problem.`}
-              open={this.state.showVerbose}
-            >
-              <Box>{this.state.errorMessage}</Box>
-              <Flex my={2}>
-                <a
-                  className="ml-auto"
-                  href={`mailto:support@metabase.com?Subject="Issue with token activation for token ${this._input.value}"&Body="${this.state.errorMessage}"`}
-                >
-                  <Button primary>{t`Contact support`}</Button>
-                </a>
-              </Flex>
-            </ModalWithTrigger>
-          )}
-        </Flex>
-      </Flex>
-    );
-  }
-}
diff --git a/enterprise/frontend/src/metabase-enterprise/store/index.js b/enterprise/frontend/src/metabase-enterprise/store/index.js
deleted file mode 100644
index 6dc92113b5569e94647e9c8cd19ccde905806503..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/store/index.js
+++ /dev/null
@@ -1,9 +0,0 @@
-import { t } from "ttag";
-import { PLUGIN_ADMIN_NAV_ITEMS, PLUGIN_ADMIN_ROUTES } from "metabase/plugins";
-import MetabaseSettings from "metabase/lib/settings";
-import getRoutes from "./routes";
-
-if (!MetabaseSettings.isHosted()) {
-  PLUGIN_ADMIN_NAV_ITEMS.push({ name: t`Enterprise`, path: "/admin/store" });
-  PLUGIN_ADMIN_ROUTES.push(getRoutes);
-}
diff --git a/enterprise/frontend/src/metabase-enterprise/store/lib/features.js b/enterprise/frontend/src/metabase-enterprise/store/lib/features.js
deleted file mode 100644
index 811a43b45c223dd3aa43b6a360c345a76729639d..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/store/lib/features.js
+++ /dev/null
@@ -1,52 +0,0 @@
-import { t } from "ttag";
-import MetabaseSettings from "metabase/lib/settings";
-
-const FEATURES = {
-  sandboxes: {
-    name: t`Data sandboxes`,
-    description: t`Make sure you're showing the right people the right data with automatic and secure filters based on user attributes.`,
-    icon: "lock",
-    docs: [
-      {
-        link: MetabaseSettings.docsUrl("enterprise-guide/data-sandboxes"),
-      },
-    ],
-  },
-  whitelabel: {
-    name: t`White labeling`,
-    description: t`Match Metabase to your brand with custom colors, your own logo and more.`,
-    icon: "star",
-    docs: [
-      {
-        link: MetabaseSettings.docsUrl("enterprise-guide/whitelabeling"),
-      },
-    ],
-  },
-  "audit-app": {
-    name: t`Auditing`,
-    description: t`Keep an eye on performance and behavior with robust auditing tools.`,
-    icon: "clipboard",
-    info: [{ link: "https://metabase.com/enterprise/" }],
-  },
-  sso: {
-    name: t`Single sign-on`,
-    description: t`Provide easy login that works with your exisiting authentication infrastructure.`,
-    icon: "group",
-    docs: [
-      {
-        title: "SAML",
-        link: MetabaseSettings.docsUrl(
-          "enterprise-guide/authenticating-with-saml",
-        ),
-      },
-      {
-        title: "JWT",
-        link: MetabaseSettings.docsUrl(
-          "enterprise-guide/authenticating-with-jwt",
-        ),
-      },
-    ],
-  },
-};
-
-export default FEATURES;
diff --git a/enterprise/frontend/src/metabase-enterprise/store/routes.jsx b/enterprise/frontend/src/metabase-enterprise/store/routes.jsx
deleted file mode 100644
index ef015eb5f1a4f2b764645298c3ba2aaf5fc960aa..0000000000000000000000000000000000000000
--- a/enterprise/frontend/src/metabase-enterprise/store/routes.jsx
+++ /dev/null
@@ -1,17 +0,0 @@
-import React from "react";
-import { IndexRoute } from "react-router";
-import { t } from "ttag";
-
-import { Route } from "metabase/hoc/Title";
-
-import StoreActivate from "./containers/StoreActivate";
-import StoreAccount from "./containers/StoreAccount";
-
-export default function getRoutes() {
-  return (
-    <Route key="store" path="store" title={t`Store`}>
-      <IndexRoute component={StoreAccount} />
-      <Route path="activate" component={StoreActivate} />
-    </Route>
-  );
-}
diff --git a/frontend/src/metabase/admin/routes.jsx b/frontend/src/metabase/admin/routes.jsx
index ab0a6bb5c80f50e74be8f51c331f27d6093355d1..e19ac63c93f89551e44d25416364eb58e0b401c2 100644
--- a/frontend/src/metabase/admin/routes.jsx
+++ b/frontend/src/metabase/admin/routes.jsx
@@ -20,6 +20,7 @@ import UserActivationModal from "metabase/admin/people/containers/UserActivation
 
 // Settings
 import SettingsEditorApp from "metabase/admin/settings/containers/SettingsEditorApp";
+import PremiumEmbeddingLicensePage from "metabase/admin/settings/containers/PremiumEmbeddingLicensePage";
 
 //  DB Add / list
 import DatabaseListApp from "metabase/admin/databases/containers/DatabaseListApp";
@@ -141,6 +142,10 @@ const getRoutes = (store, IsAdmin) => (
       {/* SETTINGS */}
       <Route path="settings" title={t`Settings`}>
         <IndexRedirect to="setup" />
+        <Route
+          path="premium-embedding-license"
+          component={PremiumEmbeddingLicensePage}
+        />
         <Route path="*" component={SettingsEditorApp} />
       </Route>
 
diff --git a/frontend/src/metabase/admin/settings/components/LicenseInput/LicenseInput.styled.tsx b/frontend/src/metabase/admin/settings/components/LicenseInput/LicenseInput.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6281b0e0c8779c5248ea5a895b874d9c4de39ba1
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/LicenseInput/LicenseInput.styled.tsx
@@ -0,0 +1,21 @@
+import TextInput from "metabase/components/TextInput";
+import { color } from "metabase/lib/colors";
+import styled from "styled-components";
+
+export const LicenseInputContainer = styled.div`
+  display: flex;
+  flex-wrap: nowrap;
+  // min-width: 680px;
+  width: 680px;
+`;
+
+export const LicenseTextInput = styled(TextInput)`
+  flex-grow: 1;
+  margin-right: 8px;
+`;
+
+export const LicenseErrorMessage = styled.div`
+  margin-top: 8px;
+  white-space: nowrap;
+  color: ${color("error")};
+`;
diff --git a/frontend/src/metabase/admin/settings/components/LicenseInput/LicenseInput.tsx b/frontend/src/metabase/admin/settings/components/LicenseInput/LicenseInput.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..6858cbe3173b889a0460fefc31542ddbdda4a323
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/LicenseInput/LicenseInput.tsx
@@ -0,0 +1,62 @@
+import React, { useState } from "react";
+import { t } from "ttag";
+import Button from "metabase/components/Button";
+import {
+  LicenseErrorMessage,
+  LicenseTextInput,
+  LicenseInputContainer,
+} from "./LicenseInput.styled";
+
+export interface LicenseInputProps {
+  token?: string;
+  error?: string;
+  onUpdate: (license: string) => void;
+  loading?: boolean;
+  invalid?: boolean;
+  placeholder?: string;
+}
+
+export const LicenseInput = ({
+  token,
+  error,
+  onUpdate,
+  loading,
+  invalid,
+  placeholder,
+}: LicenseInputProps) => {
+  const [value, setValue] = useState(token ?? "");
+
+  const handleChange = (value: string) => setValue(value);
+
+  const handleActivate = () => {
+    onUpdate(value);
+  };
+
+  return (
+    <>
+      <LicenseInputContainer>
+        <LicenseTextInput
+          invalid={invalid}
+          data-testid="license-input"
+          disabled={loading}
+          onChange={handleChange}
+          value={value}
+          placeholder={
+            placeholder ??
+            "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
+          }
+        />
+        <Button
+          disabled={loading}
+          data-testid="activate-button"
+          className="px2"
+          onClick={handleActivate}
+        >
+          {t`Activate`}
+        </Button>
+      </LicenseInputContainer>
+
+      {error && <LicenseErrorMessage>{error}</LicenseErrorMessage>}
+    </>
+  );
+};
diff --git a/frontend/src/metabase/admin/settings/components/LicenseInput/index.ts b/frontend/src/metabase/admin/settings/components/LicenseInput/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6bfecdf1a76af707555e58e2a012de7c599399a0
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/LicenseInput/index.ts
@@ -0,0 +1 @@
+export * from "./LicenseInput";
diff --git a/frontend/src/metabase/admin/settings/components/SettingsLicense/SettingsLicense.styled.tsx b/frontend/src/metabase/admin/settings/components/SettingsLicense/SettingsLicense.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..ffca32d77d12a24ad24686d43a3c3d8766672df2
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/SettingsLicense/SettingsLicense.styled.tsx
@@ -0,0 +1,50 @@
+import styled from "styled-components";
+import { color } from "metabase/lib/colors";
+
+export const SectionHeader = styled.h4`
+  display: block;
+  color: ${color("text-medium")};
+  font-weight: bold;
+  text-transform: uppercase;
+  margin-bottom: 8px;
+
+  &:not(:first-child) {
+    margin-top: 40px;
+  }
+`;
+
+export const SectionDescription = styled.p`
+  color: ${color("text-medium")};
+  margin-top: 8px;
+  margin-bottom: 16px;
+  line-height: 1.7em;
+`;
+
+export const SubHeader = styled.h4`
+  margin-top: 32px;
+`;
+
+interface ExporePaidPlansContainerProps {
+  justifyContent?: string;
+}
+
+export const ExporePaidPlansContainer = styled.div<
+  ExporePaidPlansContainerProps
+>`
+  margin: 16px 0;
+  display: flex;
+  align-items: flex-start;
+  justify-content: ${props => props.justifyContent ?? "space-between"};
+  border-bottom: 1px solid ${color("border")};
+`;
+
+export const SettingsLicenseContainer = styled.div`
+  width: 580px;
+  padding: 16px;
+`;
+
+export const LoaderContainer = styled.div`
+  display: flex;
+  justify-content: center;
+  align-items: center;
+`;
diff --git a/frontend/src/metabase/admin/settings/components/SettingsLicense/SettingsLicense.tsx b/frontend/src/metabase/admin/settings/components/SettingsLicense/SettingsLicense.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7737e5519acd7b5dd348ec49ea30e511b7eb25fd
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/SettingsLicense/SettingsLicense.tsx
@@ -0,0 +1,34 @@
+import React from "react";
+import MetabaseSettings from "metabase/lib/settings";
+import { StarterContent } from "./content/StarterContent";
+import { UnlicensedContent } from "./content/UnlicensedContent";
+import { PLUGIN_LICENSE_PAGE } from "metabase/plugins";
+import { SettingsLicenseContainer } from "./SettingsLicense.styled";
+
+const SettingsLicense = () => {
+  const isOss =
+    !MetabaseSettings.isHosted() && !MetabaseSettings.isEnterprise();
+
+  if (isOss) {
+    return (
+      <SettingsLicenseContainer>
+        <UnlicensedContent />
+      </SettingsLicenseContainer>
+    );
+  }
+
+  const isStarter =
+    MetabaseSettings.isHosted() && !MetabaseSettings.isEnterprise();
+
+  if (isStarter) {
+    return (
+      <SettingsLicenseContainer>
+        <StarterContent />
+      </SettingsLicenseContainer>
+    );
+  }
+
+  return <PLUGIN_LICENSE_PAGE.LicenseAndBillingSettings />;
+};
+
+export default SettingsLicense;
diff --git a/frontend/src/metabase/admin/settings/components/SettingsLicense/content/ExplorePlansIllustration.tsx b/frontend/src/metabase/admin/settings/components/SettingsLicense/content/ExplorePlansIllustration.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..7f5b2b5bd3d984bb6dc4809ea8e26389a025027b
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/SettingsLicense/content/ExplorePlansIllustration.tsx
@@ -0,0 +1,155 @@
+import React from "react";
+
+export const ExplorePlansIllustration = () => {
+  return (
+    <svg
+      width="287"
+      height="243"
+      fill="none"
+      xmlns="http://www.w3.org/2000/svg"
+    >
+      <path
+        fillRule="evenodd"
+        clipRule="evenodd"
+        d="M249.785 100.5c-11.319 8.467-31.524 7.885-47.417-7.997-16.102-16.091-17.121-39.65-8.523-51.249-.388.4-.742.815-1.06 1.246-14.465 15.567-12.372 41.47 1.97 55.803 15.944 14.759 41.13 16.047 55.03 2.197Z"
+        fill="#EEF6FD"
+      />
+      <path
+        d="m267.081 41.083.515-.213-.214-.514-.963-2.317v-.001a.757.757 0 0 1-.058-.29.762.762 0 0 1 1.124-.658.766.766 0 0 1 .345.375l.961 2.317.213.513.514-.212 2.317-.957a.766.766 0 0 1 .972.995.765.765 0 0 1-.387.41l-2.316.957-.515.213.214.514.964 2.32.004.008.004.009a.773.773 0 0 1 .015.594.75.75 0 0 1-.419.425.769.769 0 0 1-1.009-.438l-.004-.01-.004-.008-.964-2.32-.212-.51-.513.21-2.324.954a.77.77 0 0 1-1-.41.765.765 0 0 1 .415-.995l2.325-.961ZM143.081 58.083l.515-.213-.214-.514-.963-2.317v-.001a.757.757 0 0 1-.058-.29.762.762 0 0 1 1.124-.658.766.766 0 0 1 .345.375l.961 2.317.213.513.514-.212 2.317-.957a.766.766 0 0 1 .972.995.765.765 0 0 1-.387.41l-2.316.957-.515.213.214.514.964 2.32.004.008.004.009a.773.773 0 0 1 .015.594.75.75 0 0 1-.419.425.769.769 0 0 1-1.009-.438l-.004-.01-.004-.008-.964-2.32-.212-.51-.513.21-2.324.954a.77.77 0 0 1-1-.41.765.765 0 0 1 .415-.995l2.325-.961ZM210.081 143.083l.515-.213-.214-.515-.963-2.316v-.001a.758.758 0 0 1-.058-.29.759.759 0 0 1 .617-.734.768.768 0 0 1 .852.451l.961 2.317.213.513.514-.212 2.317-.957a.766.766 0 0 1 .967.425.764.764 0 0 1 .005.57.768.768 0 0 1-.387.41l-2.316.957-.515.213.214.514.964 2.319.004.009.004.009a.77.77 0 0 1 .015.594.754.754 0 0 1-.419.425.767.767 0 0 1-1.009-.438l-.004-.009-.004-.009-.964-2.319-.212-.512-.513.211-2.324.954a.768.768 0 0 1-1-.41.764.764 0 0 1 .415-.995l2.325-.961Z"
+        fill="#509EE3"
+        stroke="#509EE3"
+      />
+      <path
+        d="M260.126 91.41c.798-1.267-.305-2.817-1.721-2.58a45.925 45.925 0 0 1-11.92.419c-25.367-2.402-44.906-25.017-42.5-50.437.144-1.52.359-3.015.643-4.483.272-1.414-1.254-2.55-2.539-1.783-11.169 6.662-19.131 18.411-20.455 32.394-2.2 23.234 14.762 43.857 37.902 46.048 16.315 1.545 32.355-6.493 40.59-19.577Z"
+        stroke="#509EE3"
+        strokeWidth="3"
+      />
+      <path
+        d="M193.654 9.179a.826.826 0 0 1-.835.834c-4.141 0-7.515 3.371-7.515 7.51a.826.826 0 0 1-.835.834.838.838 0 0 1-.835-.834c0-4.139-3.373-7.51-7.514-7.51a.837.837 0 0 1-.835-.834c0-.468.384-.835.835-.835 4.141 0 7.514-3.37 7.514-7.51 0-.467.385-.834.835-.834.468 0 .835.367.835.834 0 4.14 3.374 7.51 7.515 7.51.468 0 .835.367.835.835ZM162.654 122.179a.826.826 0 0 1-.835.834c-4.141 0-7.515 3.371-7.515 7.51a.826.826 0 0 1-.835.834.838.838 0 0 1-.835-.834c0-4.139-3.373-7.51-7.514-7.51a.837.837 0 0 1-.835-.834c0-.468.384-.835.835-.835 4.141 0 7.514-3.371 7.514-7.51 0-.467.385-.834.835-.834.468 0 .835.367.835.834 0 4.139 3.374 7.51 7.515 7.51.468 0 .835.367.835.835ZM286.654 122.179a.826.826 0 0 1-.835.834c-4.141 0-7.515 3.371-7.515 7.51a.826.826 0 0 1-.835.834.838.838 0 0 1-.835-.834c0-4.139-3.373-7.51-7.514-7.51a.837.837 0 0 1-.835-.834c0-.468.384-.835.835-.835 4.141 0 7.514-3.371 7.514-7.51 0-.467.385-.834.835-.834.468 0 .835.367.835.834 0 4.139 3.374 7.51 7.515 7.51.468 0 .835.367.835.835Z"
+        fill="#E6F5FF"
+      />
+      <rect
+        x="94.285"
+        y="127.788"
+        width="16.829"
+        height="9.963"
+        rx="3"
+        transform="rotate(-23.79 94.285 127.788)"
+        fill="#EEF6FD"
+      />
+      <rect
+        x="1.285"
+        y="183.422"
+        width="24.349"
+        height="7.835"
+        rx="3"
+        transform="rotate(-23.79 1.285 183.422)"
+        fill="#EEF6FD"
+      />
+      <path
+        fill="#EEF6FD"
+        d="m18.635 169.492 44.577-19.65 3.923 8.9-44.576 19.65z"
+      />
+      <path
+        fill="#EEF6FD"
+        d="m58.775 147.087 39.567-17.443 4.445 10.083L63.22 157.17z"
+      />
+      <rect
+        x="96.262"
+        y="128.556"
+        width="13.829"
+        height="37.945"
+        rx="1.5"
+        transform="rotate(-23.79 96.262 128.556)"
+        stroke="#509EE3"
+        strokeWidth="3"
+      />
+      <rect
+        x="60.752"
+        y="147.855"
+        width="40.241"
+        height="31.741"
+        rx="1.5"
+        transform="rotate(-23.79 60.752 147.855)"
+        stroke="#509EE3"
+        strokeWidth="3"
+      />
+      <rect
+        x="20.613"
+        y="170.26"
+        width="45.716"
+        height="23.651"
+        rx="1.5"
+        transform="rotate(-23.79 20.613 170.26)"
+        stroke="#509EE3"
+        strokeWidth="3"
+      />
+      <rect
+        x="3.262"
+        y="184.19"
+        width="21.349"
+        height="13.164"
+        rx="1.5"
+        transform="rotate(-23.79 3.262 184.19)"
+        stroke="#509EE3"
+        strokeWidth="3"
+      />
+      <rect
+        x="1.33"
+        y="181.685"
+        width="1.586"
+        height="19.132"
+        rx=".793"
+        transform="rotate(-23.79 1.33 181.685)"
+        stroke="#509EE3"
+        strokeWidth="1.586"
+      />
+      <rect
+        x="72.311"
+        y="185.602"
+        width="1.586"
+        height="60.501"
+        rx=".793"
+        transform="rotate(-21.29 72.311 185.602)"
+        stroke="#509EE3"
+        strokeWidth="1.586"
+      />
+      <rect
+        x="63.007"
+        y="184.024"
+        width="1.586"
+        height="60.501"
+        rx=".793"
+        transform="rotate(21.017 63.007 184.024)"
+        stroke="#509EE3"
+        strokeWidth="1.586"
+      />
+      <rect
+        x="113.535"
+        y="240.75"
+        width="1.5"
+        height="90.5"
+        rx=".75"
+        transform="rotate(90 113.535 240.75)"
+        stroke="#509EE3"
+        strokeWidth="1.5"
+      />
+      <circle
+        cx="68.285"
+        cy="175"
+        r="10.5"
+        fill="#fff"
+        stroke="#509EE3"
+        strokeWidth="3"
+      />
+      <circle
+        cx="92.785"
+        cy="237.5"
+        r="4.3"
+        fill="#fff"
+        stroke="#509EE3"
+        strokeWidth="2.4"
+      />
+    </svg>
+  );
+};
diff --git a/frontend/src/metabase/admin/settings/components/SettingsLicense/content/StarterContent.tsx b/frontend/src/metabase/admin/settings/components/SettingsLicense/content/StarterContent.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..92d596e6a4042e721b027ae3e0bf5b78193a08d1
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/SettingsLicense/content/StarterContent.tsx
@@ -0,0 +1,44 @@
+import React from "react";
+import { t, jt } from "ttag";
+import ExternalLink from "metabase/components/ExternalLink";
+import MetabaseSettings from "metabase/lib/settings";
+import { ExplorePlansIllustration } from "./ExplorePlansIllustration";
+import {
+  ExporePaidPlansContainer,
+  SectionDescription,
+  SectionHeader,
+  SettingsLicenseContainer,
+} from "../SettingsLicense.styled";
+
+export const StarterContent = () => {
+  return (
+    <SettingsLicenseContainer>
+      <SectionHeader>{t`Billing`}</SectionHeader>
+
+      <SectionDescription>
+        {t`Manage your Cloud account, including billing preferences, in your Metabase Store account.`}
+      </SectionDescription>
+
+      <ExternalLink
+        href={MetabaseSettings.storeUrl()}
+        className="Button Button--primary"
+      >
+        {t`Go to the Metabase Store`}
+      </ExternalLink>
+
+      <SectionHeader>{t`Looking for more?`}</SectionHeader>
+
+      <SectionDescription>
+        {jt`You can get priority support, more tools to help you share your insights with your teams and powerful options to help you create seamless, interactive data experiences for your customers with ${(
+          <ExternalLink href={MetabaseSettings.upgradeUrl()}>
+            {t`our other paid plans.`}
+          </ExternalLink>
+        )}`}
+      </SectionDescription>
+
+      <ExporePaidPlansContainer justifyContent="flex-end">
+        <ExplorePlansIllustration />
+      </ExporePaidPlansContainer>
+    </SettingsLicenseContainer>
+  );
+};
diff --git a/frontend/src/metabase/admin/settings/components/SettingsLicense/content/UnlicensedContent.tsx b/frontend/src/metabase/admin/settings/components/SettingsLicense/content/UnlicensedContent.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..66929c1b3af68314b1ae64a31f9668572a988094
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/SettingsLicense/content/UnlicensedContent.tsx
@@ -0,0 +1,35 @@
+import React from "react";
+import { t } from "ttag";
+import ExternalLink from "metabase/components/ExternalLink";
+import MetabaseSettings from "metabase/lib/settings";
+import {
+  ExporePaidPlansContainer,
+  SectionDescription,
+  SectionHeader,
+  SettingsLicenseContainer,
+  SubHeader,
+} from "../SettingsLicense.styled";
+import { ExplorePlansIllustration } from "./ExplorePlansIllustration";
+
+const description = t`Metabase is open source and will be free forever – but by upgrading you can have priority support, more tools to help you share your insights with your teams and powerful options to help you create seamless, interactive data experiences for your customers.`;
+
+export const UnlicensedContent = () => {
+  return (
+    <>
+      <SectionHeader>{t`Looking for more?`}</SectionHeader>
+
+      <SectionDescription>{description}</SectionDescription>
+
+      <SubHeader>{t`Want to know more?`}</SubHeader>
+
+      <ExporePaidPlansContainer>
+        <ExternalLink
+          className="Button Button--primary"
+          href={MetabaseSettings.upgradeUrl()}
+        >{t`Explore our paid plans`}</ExternalLink>
+
+        <ExplorePlansIllustration />
+      </ExporePaidPlansContainer>
+    </>
+  );
+};
diff --git a/frontend/src/metabase/admin/settings/components/SettingsLicense/index.ts b/frontend/src/metabase/admin/settings/components/SettingsLicense/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..6ccb81f331cced897e6f89b0eeab8ccf690f50aa
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/SettingsLicense/index.ts
@@ -0,0 +1,2 @@
+export { default } from "./SettingsLicense";
+export * from "./SettingsLicense.styled";
diff --git a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo.tsx b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo.tsx
index e77351dca71dc9f5daa03b0f805609e333cb64aa..be60c968231c37cd95f1620dd754eb26bfb63e88 100644
--- a/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo.tsx
+++ b/frontend/src/metabase/admin/settings/components/widgets/EmbeddingCustomizationInfo.tsx
@@ -11,7 +11,7 @@ export const EmbeddingCustomizationInfo = () => {
       <p style={{ maxWidth: "460px" }}>
         {jt`Looking to remove the “Powered by Metabase” logo, customize colors
         and make it your own? ${(
-          <ExternalLink href={MetabaseSettings.pricingUrl()}>
+          <ExternalLink href={MetabaseSettings.upgradeUrl()}>
             Explore our paid plans.
           </ExternalLink>
         )}`}
diff --git a/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/PremiumEmbeddingLinkWidget.styled.tsx b/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/PremiumEmbeddingLinkWidget.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..93be1e44751a571c91d5233afc0892c4f47d9d6a
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/PremiumEmbeddingLinkWidget.styled.tsx
@@ -0,0 +1,10 @@
+import styled from "styled-components";
+import { color } from "metabase/lib/colors";
+
+export const PremiumEmbeddingLinkWidgetRoot = styled.div`
+  color: ${color("text-medium")};
+  padding-top: 1rem;
+  width: 100%;
+  max-width: 38.75rem;
+  border-top: 1px solid ${color("border")};
+`;
diff --git a/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/PremiumEmbeddingLinkWidget.tsx b/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/PremiumEmbeddingLinkWidget.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..f465f36fabaac4f268002ad5918c005bdcb9e968
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/PremiumEmbeddingLinkWidget.tsx
@@ -0,0 +1,16 @@
+import React from "react";
+import { t } from "ttag";
+import Link from "metabase/components/Link";
+import { PremiumEmbeddingLinkWidgetRoot } from "./PremiumEmbeddingLinkWidget.styled";
+
+export const PremiumEmbeddingLinkWidget = () => {
+  return (
+    <PremiumEmbeddingLinkWidgetRoot>
+      {t`Have a Premium Embedding license?`}{" "}
+      <Link
+        to="/admin/settings/premium-embedding-license"
+        className="link"
+      >{t`Activate it here.`}</Link>
+    </PremiumEmbeddingLinkWidgetRoot>
+  );
+};
diff --git a/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/index.ts b/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c0227b847b52f33b81ad7593fb87b20a97021c7a
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/components/widgets/PremiumEmbeddingLinkWidget/index.ts
@@ -0,0 +1 @@
+export * from "./PremiumEmbeddingLinkWidget";
diff --git a/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/PremiumEmbeddingLicensePage.styled.tsx b/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/PremiumEmbeddingLicensePage.styled.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..a54f278120aa57cd0272f68641806126a1954803
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/PremiumEmbeddingLicensePage.styled.tsx
@@ -0,0 +1,37 @@
+import LoadingSpinner from "metabase/components/LoadingSpinner";
+import { color } from "metabase/lib/colors";
+import styled from "styled-components";
+
+export const PremiumEmbeddingLicensePageContent = styled.div`
+  display: flex;
+  align-items: stretch;
+  text-align: left;
+  justify-content: center;
+  flex-direction: column;
+  margin-left: 10%;
+  margin-top: 32px;
+  max-width: 640px;
+`;
+
+export const PremiumEmbeddingHeading = styled.h1`
+  font-weight: 700;
+  font-size: 21px;
+  line-height: 25px;
+`;
+
+export const PremiumEmbeddingDescription = styled.p`
+  color: ${color("text-medium")};
+  margin-bottom: 2rem;
+  font-size: 14px;
+  line-height: 24px;
+`;
+
+export const LicenseInputTitle = styled.div`
+  font-weight: 700;
+  margin-bottom: 1rem;
+`;
+
+export const Loader = styled(LoadingSpinner)`
+  display: flex;
+  justify-content: center;
+`;
diff --git a/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/PremiumEmbeddingLicensePage.tsx b/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/PremiumEmbeddingLicensePage.tsx
new file mode 100644
index 0000000000000000000000000000000000000000..42fdad5971278b3c2b8d8230ffb2922ec7433601
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/PremiumEmbeddingLicensePage.tsx
@@ -0,0 +1,124 @@
+import React, { useEffect } from "react";
+import { jt, t } from "ttag";
+import { connect } from "react-redux";
+import moment from "moment";
+import AdminLayout from "metabase/components/AdminLayout";
+import ExternalLink from "metabase/components/ExternalLink";
+import MetabaseSettings from "metabase/lib/settings";
+import {
+  LicenseInputTitle,
+  Loader,
+  PremiumEmbeddingDescription,
+  PremiumEmbeddingHeading,
+  PremiumEmbeddingLicensePageContent,
+} from "./PremiumEmbeddingLicensePage.styled";
+import { LicenseInput } from "../../components/LicenseInput";
+import { initializeSettings } from "../../settings";
+import { getSettings } from "../../selectors";
+import { TokenStatus, useLicense } from "../../hooks/use-license";
+
+const getDescription = (tokenStatus?: TokenStatus, hasToken?: boolean) => {
+  if (!hasToken) {
+    return t`Our Premium Embedding product has been discontinued, but if you already have a license you can activate it here. You’ll continue to receive support for the duration of your license.`;
+  }
+
+  if (!tokenStatus || !tokenStatus.isValid) {
+    return (
+      <>
+        {jt`Your Premium Embedding license isn’t valid anymore. ${(
+          <ExternalLink href={MetabaseSettings.upgradeUrl()}>
+            {t`Explore our paid plans.`}
+          </ExternalLink>
+        )}`}
+      </>
+    );
+  }
+
+  const validUntil = moment(tokenStatus.validUntil).format("MMM D, YYYY");
+
+  return t`Your Premium Embedding license is active until ${validUntil}.`;
+};
+
+const mapStateToProps = (state: any) => {
+  return {
+    settings: getSettings(state),
+  };
+};
+
+const mapDispatchToProps = {
+  initializeSettings,
+};
+
+interface PremiumEmbeddingLicensePage {
+  initializeSettings: () => void;
+  settings: any[];
+}
+
+export const PremiumEmbeddingLicensePage = ({
+  settings,
+  initializeSettings,
+}: PremiumEmbeddingLicensePage) => {
+  const tokenSetting = settings.find(
+    setting => setting.key === "premium-embedding-token",
+  );
+  const token = tokenSetting?.value;
+
+  const {
+    isLoading,
+    error,
+    tokenStatus,
+    updateToken,
+    isUpdating,
+  } = useLicense();
+
+  useEffect(() => {
+    initializeSettings();
+  }, [initializeSettings]);
+
+  const hasSettings = settings.length > 0;
+
+  if (isLoading || !hasSettings) {
+    return (
+      <AdminLayout>
+        <PremiumEmbeddingLicensePageContent>
+          <Loader />
+        </PremiumEmbeddingLicensePageContent>
+      </AdminLayout>
+    );
+  }
+
+  const isInvalid = !!error || (tokenStatus != null && !tokenStatus.isValid);
+
+  const placeholder = tokenSetting.is_env_setting
+    ? t`Using ${tokenSetting.env_name}`
+    : undefined;
+
+  return (
+    <AdminLayout>
+      <PremiumEmbeddingLicensePageContent>
+        <PremiumEmbeddingHeading>Premium embedding</PremiumEmbeddingHeading>
+        <PremiumEmbeddingDescription>
+          {getDescription(tokenStatus, !!token)}
+        </PremiumEmbeddingDescription>
+        {!tokenStatus?.isValid && (
+          <LicenseInputTitle>
+            {t`Enter the token you bought from the Metabase Store below.`}
+          </LicenseInputTitle>
+        )}
+        <LicenseInput
+          error={error}
+          loading={isUpdating}
+          token={token}
+          onUpdate={updateToken}
+          invalid={isInvalid}
+          placeholder={placeholder}
+        />
+      </PremiumEmbeddingLicensePageContent>
+    </AdminLayout>
+  );
+};
+
+export default connect(
+  mapStateToProps,
+  mapDispatchToProps,
+)(PremiumEmbeddingLicensePage);
diff --git a/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/index.ts b/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/index.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6710761ddfc0b58c54b6d2ed7e687dc53c1d261
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/containers/PremiumEmbeddingLicensePage/index.ts
@@ -0,0 +1 @@
+export { default } from "./PremiumEmbeddingLicensePage";
diff --git a/frontend/src/metabase/admin/settings/hooks/use-license.ts b/frontend/src/metabase/admin/settings/hooks/use-license.ts
new file mode 100644
index 0000000000000000000000000000000000000000..aa9ca3875885f0f08d05f4b9cb767dd7dc891c35
--- /dev/null
+++ b/frontend/src/metabase/admin/settings/hooks/use-license.ts
@@ -0,0 +1,81 @@
+import { SettingsApi, StoreApi } from "metabase/services";
+import { useCallback, useEffect, useState } from "react";
+import { t } from "ttag";
+
+export const LICENSE_ACCEPTED_URL_HASH = "#activated";
+
+const INVALID_TOKEN_ERROR = t`This token doesn't seem to be valid. Double-check it, then contact support if you think it should be working.`;
+const UNABLE_TO_VALIDATE_TOKEN = t`We're having trouble validating your token. Please double-check that your instance can connect to Metabase's servers.`;
+
+export type TokenStatus = {
+  validUntil: Date;
+  isValid: boolean;
+  isTrial: boolean;
+  features: string[];
+};
+
+export const useLicense = (onActivated?: () => void) => {
+  const [tokenStatus, setTokenStatus] = useState<TokenStatus>();
+  const [isLoading, setIsLoading] = useState(true);
+  const [isUpdating, setIsUpdating] = useState(false);
+  const [error, setError] = useState<string>();
+
+  useEffect(() => {
+    if (window.location.hash === LICENSE_ACCEPTED_URL_HASH) {
+      history.pushState("", document.title, window.location.pathname);
+      onActivated?.();
+    }
+  }, [onActivated]);
+
+  const updateToken = useCallback(async (token: string) => {
+    try {
+      setError(undefined);
+      setIsUpdating(true);
+      await SettingsApi.put({
+        key: "premium-embedding-token",
+        value: token,
+      });
+
+      // In order to apply pro and enterprise features we need to perform a full reload
+      const isValidTokenAccepted = token.trim().length > 0;
+      if (isValidTokenAccepted) {
+        window.location.href += LICENSE_ACCEPTED_URL_HASH;
+      }
+      window.location.reload();
+    } catch {
+      setError(INVALID_TOKEN_ERROR);
+    } finally {
+      setIsUpdating(false);
+    }
+  }, []);
+
+  useEffect(() => {
+    const fetchStatus = async () => {
+      try {
+        const response = await StoreApi.tokenStatus();
+        setTokenStatus({
+          validUntil: new Date(response["valid-thru"]),
+          isValid: response.valid,
+          isTrial: response.trial,
+          features: response.features,
+        });
+      } catch (e) {
+        if ((e as any).status !== 404) {
+          setError(UNABLE_TO_VALIDATE_TOKEN);
+        }
+      } finally {
+        setIsLoading(false);
+      }
+    };
+
+    fetchStatus();
+  }, []);
+
+  return {
+    isUpdating,
+    error,
+    tokenStatus,
+    isLoading,
+    updateToken,
+  };
+};
diff --git a/frontend/src/metabase/admin/settings/selectors.js b/frontend/src/metabase/admin/settings/selectors.js
index b1e6b2292efc32f1a7d7739e42f92ff0098092f8..a00972ca5645b2ae02a1c2beb9ad37c91af6f6ee 100644
--- a/frontend/src/metabase/admin/settings/selectors.js
+++ b/frontend/src/metabase/admin/settings/selectors.js
@@ -3,6 +3,7 @@ import { createSelector } from "reselect";
 import MetabaseSettings from "metabase/lib/settings";
 import { t } from "ttag";
 import CustomGeoJSONWidget from "./components/widgets/CustomGeoJSONWidget";
+import SettingsLicense from "./components/SettingsLicense";
 import SiteUrlWidget from "./components/widgets/SiteUrlWidget";
 import HttpsOnlyWidget from "./components/widgets/HttpsOnlyWidget";
 import { EmbeddingCustomizationInfo } from "./components/widgets/EmbeddingCustomizationInfo";
@@ -15,6 +16,7 @@ import {
 import SecretKeyWidget from "./components/widgets/SecretKeyWidget";
 import EmbeddingLegalese from "./components/widgets/EmbeddingLegalese";
 import FormattingWidget from "./components/widgets/FormattingWidget";
+import { PremiumEmbeddingLinkWidget } from "./components/widgets/PremiumEmbeddingLinkWidget";
 import SettingsUpdatesForm from "./components/SettingsUpdatesForm/SettingsUpdatesForm";
 import SettingsEmailForm from "./components/SettingsEmailForm";
 import SettingsSetupList from "./components/SettingsSetupList";
@@ -365,11 +367,22 @@ const SECTIONS = updateSectionsWithPlugins({
         widget: EmbeddedQuestionListing,
         getHidden: settings => !settings["enable-embedding"],
       },
+      {
+        widget: PremiumEmbeddingLinkWidget,
+        getHidden: settings =>
+          !settings["enable-embedding"] || MetabaseSettings.isEnterprise(),
+      },
     ],
   },
+  license: {
+    name: MetabaseSettings.isPaidPlan() ? t`License and billing` : t`License`,
+    order: 11,
+    component: SettingsLicense,
+    settings: [],
+  },
   caching: {
     name: t`Caching`,
-    order: 11,
+    order: 12,
     settings: [
       {
         key: "enable-query-caching",
diff --git a/frontend/src/metabase/admin/settings/settings.js b/frontend/src/metabase/admin/settings/settings.js
index 808443e707e2e04682161f0baf1e94b579f3822e..a514b1a685a615b18cd4e63afe68537b4aa1b8df 100644
--- a/frontend/src/metabase/admin/settings/settings.js
+++ b/frontend/src/metabase/admin/settings/settings.js
@@ -4,9 +4,7 @@ import {
   handleActions,
   combineReducers,
 } from "metabase/lib/redux";
-
 import { SettingsApi, EmailApi, SlackApi, LdapApi } from "metabase/services";
-
 import { refreshSiteSettings } from "metabase/redux/settings";
 
 // ACITON TYPES AND ACTION CREATORS
diff --git a/frontend/src/metabase/components/TextInput/TextInput.styled.jsx b/frontend/src/metabase/components/TextInput/TextInput.styled.tsx
similarity index 71%
rename from frontend/src/metabase/components/TextInput/TextInput.styled.jsx
rename to frontend/src/metabase/components/TextInput/TextInput.styled.tsx
index e4c7e12911fd050137f7995852a232b8494fc54c..86a4c7b9e72f22d3971dadd8897c88f9e3843332 100644
--- a/frontend/src/metabase/components/TextInput/TextInput.styled.jsx
+++ b/frontend/src/metabase/components/TextInput/TextInput.styled.tsx
@@ -1,5 +1,6 @@
 import styled, { css } from "styled-components";
 import { color } from "metabase/lib/colors";
+import { ColorScheme, Size } from "./TextInput";
 
 const PADDING = {
   sm: "0.5rem",
@@ -17,9 +18,26 @@ const BORDER_COLOR = {
   transparent: () => "transparent",
 };
 
-export const Input = styled.input`
+interface InputProps {
+  colorScheme: ColorScheme;
+  borderRadius: Size;
+  padding: Size;
+  hasClearButton?: boolean;
+  hasIcon?: boolean;
+  invalid?: boolean;
+}
+
+const getBorderColor = (colorScheme: ColorScheme, invalid?: boolean) => {
+  if (invalid) {
+    return color("error");
+  }
+
+  return colorScheme === "transparent" ? "transparent" : color("border");
+};
+
+export const Input = styled.input<InputProps>`
   border: 1px solid ${props =>
-    props.colorScheme === "transparent" ? "transparent" : color("border")};
+    getBorderColor(props.colorScheme, props.invalid)};
   outline: none;
   width: 100%;
   font-size: 1.12em;
@@ -29,6 +47,10 @@ export const Input = styled.input`
   background-color: ${props =>
     props.colorScheme === "transparent" ? "transparent" : color("white")};
 
+  &:disabled {
+    background-color: ${color("bg-light")};
+  }
+
   ${({ borderRadius, padding }) => css`
     border-radius: ${BORDER_RADIUS[borderRadius]};
     padding: ${PADDING[padding]};
diff --git a/frontend/src/metabase/components/TextInput/TextInput.jsx b/frontend/src/metabase/components/TextInput/TextInput.tsx
similarity index 65%
rename from frontend/src/metabase/components/TextInput/TextInput.jsx
rename to frontend/src/metabase/components/TextInput/TextInput.tsx
index 66349a48d135238371b336ad34cc9470152a1cdf..85b069714ae62f009738819df4e92a06c0f555b8 100644
--- a/frontend/src/metabase/components/TextInput/TextInput.jsx
+++ b/frontend/src/metabase/components/TextInput/TextInput.tsx
@@ -1,5 +1,4 @@
 import React, { forwardRef } from "react";
-import PropTypes from "prop-types";
 import { t } from "ttag";
 
 import Icon from "metabase/components/Icon";
@@ -11,21 +10,22 @@ import {
   Input,
 } from "./TextInput.styled";
 
-TextInput.propTypes = {
-  onChange: PropTypes.func.isRequired,
-  placeholder: PropTypes.string,
-  value: PropTypes.string,
-  type: PropTypes.string,
-  autoFocus: PropTypes.bool,
-  className: PropTypes.string,
-  hasClearButton: PropTypes.bool,
-  icon: PropTypes.node,
-  padding: PropTypes.oneOf(["sm", "md"]),
-  borderRadius: PropTypes.oneOf(["sm", "md"]),
-  colorScheme: PropTypes.oneOf(["default", "admin", "transparent"]),
-  hasBorder: PropTypes.bool,
-  innerRef: PropTypes.object,
-};
+export type ColorScheme = "default" | "admin" | "transparent";
+export type Size = "sm" | "md";
+
+type TextInputProps = {
+  value?: string;
+  placeholder?: string;
+  onChange: (value: string) => void;
+  hasClearButton?: boolean;
+  icon?: React.ReactNode;
+  colorScheme?: ColorScheme;
+  autoFocus?: boolean;
+  padding?: Size;
+  borderRadius?: Size;
+  innerRef?: any;
+  invalid?: boolean;
+} & Omit<React.HTMLProps<HTMLInputElement>, "onChange">;
 
 function TextInput({
   value = "",
@@ -40,8 +40,10 @@ function TextInput({
   padding = "md",
   borderRadius = "md",
   innerRef,
+  ref,
+  invalid,
   ...rest
-}) {
+}: TextInputProps) {
   const handleClearClick = () => {
     onChange("");
   };
@@ -63,6 +65,7 @@ function TextInput({
         onChange={e => onChange(e.target.value)}
         padding={padding}
         borderRadius={borderRadius}
+        invalid={invalid}
         {...rest}
       />
 
@@ -75,6 +78,8 @@ function TextInput({
   );
 }
 
-export default forwardRef(function TextInputForwardRef(props, ref) {
-  return <TextInput {...props} innerRef={ref} />;
-});
+export default forwardRef<HTMLInputElement, TextInputProps>(
+  function TextInputForwardRef(props, ref) {
+    return <TextInput {...props} innerRef={ref} />;
+  },
+);
diff --git a/frontend/src/metabase/lib/settings.ts b/frontend/src/metabase/lib/settings.ts
index e68c8aa3cc55a687c873709e2ab3dd425a188f83..80b407151b1324c12a28219e7fe4f6e8a8624526 100644
--- a/frontend/src/metabase/lib/settings.ts
+++ b/frontend/src/metabase/lib/settings.ts
@@ -88,7 +88,9 @@ export type SettingName =
   | "snowplow-enabled"
   | "snowplow-url"
   | "engine-deprecation-notice-version"
-  | "show-database-syncing-modal";
+  | "show-database-syncing-modal"
+  | "premium-embedding-token"
+  | "metabase-store-managed";
 
 type SettingsMap = Record<SettingName, any>; // provides access to Metabase application settings
 
@@ -154,6 +156,10 @@ class Settings {
     return this.get("is-hosted?");
   }
 
+  isStoreManaged(): boolean {
+    return this.get("metabase-store-managed");
+  }
+
   cloudGatewayIps(): string[] {
     return this.get("cloud-gateway-ips") || [];
   }
@@ -202,6 +208,10 @@ class Settings {
     return this.currentVersion() !== this.engineDeprecationNoticeVersion();
   }
 
+  token() {
+    return this.get("premium-embedding-token");
+  }
+
   formattingOptions() {
     const opts = this.get("custom-formatting");
     return opts && opts["type/Temporal"] ? opts["type/Temporal"] : {};
@@ -257,8 +267,8 @@ class Settings {
     return `https://store.metabase.com/${path}`;
   }
 
-  pricingUrl() {
-    return "https://www.metabase.com/pricing/";
+  upgradeUrl() {
+    return "https://www.metabase.com/upgrade/";
   }
 
   newVersionAvailable() {
diff --git a/frontend/src/metabase/plugins/index.js b/frontend/src/metabase/plugins/index.js
index 37f04eb47b8eacb2134c8ba99efd151d1923a77f..36f551313b07aa43e6de65886b57b6086fd2b055 100644
--- a/frontend/src/metabase/plugins/index.js
+++ b/frontend/src/metabase/plugins/index.js
@@ -107,3 +107,7 @@ export const PLUGIN_ADVANCED_PERMISSIONS = {
   addTablePermissionOptions: (permissions, _value) => permissions,
   isBlockPermission: _value => false,
 };
+
+export const PLUGIN_LICENSE_PAGE = {
+  LicenseAndBillingSettings: PluginPlaceholder,
+};
diff --git a/frontend/src/metabase/services.js b/frontend/src/metabase/services.js
index a679a2ae0835d2968e064145368ccb09777c8948..bf007a454e35798dff75f8d69540cffd10c0e27c 100644
--- a/frontend/src/metabase/services.js
+++ b/frontend/src/metabase/services.js
@@ -23,6 +23,10 @@ export const GTAPApi = {
   attributes: GET("/api/mt/user/attributes"),
 };
 
+export const StoreApi = {
+  tokenStatus: GET("/api/premium-features/token/status"),
+};
+
 // Pivot tables need extra data beyond what's described in the MBQL query itself.
 // To fetch that extra data we rely on specific APIs for pivot tables that mirrow the normal endpoints.
 // Those endpoints take the query along with `pivot_rows` and `pivot_cols` to return the subtotal data.
diff --git a/package.json b/package.json
index f406490f072ea5a368d3b4d1b78301cb5c4f7fab..6a115ff926eb07fd5a4d7d6a678bab7ae4d53204 100644
--- a/package.json
+++ b/package.json
@@ -255,6 +255,7 @@
     "dev": "yarn concurrently -n 'backend,frontend,cljs,docs' -c 'blue,green,yellow,magenta' 'clojure -M:run' 'yarn build-hot:js' 'yarn build-hot:cljs' 'yarn docs'",
     "dev-ee": "yarn concurrently -n 'backend,frontend,cljs,docs' -c 'blue,green,yellow,magenta' 'clojure -M:run:ee' 'MB_EDITION=ee yarn build-hot:js' 'MB_EDITION=ee yarn build-hot:cljs' 'yarn docs'",
     "type-check": "yarn && tsc --noEmit",
+    "remove-webpack-cache": "rm -rf ./node_modules/.cache",
     "lint": "yarn lint-eslint && yarn lint-prettier && yarn lint-docs-links && yarn lint-yaml && yarn type-check",
     "lint-eslint": "yarn build-quick:cljs && eslint --ext .js --ext .jsx --rulesdir frontend/lint/eslint-rules --max-warnings 0 enterprise/frontend/src frontend/src frontend/test",
     "lint-prettier": "yarn && prettier -l '{enterprise/,}frontend/**/*.{js,jsx,ts,tsx,css}' || (echo '\nThese files are not formatted correctly. Did you forget to \"yarn prettier\"?' && false)",