From 7711efea7019ce594b17f72325505d5ef194c4ed Mon Sep 17 00:00:00 2001 From: MananTank Date: Wed, 18 Dec 2024 23:54:39 +0000 Subject: [PATCH] [CORE-656] Update Dashboard Team layout (#5798) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem solved CORE-656 * Move the Team analytics from overview page to Analytics tab * Move the changelog to "projects" page and make that the default page to show on /team/ --- ## PR-Codex overview This PR primarily focuses on updating links related to the `thirdweb dashboard`, changing references from project-specific URLs to a more general team URL. Additionally, it refines the `TeamProjectsPage` component and enhances the analytics page structure. ### Detailed summary - Updated links in multiple `.mdx` files to point to `https://thirdweb.com/team` instead of project-specific URLs. - Modified `layout.tsx` to change the path from `projects` to `analytics`. - Enhanced `TeamProjectsPage` to display a message when no projects are created, with a button to create a new project. - Refactored the main page to include the `TeamProjectsPage` component and removed unnecessary analytics content. > ✨ Ask PR-Codex anything about this PR by commenting with `/codex {your question}` --- .../app/team/[team_slug]/(team)/layout.tsx | 4 +- .../src/app/team/[team_slug]/(team)/page.tsx | 335 +----------------- .../[team_slug]/(team)/~/analytics/page.tsx | 316 +++++++++++++++++ .../(team)/~/projects/TeamProjectsPage.tsx | 24 +- .../[team_slug]/(team)/~/projects/page.tsx | 19 - .../src/components/dashboard/Changelog.tsx | 32 +- .../tabs/code/components/code-overview.tsx | 2 +- .../src/app/account/api-keys/access/page.mdx | 2 +- .../src/app/account/api-keys/create/page.mdx | 2 +- .../src/app/account/api-keys/delete/page.mdx | 2 +- .../account/api-keys/edit-services/page.mdx | 2 +- .../src/app/connect/pay/fee-sharing/page.mdx | 2 +- .../guides/build-a-custom-experience/page.mdx | 2 +- .../src/app/connect/quickstart/page.mdx | 2 +- .../deploy-modular-contract/page.mdx | 2 +- .../infrastructure/rpc-edge/overview/page.mdx | 2 +- .../nft-checkout/api-reference/page.mdx | 2 +- .../react-native/v0/getting-started/page.mdx | 2 +- .../app/react/v4/ThirdwebProvider/page.mdx | 2 +- .../app/react/v5/rainbow-kit-migrate/page.mdx | 2 +- 20 files changed, 380 insertions(+), 378 deletions(-) create mode 100644 apps/dashboard/src/app/team/[team_slug]/(team)/~/analytics/page.tsx delete mode 100644 apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/page.tsx diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx index 2cb3232d4f9..fb4ac246844 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/layout.tsx @@ -54,8 +54,8 @@ export default async function TeamLayout(props: { exactMatch: true, }, { - path: `/team/${params.team_slug}/~/projects`, - name: "Projects", + path: `/team/${params.team_slug}/~/analytics`, + name: "Analytics", }, { path: `/team/${params.team_slug}/~/contracts`, diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/page.tsx index 026f703378b..6d55bdbf20d 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/page.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/page.tsx @@ -1,336 +1,33 @@ -import { - getInAppWalletUsage, - getUserOpUsage, - getWalletConnections, - getWalletUsers, -} from "@/api/analytics"; -import { redirect } from "next/navigation"; - -import type { - InAppWalletStats, - WalletStats, - WalletUserStats, -} from "types/analytics"; - -import { - type DurationId, - type Range, - getLastNDaysRange, -} from "components/analytics/date-range-selector"; - -import { type WalletId, getWalletInfo } from "thirdweb/wallets"; -import { AnalyticsHeader } from "../../components/Analytics/AnalyticsHeader"; -import { CombinedBarChartCard } from "../../components/Analytics/CombinedBarChartCard"; -import { EmptyState } from "../../components/Analytics/EmptyState"; -import { PieChartCard } from "../../components/Analytics/PieChartCard"; - +import { getProjects } from "@/api/projects"; import { getTeamBySlug } from "@/api/team"; -import { GenericLoadingPage } from "@/components/blocks/skeletons/GenericLoadingPage"; -import type { Account } from "@3rdweb-sdk/react/hooks/useApi"; -import { getValidAccount } from "app/account/settings/getAccount"; -import { EmptyStateCard } from "app/team/components/Analytics/EmptyStateCard"; -import { Changelog, type ChangelogItem } from "components/dashboard/Changelog"; -import { Suspense } from "react"; -import { TotalSponsoredChartCardUI } from "./_components/TotalSponsoredCard"; - -// revalidate every 5 minutes -export const revalidate = 300; - -type SearchParams = { - usersChart?: string; - from?: string; - to?: string; - type?: string; - interval?: string; -}; +import { Changelog } from "components/dashboard/Changelog"; +import { redirect } from "next/navigation"; +import { TeamProjectsPage } from "./~/projects/TeamProjectsPage"; -export default async function TeamOverviewPage(props: { +export default async function Page(props: { params: Promise<{ team_slug: string }>; - searchParams: Promise; }) { - const changelog = await getChangelog(); - const [params, searchParams] = await Promise.all([ - props.params, - props.searchParams, - ]); - - const account = await getValidAccount(`/team/${params.team_slug}`); + const params = await props.params; const team = await getTeamBySlug(params.team_slug); if (!team) { redirect("/team"); } - const interval = (searchParams.interval as "day" | "week") ?? "week"; - const rangeType = (searchParams.type as DurationId) || "last-120"; - const range: Range = { - from: new Date(searchParams.from ?? getLastNDaysRange("last-120").from), - to: new Date(searchParams.to ?? getLastNDaysRange("last-120").to), - type: rangeType, - }; + const projects = await getProjects(params.team_slug); return ( -
-
- +
+
+

Projects

+
-
- }> - - -
-

- Latest changes -

- -
-
-
- ); -} - -async function OverviewPageContent(props: { - account: Account; - range: Range; - interval: "day" | "week"; - searchParams: SearchParams; -}) { - const { account, range, interval, searchParams } = props; - - const [ - walletConnections, - walletUserStatsTimeSeries, - inAppWalletUsage, - userOpUsageTimeSeries, - userOpUsage, - ] = await Promise.all([ - // Aggregated wallet connections - getWalletConnections({ - accountId: account.id, - from: range.from, - to: range.to, - period: "all", - }), - // Time series data for wallet users - getWalletUsers({ - accountId: account.id, - from: range.from, - to: range.to, - period: interval, - }), - // In-app wallet usage - getInAppWalletUsage({ - accountId: account.id, - from: range.from, - to: range.to, - period: "all", - }), - // User operations usage - getUserOpUsage({ - accountId: account.id, - from: range.from, - to: range.to, - period: interval, - }), - getUserOpUsage({ - accountId: account.id, - from: range.from, - to: range.to, - period: "all", - }), - ]); - - const isEmpty = - !walletUserStatsTimeSeries.some((w) => w.totalUsers !== 0) && - walletConnections.length === 0 && - inAppWalletUsage.length === 0 && - userOpUsage.length === 0; - - if (isEmpty) { - return ; - } - - return ( -
- {walletUserStatsTimeSeries.some((w) => w.totalUsers !== 0) ? ( -
- -
- ) : ( - - )} -
- {walletConnections.length > 0 ? ( - - ) : ( - - )} - {inAppWalletUsage.length > 0 ? ( - - ) : ( - - )} +
+

+ Latest changes +

+
- {userOpUsage.length > 0 ? ( - - ) : ( - - )}
); } - -async function getChangelog() { - const res = await fetch( - "https://thirdweb.ghost.io/ghost/api/content/posts/?key=49c62b5137df1c17ab6b9e46e3&fields=title,url,published_at&filter=tag:changelog&visibility:public&limit=5", - ); - const json = await res.json(); - return json.posts as ChangelogItem[]; -} - -type UserMetrics = { - totalUsers: number; - activeUsers: number; - newUsers: number; - returningUsers: number; -}; - -type TimeSeriesMetrics = UserMetrics & { - date: string; -}; - -function processTimeSeriesData( - userStats: WalletUserStats[], -): TimeSeriesMetrics[] { - const metrics: TimeSeriesMetrics[] = []; - - let cumulativeUsers = 0; - for (const stat of userStats) { - cumulativeUsers += stat.newUsers ?? 0; - metrics.push({ - date: stat.date, - activeUsers: stat.totalUsers ?? 0, - returningUsers: stat.returningUsers ?? 0, - newUsers: stat.newUsers ?? 0, - totalUsers: cumulativeUsers, - }); - } - - return metrics; -} - -function UsersChartCard({ - userStats, - searchParams, -}: { - userStats: WalletUserStats[]; - searchParams?: { [key: string]: string | string[] | undefined }; -}) { - const timeSeriesData = processTimeSeriesData(userStats); - - const chartConfig = { - activeUsers: { label: "Active Users", color: "hsl(var(--chart-1))" }, - totalUsers: { label: "Total Users", color: "hsl(var(--chart-2))" }, - newUsers: { label: "New Users", color: "hsl(var(--chart-3))" }, - returningUsers: { - label: "Returning Users", - color: "hsl(var(--chart-4))", - }, - } as const; - - return ( - - timeSeriesData[timeSeriesData.length - 2]?.[key] - } - // Get the trend from the last two COMPLETE periods - trendFn={(data, key) => - data.filter((d) => (d[key] as number) > 0).length >= 3 - ? ((data[data.length - 2]?.[key] as number) ?? 0) / - ((data[data.length - 3]?.[key] as number) ?? 0) - - 1 - : undefined - } - queryKey="usersChart" - existingQueryParams={searchParams} - /> - ); -} - -async function WalletDistributionCard({ data }: { data: WalletStats[] }) { - const formattedData = await Promise.all( - data - .filter((w) => w.walletType !== "smart" && w.walletType !== "smartWallet") - .map(async (w) => { - const wallet = await getWalletInfo(w.walletType as WalletId).catch( - () => ({ name: w.walletType }), - ); - return { - walletType: w.walletType, - uniqueWalletsConnected: w.uniqueWalletsConnected, - totalConnections: w.totalConnections, - walletName: wallet.name, - }; - }), - ); - - return ( - { - return { - value: uniqueWalletsConnected, - label: walletName, - }; - })} - /> - ); -} - -function AuthMethodDistributionCard({ data }: { data: InAppWalletStats[] }) { - return ( - ({ - value: uniqueWalletsConnected, - label: authenticationMethod, - }))} - /> - ); -} diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/analytics/page.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/analytics/page.tsx new file mode 100644 index 00000000000..1ba33619388 --- /dev/null +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/analytics/page.tsx @@ -0,0 +1,316 @@ +import { + getInAppWalletUsage, + getUserOpUsage, + getWalletConnections, + getWalletUsers, +} from "@/api/analytics"; +import { redirect } from "next/navigation"; + +import type { + InAppWalletStats, + WalletStats, + WalletUserStats, +} from "types/analytics"; + +import { + type DurationId, + type Range, + getLastNDaysRange, +} from "components/analytics/date-range-selector"; + +import { type WalletId, getWalletInfo } from "thirdweb/wallets"; +import { AnalyticsHeader } from "../../../../components/Analytics/AnalyticsHeader"; +import { CombinedBarChartCard } from "../../../../components/Analytics/CombinedBarChartCard"; +import { EmptyState } from "../../../../components/Analytics/EmptyState"; +import { PieChartCard } from "../../../../components/Analytics/PieChartCard"; + +import { getTeamBySlug } from "@/api/team"; +import { GenericLoadingPage } from "@/components/blocks/skeletons/GenericLoadingPage"; +import type { Account } from "@3rdweb-sdk/react/hooks/useApi"; +import { getValidAccount } from "app/account/settings/getAccount"; +import { EmptyStateCard } from "app/team/components/Analytics/EmptyStateCard"; +import { Suspense } from "react"; +import { TotalSponsoredChartCardUI } from "../../_components/TotalSponsoredCard"; + +// revalidate every 5 minutes +export const revalidate = 300; + +type SearchParams = { + usersChart?: string; + from?: string; + to?: string; + type?: string; + interval?: string; +}; + +export default async function TeamOverviewPage(props: { + params: Promise<{ team_slug: string }>; + searchParams: Promise; +}) { + const [params, searchParams] = await Promise.all([ + props.params, + props.searchParams, + ]); + + const account = await getValidAccount(`/team/${params.team_slug}`); + const team = await getTeamBySlug(params.team_slug); + + if (!team) { + redirect("/team"); + } + + const interval = (searchParams.interval as "day" | "week") ?? "week"; + const rangeType = (searchParams.type as DurationId) || "last-120"; + const range: Range = { + from: new Date(searchParams.from ?? getLastNDaysRange("last-120").from), + to: new Date(searchParams.to ?? getLastNDaysRange("last-120").to), + type: rangeType, + }; + + return ( +
+
+ +
+
+ }> + + +
+
+ ); +} + +async function OverviewPageContent(props: { + account: Account; + range: Range; + interval: "day" | "week"; + searchParams: SearchParams; +}) { + const { account, range, interval, searchParams } = props; + + const [ + walletConnections, + walletUserStatsTimeSeries, + inAppWalletUsage, + userOpUsageTimeSeries, + userOpUsage, + ] = await Promise.all([ + // Aggregated wallet connections + getWalletConnections({ + accountId: account.id, + from: range.from, + to: range.to, + period: "all", + }), + // Time series data for wallet users + getWalletUsers({ + accountId: account.id, + from: range.from, + to: range.to, + period: interval, + }), + // In-app wallet usage + getInAppWalletUsage({ + accountId: account.id, + from: range.from, + to: range.to, + period: "all", + }), + // User operations usage + getUserOpUsage({ + accountId: account.id, + from: range.from, + to: range.to, + period: interval, + }), + getUserOpUsage({ + accountId: account.id, + from: range.from, + to: range.to, + period: "all", + }), + ]); + + const isEmpty = + !walletUserStatsTimeSeries.some((w) => w.totalUsers !== 0) && + walletConnections.length === 0 && + inAppWalletUsage.length === 0 && + userOpUsage.length === 0; + + if (isEmpty) { + return ; + } + + return ( +
+ {walletUserStatsTimeSeries.some((w) => w.totalUsers !== 0) ? ( +
+ +
+ ) : ( + + )} +
+ {walletConnections.length > 0 ? ( + + ) : ( + + )} + {inAppWalletUsage.length > 0 ? ( + + ) : ( + + )} +
+ {userOpUsage.length > 0 ? ( + + ) : ( + + )} +
+ ); +} + +type UserMetrics = { + totalUsers: number; + activeUsers: number; + newUsers: number; + returningUsers: number; +}; + +type TimeSeriesMetrics = UserMetrics & { + date: string; +}; + +function processTimeSeriesData( + userStats: WalletUserStats[], +): TimeSeriesMetrics[] { + const metrics: TimeSeriesMetrics[] = []; + + let cumulativeUsers = 0; + for (const stat of userStats) { + cumulativeUsers += stat.newUsers ?? 0; + metrics.push({ + date: stat.date, + activeUsers: stat.totalUsers ?? 0, + returningUsers: stat.returningUsers ?? 0, + newUsers: stat.newUsers ?? 0, + totalUsers: cumulativeUsers, + }); + } + + return metrics; +} + +function UsersChartCard({ + userStats, + searchParams, +}: { + userStats: WalletUserStats[]; + searchParams?: { [key: string]: string | string[] | undefined }; +}) { + const timeSeriesData = processTimeSeriesData(userStats); + + const chartConfig = { + activeUsers: { label: "Active Users", color: "hsl(var(--chart-1))" }, + totalUsers: { label: "Total Users", color: "hsl(var(--chart-2))" }, + newUsers: { label: "New Users", color: "hsl(var(--chart-3))" }, + returningUsers: { + label: "Returning Users", + color: "hsl(var(--chart-4))", + }, + } as const; + + return ( + + timeSeriesData[timeSeriesData.length - 2]?.[key] + } + // Get the trend from the last two COMPLETE periods + trendFn={(data, key) => + data.filter((d) => (d[key] as number) > 0).length >= 3 + ? ((data[data.length - 2]?.[key] as number) ?? 0) / + ((data[data.length - 3]?.[key] as number) ?? 0) - + 1 + : undefined + } + queryKey="usersChart" + existingQueryParams={searchParams} + /> + ); +} + +async function WalletDistributionCard({ data }: { data: WalletStats[] }) { + const formattedData = await Promise.all( + data + .filter((w) => w.walletType !== "smart" && w.walletType !== "smartWallet") + .map(async (w) => { + const wallet = await getWalletInfo(w.walletType as WalletId).catch( + () => ({ name: w.walletType }), + ); + return { + walletType: w.walletType, + uniqueWalletsConnected: w.uniqueWalletsConnected, + totalConnections: w.totalConnections, + walletName: wallet.name, + }; + }), + ); + + return ( + { + return { + value: uniqueWalletsConnected, + label: walletName, + }; + })} + /> + ); +} + +function AuthMethodDistributionCard({ data }: { data: InAppWalletStats[] }) { + return ( + ({ + value: uniqueWalletsConnected, + label: authenticationMethod, + }))} + /> + ); +} diff --git a/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/TeamProjectsPage.tsx b/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/TeamProjectsPage.tsx index 79a538cd8d1..b7ee115f177 100644 --- a/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/TeamProjectsPage.tsx +++ b/apps/dashboard/src/app/team/[team_slug]/(team)/~/projects/TeamProjectsPage.tsx @@ -19,7 +19,7 @@ import { } from "@/components/ui/select"; import { useDashboardRouter } from "@/lib/DashboardRouter"; import { LazyCreateAPIKeyDialog } from "components/settings/ApiKeys/Create/LazyCreateAPIKeyDialog"; -import { ChevronDownIcon, SearchIcon } from "lucide-react"; +import { ChevronDownIcon, PlusIcon, SearchIcon } from "lucide-react"; import Link from "next/link"; import { useState } from "react"; @@ -58,9 +58,7 @@ export function TeamProjectsPage(props: { } return ( -
-
- +
{/* Filters + Add New */}
@@ -77,11 +75,21 @@ export function TeamProjectsPage(props: { {/* Projects */} {projectsToShow.length === 0 ? ( -
- No projects found +
+
+

No projects created

+ +
) : ( -
+
{projectsToShow.map((project) => { return ( )} -
- ; -}) { - const params = await props.params; - const team = await getTeamBySlug(params.team_slug); - - if (!team) { - redirect("/team"); - } - - const projects = await getProjects(params.team_slug); - - return ; -} diff --git a/apps/dashboard/src/components/dashboard/Changelog.tsx b/apps/dashboard/src/components/dashboard/Changelog.tsx index c618c59239f..53da85247af 100644 --- a/apps/dashboard/src/components/dashboard/Changelog.tsx +++ b/apps/dashboard/src/components/dashboard/Changelog.tsx @@ -1,20 +1,16 @@ -import { Skeleton } from "@/components/ui/skeleton"; -import { formatDistance } from "date-fns/formatDistance"; +import { formatDistance } from "date-fns"; import { ArrowRightIcon } from "lucide-react"; import Link from "next/link"; -import { ClientOnly } from "../ClientOnly/ClientOnly"; -export interface ChangelogItem { +type ChangelogItem = { published_at: string; title: string; url: string; -} +}; -interface ChangelogProps { - changelog: ChangelogItem[]; -} +export async function Changelog() { + const changelog = await getChangelog(); -export const Changelog: React.FC = ({ changelog }) => { return (
{changelog.map((item) => ( @@ -31,11 +27,9 @@ export const Changelog: React.FC = ({ changelog }) => { {item.title}
- }> - {formatDistance(new Date(item.published_at), Date.now(), { - addSuffix: true, - })} - + {formatDistance(new Date(item.published_at), Date.now(), { + addSuffix: true, + })}
@@ -49,4 +43,12 @@ export const Changelog: React.FC = ({ changelog }) => {
); -}; +} + +async function getChangelog() { + const res = await fetch( + "https://thirdweb.ghost.io/ghost/api/content/posts/?key=49c62b5137df1c17ab6b9e46e3&fields=title,url,published_at&filter=tag:changelog&visibility:public&limit=10", + ); + const json = await res.json(); + return json.posts as ChangelogItem[]; +} diff --git a/apps/dashboard/src/contract-ui/tabs/code/components/code-overview.tsx b/apps/dashboard/src/contract-ui/tabs/code/components/code-overview.tsx index cb113e59227..5833967e979 100644 --- a/apps/dashboard/src/contract-ui/tabs/code/components/code-overview.tsx +++ b/apps/dashboard/src/contract-ui/tabs/code/components/code-overview.tsx @@ -753,7 +753,7 @@ export const CodeOverview: React.FC = ({ thirdweb's infrastructure services. If you don't have any API keys yet you can create one by creating a project for free from the{" "} - + dashboard . diff --git a/apps/portal/src/app/account/api-keys/access/page.mdx b/apps/portal/src/app/account/api-keys/access/page.mdx index f80c63d05d4..8bed4b23eab 100644 --- a/apps/portal/src/app/account/api-keys/access/page.mdx +++ b/apps/portal/src/app/account/api-keys/access/page.mdx @@ -26,7 +26,7 @@ To modify the allowed Domain Id or Bundle Ids: -Go to **[thirdweb dashboard](https://thirdweb.com/team/~/~/projects)** +Go to **[thirdweb dashboard](https://thirdweb.com/team)** diff --git a/apps/portal/src/app/account/api-keys/create/page.mdx b/apps/portal/src/app/account/api-keys/create/page.mdx index 95545588ee7..b6c290a187a 100644 --- a/apps/portal/src/app/account/api-keys/create/page.mdx +++ b/apps/portal/src/app/account/api-keys/create/page.mdx @@ -17,7 +17,7 @@ export const metadata = createMetadata({ -Log in to the dashboard and go to your **[Team projects page](https://thirdweb.com/team/~/~/projects)** +Log in to the dashboard and go to your **[Team projects page](https://thirdweb.com/team)** diff --git a/apps/portal/src/app/account/api-keys/delete/page.mdx b/apps/portal/src/app/account/api-keys/delete/page.mdx index 0c785f55a24..dfa811f8179 100644 --- a/apps/portal/src/app/account/api-keys/delete/page.mdx +++ b/apps/portal/src/app/account/api-keys/delete/page.mdx @@ -20,7 +20,7 @@ Deleting an API key will invalidate it, making it no longer usable. - Go to **[your team's projects page](https://thirdweb.com/team/~/~/projects/)** on the dashboard. + Go to **[your team's projects page](https://thirdweb.com/team)** on the dashboard. diff --git a/apps/portal/src/app/account/api-keys/edit-services/page.mdx b/apps/portal/src/app/account/api-keys/edit-services/page.mdx index 29e0b0dcce6..dc28d42acee 100644 --- a/apps/portal/src/app/account/api-keys/edit-services/page.mdx +++ b/apps/portal/src/app/account/api-keys/edit-services/page.mdx @@ -23,7 +23,7 @@ All services on API keys are enabled by default. If you want to disable any serv -Go to **[your team's projects page](https://thirdweb.com/team/~/~/projects)** on the dashboard. +Go to **[your team's projects page](https://thirdweb.com/team)** on the dashboard. diff --git a/apps/portal/src/app/connect/pay/fee-sharing/page.mdx b/apps/portal/src/app/connect/pay/fee-sharing/page.mdx index 895d963e694..25633d98867 100644 --- a/apps/portal/src/app/connect/pay/fee-sharing/page.mdx +++ b/apps/portal/src/app/connect/pay/fee-sharing/page.mdx @@ -18,6 +18,6 @@ For example, if a user purchases $100 worth of Polygon through your application, Plase note that fee sharing only applies to fees collected through swaps and bridges. Fiat purchases do not currently qualify for fee sharing. -To participate in fee sharing, all you need to do is set a recipient address in your dashboard. Your recipient address can be configured in your dashboard by navigating to your Team > Project > Connect > Pay in [thirdweb dashboard](https://www.thirdweb.com/team/~/~/projects). +To participate in fee sharing, all you need to do is set a recipient address in your dashboard. Your recipient address can be configured in your dashboard by navigating to your Team > Project > Connect > Pay in [thirdweb dashboard](https://www.thirdweb.com/team). diff --git a/apps/portal/src/app/connect/pay/guides/build-a-custom-experience/page.mdx b/apps/portal/src/app/connect/pay/guides/build-a-custom-experience/page.mdx index 497bc76f64c..184461922bf 100644 --- a/apps/portal/src/app/connect/pay/guides/build-a-custom-experience/page.mdx +++ b/apps/portal/src/app/connect/pay/guides/build-a-custom-experience/page.mdx @@ -41,7 +41,7 @@ In this guide, we'll show you how to purchase 0.01 Base ETH from USD in Typescri /> -Log in to the [thirdweb dashboard](https://thirdweb.com/team/~/~/projects). Click on Create New > Project to get your **Client ID**. You'll need your Client ID to interact with the Connect SDK. +Log in to the [thirdweb dashboard](https://thirdweb.com/team). Click on Create New > Project to get your **Client ID**. You'll need your Client ID to interact with the Connect SDK. diff --git a/apps/portal/src/app/connect/quickstart/page.mdx b/apps/portal/src/app/connect/quickstart/page.mdx index 774477e7ca4..40d4efd165b 100644 --- a/apps/portal/src/app/connect/quickstart/page.mdx +++ b/apps/portal/src/app/connect/quickstart/page.mdx @@ -17,7 +17,7 @@ npm i thirdweb -Log in to the [thirdweb dashboard](https://thirdweb.com/team/~/~/projects). Create a new project to get your **Client ID**. +Log in to the [thirdweb dashboard](https://thirdweb.com/team). Create a new project to get your **Client ID**. diff --git a/apps/portal/src/app/contracts/modular-contracts/get-started/deploy-modular-contract/page.mdx b/apps/portal/src/app/contracts/modular-contracts/get-started/deploy-modular-contract/page.mdx index bf48df08d1d..28a391bb75c 100644 --- a/apps/portal/src/app/contracts/modular-contracts/get-started/deploy-modular-contract/page.mdx +++ b/apps/portal/src/app/contracts/modular-contracts/get-started/deploy-modular-contract/page.mdx @@ -34,7 +34,7 @@ as this guide will build on top of those previous guides. -Go to the [thirdweb Dashboard](https://thirdweb.com/team/~/~/projects), Create a new Project to obtain API Key +Go to the [thirdweb Dashboard](https://thirdweb.com/team), Create a new Project to obtain API Key diff --git a/apps/portal/src/app/infrastructure/rpc-edge/overview/page.mdx b/apps/portal/src/app/infrastructure/rpc-edge/overview/page.mdx index d816ee4a568..0986befbbe4 100644 --- a/apps/portal/src/app/infrastructure/rpc-edge/overview/page.mdx +++ b/apps/portal/src/app/infrastructure/rpc-edge/overview/page.mdx @@ -21,7 +21,7 @@ Remote Procedure Call (RPC) Edge provides reliable access to querying data and i By default, we provide publicly available RPCs for over 900+ EVM Networks. [View the default RPC endpoints](https://thirdweb.com/chainlist) for each supported chain. - To use RPC Edge with other tools like Anvil, take a chain's [public RPC endpoint](https://thirdweb.com/chainlist) and attach your app's client ID from Project > Settings page in [dashboard](https://thirdweb.com/team/~/~/projects) `https://.rpc.thirdweb.com/`. + To use RPC Edge with other tools like Anvil, take a chain's [public RPC endpoint](https://thirdweb.com/chainlist) and attach your app's client ID from Project > Settings page in [dashboard](https://thirdweb.com/team) `https://.rpc.thirdweb.com/`. #### Features diff --git a/apps/portal/src/app/payments/nft-checkout/api-reference/page.mdx b/apps/portal/src/app/payments/nft-checkout/api-reference/page.mdx index a04ffaa0886..4b1e7ebf000 100644 --- a/apps/portal/src/app/payments/nft-checkout/api-reference/page.mdx +++ b/apps/portal/src/app/payments/nft-checkout/api-reference/page.mdx @@ -12,7 +12,7 @@ The Payments API enables all the functionalities needed to create checkouts. [View the full API reference.](https://redocly.github.io/redoc/?url=https://payments.thirdweb.com/api/doc) You must use an API Secret Key to make authenticated calls. These calls should be -made from your backend. [Create an API Key by creating a project from your thirdweb dashboard.](https://thirdweb.com/team/~/~/projects) +made from your backend. [Create an API Key by creating a project from your thirdweb dashboard.](https://thirdweb.com/team) Provide your secret key as a header: `x-secret-key: your_api_secret_key` diff --git a/apps/portal/src/app/react-native/v0/getting-started/page.mdx b/apps/portal/src/app/react-native/v0/getting-started/page.mdx index 4068ab8d95b..ce2c1052585 100644 --- a/apps/portal/src/app/react-native/v0/getting-started/page.mdx +++ b/apps/portal/src/app/react-native/v0/getting-started/page.mdx @@ -18,7 +18,7 @@ Our SDK uses a [Provider Pattern](https://flexiple.com/react/provider-pattern-wi You will require an API key to use thirdweb's infrastructure services with the SDK. -you need to first obtain an API key from the [dashboard](https://thirdweb.com/team/~/~/projects) by creating a new project and then copy the "Client ID" and pass it to the `ThirdwebPovider` as the `clientId` prop. +you need to first obtain an API key from the [dashboard](https://thirdweb.com/team) by creating a new project and then copy the "Client ID" and pass it to the `ThirdwebPovider` as the `clientId` prop. diff --git a/apps/portal/src/app/react/v4/ThirdwebProvider/page.mdx b/apps/portal/src/app/react/v4/ThirdwebProvider/page.mdx index dfe93c6f24b..1807d065f1e 100644 --- a/apps/portal/src/app/react/v4/ThirdwebProvider/page.mdx +++ b/apps/portal/src/app/react/v4/ThirdwebProvider/page.mdx @@ -26,7 +26,7 @@ The `ThirdwebProvider` is a wrapper component that provides access to all of the You will require an API key to use thirdweb's infrastructure services with the SDK. -you need to first obtain an API key from the [dashboard](https://thirdweb.com/team/~/~/projects) by creating a new project and then copy the "Client ID" and pass it to the `ThirdwebProvider` as the `clientId` prop. +you need to first obtain an API key from the [dashboard](https://thirdweb.com/team) by creating a new project and then copy the "Client ID" and pass it to the `ThirdwebProvider` as the `clientId` prop. diff --git a/apps/portal/src/app/react/v5/rainbow-kit-migrate/page.mdx b/apps/portal/src/app/react/v5/rainbow-kit-migrate/page.mdx index 07427244585..720652c0d66 100644 --- a/apps/portal/src/app/react/v5/rainbow-kit-migrate/page.mdx +++ b/apps/portal/src/app/react/v5/rainbow-kit-migrate/page.mdx @@ -85,7 +85,7 @@ Learn how to migrate to thirdweb's ConnectButton component from [RainbowKit](htt ); }; ``` - Get a free client ID to use in your application by creating a project in [thirdweb's dashboard](https://thirdweb.com/team/~/~/projects). + Get a free client ID to use in your application by creating a project in [thirdweb's dashboard](https://thirdweb.com/team). To customize your ConnectButton component, view the cheatsheet below or [view the customization documentation](https://portal.thirdweb.com/connect/sign-in/customization).