From d10fc24fbb7d1f9d28280bb9c7f44a7e0d0a1c27 Mon Sep 17 00:00:00 2001
From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com>
Date: Mon, 1 Sep 2025 17:44:39 +0100
Subject: [PATCH 1/3] feat: Pricing update

---
 .../src/routes/(window-chrome)/upgrade.tsx    | 1128 ++++++++---------
 apps/desktop/src/utils/plans.ts               |    4 +-
 apps/web/components/pages/FaqPage.tsx         |  104 +-
 .../pages/seo/LoomAlternativePage.tsx         |  348 ++---
 apps/web/public/llms.txt                      |    2 +-
 packages/ui-solid/src/auto-imports.d.ts       |    8 +-
 packages/utils/src/constants/plans.ts         |    4 +-
 7 files changed, 799 insertions(+), 799 deletions(-)

diff --git a/apps/desktop/src/routes/(window-chrome)/upgrade.tsx b/apps/desktop/src/routes/(window-chrome)/upgrade.tsx
index 50479a39e3..58d7ce85c9 100644
--- a/apps/desktop/src/routes/(window-chrome)/upgrade.tsx
+++ b/apps/desktop/src/routes/(window-chrome)/upgrade.tsx
@@ -14,14 +14,14 @@ import { authStore } from "../../store";
 import { Dialog, DialogContent, Input } from "../editor/ui";
 
 const proFeatures = [
-	"Commercial License Included",
-	"Unlimited cloud storage & Shareable links",
-	"Connect custom S3 storage bucket",
-	"Advanced teams features",
-	"Unlimited views",
-	"Password protected videos",
-	"Advanced analytics",
-	"Priority support",
+  "Commercial License Included",
+  "Unlimited cloud storage & Shareable links",
+  "Connect custom S3 storage bucket",
+  "Advanced teams features",
+  "Unlimited views",
+  "Password protected videos",
+  "Advanced analytics",
+  "Priority support",
 ];
 
 import { RuntimeLoader } from "@rive-app/canvas";
@@ -31,566 +31,566 @@ import { createSignInMutation } from "~/utils/auth";
 RuntimeLoader.setWasmUrl(riveWASMResource);
 
 export default function Page() {
-	const [isProAnnual, setIsProAnnual] = createSignal(true);
-	const [isCommercialAnnual, setIsCommercialAnnual] = createSignal(true);
-	const [upgradeComplete, setUpgradeComplete] = createSignal(false);
-	const [loading, setLoading] = createSignal(false);
-	const signIn = createSignInMutation();
-	const license = createLicenseQuery();
-	const [openLicenseDialog, setOpenLicenseDialog] = createSignal(false);
-
-	const resetLicense = createMutation(() => ({
-		mutationFn: async () => {
-			const generalSettings = await generalSettingsStore.get();
-			if (
-				!generalSettings?.instanceId ||
-				!license.data ||
-				license.data.type !== "commercial"
-			) {
-				throw new Error("No instance ID or valid commercial license found");
-			}
-
-			const resp = await licenseApiClient.activateCommercialLicense({
-				headers: {
-					licensekey: license.data.licenseKey,
-					instanceid: generalSettings.instanceId,
-				},
-				body: { reset: true },
-			});
-
-			if (resp.status !== 200) {
-				if (
-					typeof resp.body === "object" &&
-					resp.body &&
-					"message" in resp.body
-				)
-					throw resp.body.message;
-				throw new Error((resp.body as any).toString());
-			}
-		},
-		onSuccess: async () => {
-			await generalSettingsStore.set({
-				commercialLicense: undefined,
-			});
-			license.refetch();
-		},
-	}));
-
-	const openCheckoutInExternalBrowser = async () => {
-		console.log("Opening checkout in external browser");
-		setLoading(true);
-
-		try {
-			const auth = await authStore.get();
-
-			console.log({ auth });
-			if (!auth) {
-				console.log("No auth found, starting sign in flow");
-				await signIn.mutateAsync(new AbortController());
-			}
-
-			const planId = getProPlanId(isProAnnual() ? "yearly" : "monthly");
-			console.log("Getting checkout URL for plan:", planId);
-			const response = await apiClient.desktop.getProSubscribeURL({
-				body: { priceId: planId },
-				headers: await protectedHeaders(),
-			});
-
-			if (response.status === 200) {
-				console.log("Opening checkout URL in external browser");
-				commands.openExternalLink(response.body.url);
-				console.log("Minimizing upgrade window");
-				const window = await Window.getByLabel("upgrade");
-				if (window) await window.minimize();
-			} else {
-				console.error("Failed to get checkout URL, status:", response.status);
-			}
-		} catch (error) {
-			console.error("Error getting checkout URL:", error);
-		} finally {
-			setLoading(false);
-		}
-	};
-
-	const openCommercialCheckout = createMutation(() => ({
-		mutationFn: async () => {
-			const resp = await licenseApiClient.createCommercialCheckoutUrl({
-				body: { type: isCommercialAnnual() ? "yearly" : "lifetime" },
-			});
-
-			if (resp.status === 200) {
-				console.log("Opening checkout URL in external browser");
-				commands.openExternalLink(resp.body.url);
-				console.log("Minimizing upgrade window");
-				const window = await Window.getByLabel("upgrade");
-				if (window) {
-					await window.minimize();
-				}
-			} else {
-				throw resp.body;
-			}
-		},
-	}));
-
-	// onMount(async () => {
-	//   console.log("Component mounted");
-	//   const unsubscribeDeepLink = await onOpenUrl(async (urls) => {
-	//     console.log("Deep link received:", urls);
-	//     const isDevMode = import.meta.env.VITE_ENVIRONMENT === "development";
-	//     if (isDevMode) {
-	//       console.log("In dev mode, ignoring deep link");
-	//       return;
-	//     }
-
-	//     for (const url of urls) {
-	//       if (!url.includes("token=")) {
-	//         console.log("URL does not contain token, skipping");
-	//         return;
-	//       }
-
-	//       console.log("Processing auth URL");
-	//       const urlObject = new URL(url);
-	//       const token = urlObject.searchParams.get("token");
-	//       const user_id = urlObject.searchParams.get("user_id");
-	//       const expires = Number(urlObject.searchParams.get("expires"));
-
-	//       if (!token || !expires || !user_id) {
-	//         console.error("Invalid signin params");
-	//         throw new Error("Invalid signin params");
-	//       }
-
-	//       console.log("Setting auth store with new credentials");
-	//       const existingAuth = await authStore.get();
-	//       await authStore.set({
-	//         token,
-	//         user_id,
-	//         expires,
-	//         intercom_hash: existingAuth?.intercom_hash ?? "",
-	//         plan: {
-	//           upgraded: false,
-	//           last_checked: 0,
-	//           manual: existingAuth?.plan?.manual ?? false,
-	//         },
-	//       });
-
-	//       console.log("Identifying user in analytics");
-	//       identifyUser(user_id);
-	//       console.log("Tracking sign in event");
-	//       trackEvent("user_signed_in", { platform: "desktop" });
-
-	//       console.log("Reopening upgrade window");
-	//       await commands.showWindow("Upgrade");
-
-	//       console.log("Waiting for window to be ready");
-	//       await new Promise((resolve) => setTimeout(resolve, 500));
-
-	//       console.log("Getting upgrade window reference");
-	//       const upgradeWindow = await Window.getByLabel("upgrade");
-	//       if (upgradeWindow) {
-	//         try {
-	//           console.log("Setting focus on upgrade window");
-	//           await upgradeWindow.show();
-	//           await upgradeWindow.setFocus();
-	//         } catch (e) {
-	//           console.error("Failed to focus upgrade window:", e);
-	//         }
-	//       }
-
-	//       console.log("Getting checkout URL");
-	//       const planId = getProPlanId(isProAnnual() ? "yearly" : "monthly");
-	//       const response = await apiClient.desktop.getProSubscribeURL({
-	//         body: { priceId: planId },
-	//         headers: await protectedHeaders(),
-	//       });
-
-	//       if (response.status === 200) {
-	//         console.log("Opening checkout URL in external browser");
-	//         commands.openExternalLink(response.body.url);
-	//         console.log("Minimizing upgrade window");
-	//         if (upgradeWindow) {
-	//           await upgradeWindow.minimize();
-	//         }
-	//       }
-	//     }
-	//   });
-
-	//   onCleanup(() => {
-	//     console.log("Cleaning up deep link listener");
-	//     unsubscribeDeepLink();
-	//   });
-
-	//   console.log("Setting up upgrade status check interval");
-	//   const interval = setInterval(async () => {
-	//     console.log("Checking upgrade status");
-	//     const result = await commands.checkUpgradedAndUpdate();
-	//     if (result) {
-	//       console.log("Upgrade complete");
-	//       setUpgradeComplete(true);
-	//     }
-	//   }, 5000);
-	//   onCleanup(() => {
-	//     console.log("Cleaning up upgrade status check interval");
-	//     clearInterval(interval);
-	//   });
-	// });
-
-	const { rive: CommercialRive, RiveComponent: Commercial } = createRive(
-		() => ({
-			src: PricingRive,
-			autoplay: true,
-			artboard: "commercial",
-			animations: ["card-stack"],
-		}),
-	);
-
-	const { rive: ProRive, RiveComponent: Pro } = createRive(() => ({
-		src: PricingRive,
-		autoplay: true,
-		artboard: "pro",
-		animations: ["items-coming-in"],
-	}));
-
-	return (
-		<div class="flex relative flex-col justify-center items-center p-5 mx-auto w-full h-full">
-			{upgradeComplete() && (
-				<div class="flex justify-center items-center h-full bg-opacity-75">
-					<div class="relative z-10 p-6 text-center bg-white rounded-lg shadow-lg">
-						<h2 class="mb-4 text-2xl font-bold">Upgrade complete</h2>
-						<p class="mb-4 text-sm text-gray-10">
-							You can now close this window - thank you for upgrading!
-						</p>
-						<Button
-							onClick={() => {
-								console.log("Closing window after upgrade");
-								const window = getCurrentWindow();
-								window.close();
-							}}
-							variant="primary"
-							size="lg"
-						>
-							Close window
-						</Button>
-					</div>
-				</div>
-			)}
-			{!upgradeComplete() &&
-				(license.data?.type === "commercial" ? (
-					<div class="p-8 mx-auto w-full max-w-[700px] rounded-xl border shadow-sm bg-gray-2 border-gray-3">
-						<div class="space-y-6">
-							<div class="flex flex-col items-center mb-6 text-center">
-								<h3 class="text-2xl font-medium">Commercial License</h3>
-								<p class="text-sm text-gray-11">
-									Your license details for Cap commercial use
-								</p>
-							</div>
-
-							<div class="space-y-6">
-								<div>
-									<label class="block mb-2 text-sm text-gray-12">
-										License Key
-									</label>
-									<p class="overflow-x-auto p-3 font-mono text-xs whitespace-pre-wrap break-all rounded-lg border border-gray-4 text-gray-9 bg-gray-3">
-										{license.data.licenseKey}
-									</p>
-								</div>
-
-								<Show when={license.data.expiryDate}>
-									{(expiryDate) => (
-										<div class="space-y-1">
-											<label class="text-sm text-gray-12">Expires</label>
-											<p class="text-gray-10">
-												{new Date(expiryDate()).toLocaleDateString(undefined, {
-													year: "numeric",
-													month: "long",
-													day: "numeric",
-												})}
-											</p>
-										</div>
-									)}
-								</Show>
-
-								<div class="flex flex-col items-center pt-6 border-t border-gray-3">
-									<Button
-										variant="destructive"
-										disabled={resetLicense.isPending}
-										onClick={() => {
-											resetLicense.mutate();
-										}}
-									>
-										{resetLicense.isPending
-											? "Deactivating..."
-											: "Deactivate License"}
-									</Button>
-								</div>
-							</div>
-						</div>
-					</div>
-				) : (
-					<>
-						<div class="text-center">
-							<h1 class="text-4xl md:text-4xl mb-6 tracking-[-.05em] font-medium text-[--text-primary]">
-								Early Adopter Pricing
-							</h1>
-						</div>
-						<div class="flex gap-4 w-full">
-							<div
-								onMouseEnter={() => {
-									const riveInstance = CommercialRive();
-									if (riveInstance) {
-										// Stop any current animations first
-										riveInstance.stop();
-										// Play the enter animation
-										riveInstance.play("cards");
-									}
-								}}
-								onMouseLeave={() => {
-									const riveInstance = CommercialRive();
-									if (riveInstance) {
-										// Stop any current animations first
-										riveInstance.stop();
-										// Play the leave animation
-										riveInstance.play("card-stack");
-									}
-								}}
-								class="flex flex-col flex-1 justify-between p-3 h-[700px ] bg-gray-3 rounded-2xl border border-gray-3 shadow-sm text-card-foreground md:p-3"
-							>
-								<div class="space-y-5">
-									<div class="flex flex-col gap-6 items-center">
-										<Commercial class="w-[250px]" />
-										<div class="space-y-1 text-center">
-											<h3 class="text-2xl font-medium tracking-tight leading-5">
-												Commercial License
-											</h3>
-											<p class="mt-2 text-sm text-[--text-tertiary]">
-												For commercial use
-											</p>
-										</div>
-										<div class="flex flex-col justify-center items-center">
-											<h3 class="text-4xl leading-6">
-												{isCommercialAnnual() ? "$29" : "$58"}
-												<span class="text-gray-11 text-[16px]">.00 /</span>
-											</h3>
-											{isCommercialAnnual() && (
-												<p class="text-[16px] font-medium text-gray-11">
-													billed annually
-												</p>
-											)}
-											{!isCommercialAnnual() && (
-												<p class="text-[16px] font-medium text-gray-11">
-													one-time payment
-												</p>
-											)}
-										</div>
-										<div
-											onClick={() => setIsCommercialAnnual((v) => !v)}
-											class="px-3 py-2 text-center rounded-full border border-transparent transition-all duration-200 cursor-pointer bg-gray-5 hover:border-gray-400"
-										>
-											<p class="text-xs text-gray-12">
-												Switch to {isCommercialAnnual() ? "lifetime" : "yearly"}
-												:{" "}
-												<span class="font-medium">
-													{isCommercialAnnual() ? "$58" : "$29"}
-												</span>
-											</p>
-										</div>
-										<ul class="flex flex-col gap-2 justify-center list-none">
-											{[
-												"Commercial Use of Cap Recorder + Editor",
-												"Community Support",
-												"Local-only features",
-												"Perpetual license option",
-											].map((feature) => (
-												<li class="flex justify-start items-center">
-													<div class="flex justify-center items-center p-0 m-0 w-6 h-6">
-														<IconLucideCheck class="w-4 h-4 text-[--text-primary]" />
-													</div>
-													<span class="ml-1 text-[0.9rem] text-[--text-primary]">
-														{feature}
-													</span>
-												</li>
-											))}
-										</ul>
-									</div>
-								</div>
-								<ActivateLicenseDialog
-									open={openLicenseDialog}
-									onOpenChange={setOpenLicenseDialog}
-								/>
-								<div class="flex flex-col gap-4 items-center">
-									<Button
-										onClick={() => openCommercialCheckout.mutate()}
-										disabled={openCommercialCheckout.isPending}
-										variant="dark"
-										class="w-full !rounded-full !h-[48px] text-lg font-medium"
-										size="lg"
-									>
-										{openCommercialCheckout.isPending
-											? "Loading..."
-											: "Purchase License"}
-									</Button>
-									<p
-										onClick={() => setOpenLicenseDialog(true)}
-										class="mb-2 text-sm transition-colors cursor-pointer text-gray-11 hover:text-gray-12"
-									>
-										Already have a license key?
-									</p>
-								</div>
-							</div>
-
-							{/* Cap Pro */}
-							<div
-								onMouseEnter={() => {
-									const riveInstance = ProRive();
-									if (riveInstance) {
-										// Stop any current animations first
-										riveInstance.stop();
-										// Play the enter animation
-										riveInstance.play("items-coming-out");
-									}
-								}}
-								onMouseLeave={() => {
-									const riveInstance = ProRive();
-									if (riveInstance) {
-										// Stop any current animations first
-										riveInstance.stop();
-										// Play the leave animation
-										riveInstance.play("items-coming-in");
-									}
-								}}
-								class="flex-grow p-3 h-[700px] flex-1 bg-gray-12 rounded-2xl border shadow-sm text-card-foreground md:p-3"
-							>
-								<div class="flex flex-col justify-between space-y-5 h-full">
-									<div class="flex flex-col gap-6 items-center px-6">
-										<Pro class="w-[250px]" />
-										<div class="space-y-1 text-center">
-											<h3 class="text-2xl font-medium tracking-tight leading-5 text-gray-1">
-												Cap Pro
-											</h3>
-											<p class="text-[0.875rem] text-gray-9">
-												For professional use and teams.
-											</p>
-										</div>
-										<div class="flex flex-col justify-center items-center">
-											<h3 class="text-4xl leading-6 text-gray-1">
-												{isProAnnual() ? "$6" : "$9"}
-												<span class="text-gray-10 text-[16px]">.00 /</span>
-											</h3>
-											{isProAnnual() && (
-												<p class="text-[16px] font-medium text-gray-9">
-													per user, billed annually
-												</p>
-											)}
-											{!isProAnnual() && (
-												<p class="text-[16px] font-medium text-gray-9">
-													per user, billed monthly
-												</p>
-											)}
-										</div>
-										<div
-											onClick={() => setIsProAnnual((v) => !v)}
-											class="px-3 py-2 text-center bg-blue-500 rounded-full border border-transparent transition-all duration-200 cursor-pointer hover:border-blue-400"
-										>
-											<p class="text-xs text-solid-white">
-												Switch to {isProAnnual() ? "monthly" : "yearly"}:{" "}
-												<span class="font-medium">
-													{isProAnnual()
-														? "$9 per user, billed monthly"
-														: "$6 per user, billed annually"}
-												</span>
-											</p>
-										</div>
-										<ul class="flex flex-col gap-2 justify-center list-none">
-											{proFeatures.map((feature) => (
-												<li class="flex justify-start items-center text-gray-1">
-													<div class="flex justify-center items-center p-0 m-0 size-4">
-														<IconLucideCheck class="size-4" />
-													</div>
-													<span class="ml-2 text-[0.9rem]">{feature}</span>
-												</li>
-											))}
-										</ul>
-									</div>
-									<Button
-										variant="blue"
-										class="!rounded-full !text-lg w-full mx-auto"
-										onClick={openCheckoutInExternalBrowser}
-									>
-										{loading() ? "Loading..." : "Upgrade to Cap Pro"}
-									</Button>
-								</div>
-							</div>
-						</div>
-					</>
-				))}
-		</div>
-	);
+  const [isProAnnual, setIsProAnnual] = createSignal(true);
+  const [isCommercialAnnual, setIsCommercialAnnual] = createSignal(true);
+  const [upgradeComplete, setUpgradeComplete] = createSignal(false);
+  const [loading, setLoading] = createSignal(false);
+  const signIn = createSignInMutation();
+  const license = createLicenseQuery();
+  const [openLicenseDialog, setOpenLicenseDialog] = createSignal(false);
+
+  const resetLicense = createMutation(() => ({
+    mutationFn: async () => {
+      const generalSettings = await generalSettingsStore.get();
+      if (
+        !generalSettings?.instanceId ||
+        !license.data ||
+        license.data.type !== "commercial"
+      ) {
+        throw new Error("No instance ID or valid commercial license found");
+      }
+
+      const resp = await licenseApiClient.activateCommercialLicense({
+        headers: {
+          licensekey: license.data.licenseKey,
+          instanceid: generalSettings.instanceId,
+        },
+        body: { reset: true },
+      });
+
+      if (resp.status !== 200) {
+        if (
+          typeof resp.body === "object" &&
+          resp.body &&
+          "message" in resp.body
+        )
+          throw resp.body.message;
+        throw new Error((resp.body as any).toString());
+      }
+    },
+    onSuccess: async () => {
+      await generalSettingsStore.set({
+        commercialLicense: undefined,
+      });
+      license.refetch();
+    },
+  }));
+
+  const openCheckoutInExternalBrowser = async () => {
+    console.log("Opening checkout in external browser");
+    setLoading(true);
+
+    try {
+      const auth = await authStore.get();
+
+      console.log({ auth });
+      if (!auth) {
+        console.log("No auth found, starting sign in flow");
+        await signIn.mutateAsync(new AbortController());
+      }
+
+      const planId = getProPlanId(isProAnnual() ? "yearly" : "monthly");
+      console.log("Getting checkout URL for plan:", planId);
+      const response = await apiClient.desktop.getProSubscribeURL({
+        body: { priceId: planId },
+        headers: await protectedHeaders(),
+      });
+
+      if (response.status === 200) {
+        console.log("Opening checkout URL in external browser");
+        commands.openExternalLink(response.body.url);
+        console.log("Minimizing upgrade window");
+        const window = await Window.getByLabel("upgrade");
+        if (window) await window.minimize();
+      } else {
+        console.error("Failed to get checkout URL, status:", response.status);
+      }
+    } catch (error) {
+      console.error("Error getting checkout URL:", error);
+    } finally {
+      setLoading(false);
+    }
+  };
+
+  const openCommercialCheckout = createMutation(() => ({
+    mutationFn: async () => {
+      const resp = await licenseApiClient.createCommercialCheckoutUrl({
+        body: { type: isCommercialAnnual() ? "yearly" : "lifetime" },
+      });
+
+      if (resp.status === 200) {
+        console.log("Opening checkout URL in external browser");
+        commands.openExternalLink(resp.body.url);
+        console.log("Minimizing upgrade window");
+        const window = await Window.getByLabel("upgrade");
+        if (window) {
+          await window.minimize();
+        }
+      } else {
+        throw resp.body;
+      }
+    },
+  }));
+
+  // onMount(async () => {
+  //   console.log("Component mounted");
+  //   const unsubscribeDeepLink = await onOpenUrl(async (urls) => {
+  //     console.log("Deep link received:", urls);
+  //     const isDevMode = import.meta.env.VITE_ENVIRONMENT === "development";
+  //     if (isDevMode) {
+  //       console.log("In dev mode, ignoring deep link");
+  //       return;
+  //     }
+
+  //     for (const url of urls) {
+  //       if (!url.includes("token=")) {
+  //         console.log("URL does not contain token, skipping");
+  //         return;
+  //       }
+
+  //       console.log("Processing auth URL");
+  //       const urlObject = new URL(url);
+  //       const token = urlObject.searchParams.get("token");
+  //       const user_id = urlObject.searchParams.get("user_id");
+  //       const expires = Number(urlObject.searchParams.get("expires"));
+
+  //       if (!token || !expires || !user_id) {
+  //         console.error("Invalid signin params");
+  //         throw new Error("Invalid signin params");
+  //       }
+
+  //       console.log("Setting auth store with new credentials");
+  //       const existingAuth = await authStore.get();
+  //       await authStore.set({
+  //         token,
+  //         user_id,
+  //         expires,
+  //         intercom_hash: existingAuth?.intercom_hash ?? "",
+  //         plan: {
+  //           upgraded: false,
+  //           last_checked: 0,
+  //           manual: existingAuth?.plan?.manual ?? false,
+  //         },
+  //       });
+
+  //       console.log("Identifying user in analytics");
+  //       identifyUser(user_id);
+  //       console.log("Tracking sign in event");
+  //       trackEvent("user_signed_in", { platform: "desktop" });
+
+  //       console.log("Reopening upgrade window");
+  //       await commands.showWindow("Upgrade");
+
+  //       console.log("Waiting for window to be ready");
+  //       await new Promise((resolve) => setTimeout(resolve, 500));
+
+  //       console.log("Getting upgrade window reference");
+  //       const upgradeWindow = await Window.getByLabel("upgrade");
+  //       if (upgradeWindow) {
+  //         try {
+  //           console.log("Setting focus on upgrade window");
+  //           await upgradeWindow.show();
+  //           await upgradeWindow.setFocus();
+  //         } catch (e) {
+  //           console.error("Failed to focus upgrade window:", e);
+  //         }
+  //       }
+
+  //       console.log("Getting checkout URL");
+  //       const planId = getProPlanId(isProAnnual() ? "yearly" : "monthly");
+  //       const response = await apiClient.desktop.getProSubscribeURL({
+  //         body: { priceId: planId },
+  //         headers: await protectedHeaders(),
+  //       });
+
+  //       if (response.status === 200) {
+  //         console.log("Opening checkout URL in external browser");
+  //         commands.openExternalLink(response.body.url);
+  //         console.log("Minimizing upgrade window");
+  //         if (upgradeWindow) {
+  //           await upgradeWindow.minimize();
+  //         }
+  //       }
+  //     }
+  //   });
+
+  //   onCleanup(() => {
+  //     console.log("Cleaning up deep link listener");
+  //     unsubscribeDeepLink();
+  //   });
+
+  //   console.log("Setting up upgrade status check interval");
+  //   const interval = setInterval(async () => {
+  //     console.log("Checking upgrade status");
+  //     const result = await commands.checkUpgradedAndUpdate();
+  //     if (result) {
+  //       console.log("Upgrade complete");
+  //       setUpgradeComplete(true);
+  //     }
+  //   }, 5000);
+  //   onCleanup(() => {
+  //     console.log("Cleaning up upgrade status check interval");
+  //     clearInterval(interval);
+  //   });
+  // });
+
+  const { rive: CommercialRive, RiveComponent: Commercial } = createRive(
+    () => ({
+      src: PricingRive,
+      autoplay: true,
+      artboard: "commercial",
+      animations: ["card-stack"],
+    })
+  );
+
+  const { rive: ProRive, RiveComponent: Pro } = createRive(() => ({
+    src: PricingRive,
+    autoplay: true,
+    artboard: "pro",
+    animations: ["items-coming-in"],
+  }));
+
+  return (
+    <div class="flex relative flex-col justify-center items-center p-5 mx-auto w-full h-full">
+      {upgradeComplete() && (
+        <div class="flex justify-center items-center h-full bg-opacity-75">
+          <div class="relative z-10 p-6 text-center bg-white rounded-lg shadow-lg">
+            <h2 class="mb-4 text-2xl font-bold">Upgrade complete</h2>
+            <p class="mb-4 text-sm text-gray-10">
+              You can now close this window - thank you for upgrading!
+            </p>
+            <Button
+              onClick={() => {
+                console.log("Closing window after upgrade");
+                const window = getCurrentWindow();
+                window.close();
+              }}
+              variant="primary"
+              size="lg"
+            >
+              Close window
+            </Button>
+          </div>
+        </div>
+      )}
+      {!upgradeComplete() &&
+        (license.data?.type === "commercial" ? (
+          <div class="p-8 mx-auto w-full max-w-[700px] rounded-xl border shadow-sm bg-gray-2 border-gray-3">
+            <div class="space-y-6">
+              <div class="flex flex-col items-center mb-6 text-center">
+                <h3 class="text-2xl font-medium">Commercial License</h3>
+                <p class="text-sm text-gray-11">
+                  Your license details for Cap commercial use
+                </p>
+              </div>
+
+              <div class="space-y-6">
+                <div>
+                  <label class="block mb-2 text-sm text-gray-12">
+                    License Key
+                  </label>
+                  <p class="overflow-x-auto p-3 font-mono text-xs whitespace-pre-wrap break-all rounded-lg border border-gray-4 text-gray-9 bg-gray-3">
+                    {license.data.licenseKey}
+                  </p>
+                </div>
+
+                <Show when={license.data.expiryDate}>
+                  {(expiryDate) => (
+                    <div class="space-y-1">
+                      <label class="text-sm text-gray-12">Expires</label>
+                      <p class="text-gray-10">
+                        {new Date(expiryDate()).toLocaleDateString(undefined, {
+                          year: "numeric",
+                          month: "long",
+                          day: "numeric",
+                        })}
+                      </p>
+                    </div>
+                  )}
+                </Show>
+
+                <div class="flex flex-col items-center pt-6 border-t border-gray-3">
+                  <Button
+                    variant="destructive"
+                    disabled={resetLicense.isPending}
+                    onClick={() => {
+                      resetLicense.mutate();
+                    }}
+                  >
+                    {resetLicense.isPending
+                      ? "Deactivating..."
+                      : "Deactivate License"}
+                  </Button>
+                </div>
+              </div>
+            </div>
+          </div>
+        ) : (
+          <>
+            <div class="text-center">
+              <h1 class="text-4xl md:text-4xl mb-6 tracking-[-.05em] font-medium text-[--text-primary]">
+                Early Adopter Pricing
+              </h1>
+            </div>
+            <div class="flex gap-4 w-full">
+              <div
+                onMouseEnter={() => {
+                  const riveInstance = CommercialRive();
+                  if (riveInstance) {
+                    // Stop any current animations first
+                    riveInstance.stop();
+                    // Play the enter animation
+                    riveInstance.play("cards");
+                  }
+                }}
+                onMouseLeave={() => {
+                  const riveInstance = CommercialRive();
+                  if (riveInstance) {
+                    // Stop any current animations first
+                    riveInstance.stop();
+                    // Play the leave animation
+                    riveInstance.play("card-stack");
+                  }
+                }}
+                class="flex flex-col flex-1 justify-between p-3 h-[700px ] bg-gray-3 rounded-2xl border border-gray-3 shadow-sm text-card-foreground md:p-3"
+              >
+                <div class="space-y-5">
+                  <div class="flex flex-col gap-6 items-center">
+                    <Commercial class="w-[250px]" />
+                    <div class="space-y-1 text-center">
+                      <h3 class="text-2xl font-medium tracking-tight leading-5">
+                        Commercial License
+                      </h3>
+                      <p class="mt-2 text-sm text-[--text-tertiary]">
+                        For commercial use
+                      </p>
+                    </div>
+                    <div class="flex flex-col justify-center items-center">
+                      <h3 class="text-4xl leading-6">
+                        {isCommercialAnnual() ? "$29" : "$58"}
+                        <span class="text-gray-11 text-[16px]">.00 /</span>
+                      </h3>
+                      {isCommercialAnnual() && (
+                        <p class="text-[16px] font-medium text-gray-11">
+                          billed annually
+                        </p>
+                      )}
+                      {!isCommercialAnnual() && (
+                        <p class="text-[16px] font-medium text-gray-11">
+                          one-time payment
+                        </p>
+                      )}
+                    </div>
+                    <div
+                      onClick={() => setIsCommercialAnnual((v) => !v)}
+                      class="px-3 py-2 text-center rounded-full border border-transparent transition-all duration-200 cursor-pointer bg-gray-5 hover:border-gray-400"
+                    >
+                      <p class="text-xs text-gray-12">
+                        Switch to {isCommercialAnnual() ? "lifetime" : "yearly"}
+                        :{" "}
+                        <span class="font-medium">
+                          {isCommercialAnnual() ? "$58" : "$29"}
+                        </span>
+                      </p>
+                    </div>
+                    <ul class="flex flex-col gap-2 justify-center list-none">
+                      {[
+                        "Commercial Use of Cap Recorder + Editor",
+                        "Community Support",
+                        "Local-only features",
+                        "Perpetual license option",
+                      ].map((feature) => (
+                        <li class="flex justify-start items-center">
+                          <div class="flex justify-center items-center p-0 m-0 w-6 h-6">
+                            <IconLucideCheck class="w-4 h-4 text-[--text-primary]" />
+                          </div>
+                          <span class="ml-1 text-[0.9rem] text-[--text-primary]">
+                            {feature}
+                          </span>
+                        </li>
+                      ))}
+                    </ul>
+                  </div>
+                </div>
+                <ActivateLicenseDialog
+                  open={openLicenseDialog}
+                  onOpenChange={setOpenLicenseDialog}
+                />
+                <div class="flex flex-col gap-4 items-center">
+                  <Button
+                    onClick={() => openCommercialCheckout.mutate()}
+                    disabled={openCommercialCheckout.isPending}
+                    variant="dark"
+                    class="w-full !rounded-full !h-[48px] text-lg font-medium"
+                    size="lg"
+                  >
+                    {openCommercialCheckout.isPending
+                      ? "Loading..."
+                      : "Purchase License"}
+                  </Button>
+                  <p
+                    onClick={() => setOpenLicenseDialog(true)}
+                    class="mb-2 text-sm transition-colors cursor-pointer text-gray-11 hover:text-gray-12"
+                  >
+                    Already have a license key?
+                  </p>
+                </div>
+              </div>
+
+              {/* Cap Pro */}
+              <div
+                onMouseEnter={() => {
+                  const riveInstance = ProRive();
+                  if (riveInstance) {
+                    // Stop any current animations first
+                    riveInstance.stop();
+                    // Play the enter animation
+                    riveInstance.play("items-coming-out");
+                  }
+                }}
+                onMouseLeave={() => {
+                  const riveInstance = ProRive();
+                  if (riveInstance) {
+                    // Stop any current animations first
+                    riveInstance.stop();
+                    // Play the leave animation
+                    riveInstance.play("items-coming-in");
+                  }
+                }}
+                class="flex-grow p-3 h-[700px] flex-1 bg-gray-12 rounded-2xl border shadow-sm text-card-foreground md:p-3"
+              >
+                <div class="flex flex-col justify-between space-y-5 h-full">
+                  <div class="flex flex-col gap-6 items-center px-6">
+                    <Pro class="w-[250px]" />
+                    <div class="space-y-1 text-center">
+                      <h3 class="text-2xl font-medium tracking-tight leading-5 text-gray-1">
+                        Cap Pro
+                      </h3>
+                      <p class="text-[0.875rem] text-gray-9">
+                        For professional use and teams.
+                      </p>
+                    </div>
+                    <div class="flex flex-col justify-center items-center">
+                      <h3 class="text-4xl leading-6 text-gray-1">
+                        {isProAnnual() ? "$8.16" : "$12"}
+                        <span class="text-gray-10 text-[16px]">.00 /</span>
+                      </h3>
+                      {isProAnnual() && (
+                        <p class="text-[16px] font-medium text-gray-9">
+                          per user, billed annually
+                        </p>
+                      )}
+                      {!isProAnnual() && (
+                        <p class="text-[16px] font-medium text-gray-9">
+                          per user, billed monthly
+                        </p>
+                      )}
+                    </div>
+                    <div
+                      onClick={() => setIsProAnnual((v) => !v)}
+                      class="px-3 py-2 text-center bg-blue-500 rounded-full border border-transparent transition-all duration-200 cursor-pointer hover:border-blue-400"
+                    >
+                      <p class="text-xs text-solid-white">
+                        Switch to {isProAnnual() ? "monthly" : "yearly"}:{" "}
+                        <span class="font-medium">
+                          {isProAnnual()
+                            ? "$12 per user, billed monthly"
+                            : "$8.16 per user, billed annually"}
+                        </span>
+                      </p>
+                    </div>
+                    <ul class="flex flex-col gap-2 justify-center list-none">
+                      {proFeatures.map((feature) => (
+                        <li class="flex justify-start items-center text-gray-1">
+                          <div class="flex justify-center items-center p-0 m-0 size-4">
+                            <IconLucideCheck class="size-4" />
+                          </div>
+                          <span class="ml-2 text-[0.9rem]">{feature}</span>
+                        </li>
+                      ))}
+                    </ul>
+                  </div>
+                  <Button
+                    variant="blue"
+                    class="!rounded-full !text-lg w-full mx-auto"
+                    onClick={openCheckoutInExternalBrowser}
+                  >
+                    {loading() ? "Loading..." : "Upgrade to Cap Pro"}
+                  </Button>
+                </div>
+              </div>
+            </div>
+          </>
+        ))}
+    </div>
+  );
 }
 
 interface Props {
-	open: Accessor<boolean>;
-	onOpenChange: (open: boolean) => void;
+  open: Accessor<boolean>;
+  onOpenChange: (open: boolean) => void;
 }
 
 const ActivateLicenseDialog = ({ open, onOpenChange }: Props) => {
-	const [licenseKey, setLicenseKey] = createSignal("");
-	const queryClient = useQueryClient();
-
-	const activateLicenseKey = createMutation(() => ({
-		mutationFn: async (vars: { licenseKey: string }) => {
-			const generalSettings = await generalSettingsStore.get();
-			if (!generalSettings?.instanceId) {
-				throw new Error("No instance ID found");
-			}
-			const resp = await licenseApiClient.activateCommercialLicense({
-				headers: {
-					licensekey: vars.licenseKey,
-					instanceid: generalSettings.instanceId,
-				},
-				body: { reset: false },
-			});
-
-			if (resp.status === 200)
-				return { ...resp.body, licenseKey: vars.licenseKey };
-			if (typeof resp.body === "object" && resp.body && "message" in resp.body)
-				throw resp.body.message;
-			throw new Error((resp.body as any).toString());
-		},
-		onSuccess: async (value) => {
-			await generalSettingsStore.set({
-				commercialLicense: {
-					activatedOn: Date.now(),
-					expiryDate: value.expiryDate ?? null,
-					refresh: value.refresh,
-					licenseKey: value.licenseKey,
-				},
-			});
-			await queryClient.refetchQueries({ queryKey: ["bruh"] });
-		},
-	}));
-	return (
-		<Dialog.Root open={open()} onOpenChange={onOpenChange}>
-			<DialogContent
-				title="Activate License"
-				confirm={
-					<Dialog.ConfirmButton
-						disabled={activateLicenseKey.isPending}
-						onClick={() =>
-							activateLicenseKey.mutate({
-								licenseKey: licenseKey(),
-							})
-						}
-					>
-						Activate
-					</Dialog.ConfirmButton>
-				}
-			>
-				<Input
-					class="mt-2"
-					placeholder="Enter license key..."
-					value={licenseKey()}
-					onInput={(e) => setLicenseKey(e.currentTarget.value)}
-				/>
-			</DialogContent>
-		</Dialog.Root>
-	);
+  const [licenseKey, setLicenseKey] = createSignal("");
+  const queryClient = useQueryClient();
+
+  const activateLicenseKey = createMutation(() => ({
+    mutationFn: async (vars: { licenseKey: string }) => {
+      const generalSettings = await generalSettingsStore.get();
+      if (!generalSettings?.instanceId) {
+        throw new Error("No instance ID found");
+      }
+      const resp = await licenseApiClient.activateCommercialLicense({
+        headers: {
+          licensekey: vars.licenseKey,
+          instanceid: generalSettings.instanceId,
+        },
+        body: { reset: false },
+      });
+
+      if (resp.status === 200)
+        return { ...resp.body, licenseKey: vars.licenseKey };
+      if (typeof resp.body === "object" && resp.body && "message" in resp.body)
+        throw resp.body.message;
+      throw new Error((resp.body as any).toString());
+    },
+    onSuccess: async (value) => {
+      await generalSettingsStore.set({
+        commercialLicense: {
+          activatedOn: Date.now(),
+          expiryDate: value.expiryDate ?? null,
+          refresh: value.refresh,
+          licenseKey: value.licenseKey,
+        },
+      });
+      await queryClient.refetchQueries({ queryKey: ["bruh"] });
+    },
+  }));
+  return (
+    <Dialog.Root open={open()} onOpenChange={onOpenChange}>
+      <DialogContent
+        title="Activate License"
+        confirm={
+          <Dialog.ConfirmButton
+            disabled={activateLicenseKey.isPending}
+            onClick={() =>
+              activateLicenseKey.mutate({
+                licenseKey: licenseKey(),
+              })
+            }
+          >
+            Activate
+          </Dialog.ConfirmButton>
+        }
+      >
+        <Input
+          class="mt-2"
+          placeholder="Enter license key..."
+          value={licenseKey()}
+          onInput={(e) => setLicenseKey(e.currentTarget.value)}
+        />
+      </DialogContent>
+    </Dialog.Root>
+  );
 };
diff --git a/apps/desktop/src/utils/plans.ts b/apps/desktop/src/utils/plans.ts
index 32d64faec8..55c67b5f64 100644
--- a/apps/desktop/src/utils/plans.ts
+++ b/apps/desktop/src/utils/plans.ts
@@ -6,8 +6,8 @@ const planIds = {
 		monthly: "price_1P9C1DFJxA1XpeSsTwwuddnq",
 	},
 	production: {
-		yearly: "price_1Q29mcFJxA1XpeSsbti0xJpZ",
-		monthly: "price_1OtBMeFJxA1XpeSsfOu2SKp1",
+		yearly: "price_1S2al7FJxA1XpeSsJCI5Z2UD",
+		monthly: "price_1S2akxFJxA1XpeSsfoAUUbpJ",
 	},
 };
 
diff --git a/apps/web/components/pages/FaqPage.tsx b/apps/web/components/pages/FaqPage.tsx
index ae0e532f1b..65a2e3a286 100644
--- a/apps/web/components/pages/FaqPage.tsx
+++ b/apps/web/components/pages/FaqPage.tsx
@@ -1,59 +1,59 @@
 "use client";
 
 const faqContent = [
-	{
-		title: "Who is Cap for?",
-		answer:
-			"Cap is for anyone who wants to record, edit, and share videos. It's a lightweight, powerful tool for creators, educators, marketers, developers, and remote teams who want to communicate more effectively through screen recordings.",
-	},
-	{
-		title: "How much does it cost?",
-		answer:
-			"Cap offers a free version for personal use. You can upgrade to Cap Pro for just $9/month to unlock unlimited cloud storage, unlimited recording length, custom domain support, advanced team features, password-protected videos, analytics, and priority support. We also offer commercial licenses and self-hosted options for businesses.",
-	},
-	{
-		title: "Which platforms does Cap support?",
-		answer:
-			"Cap is cross-platform and works on macOS (both Apple Silicon and Intel) and Windows. For macOS, we recommend version 13.1 or newer. For Windows, we recommend Windows 10 or newer.",
-	},
-	{
-		title: "What makes Cap different from Loom?",
-		answer:
-			"Cap is open source, privacy-focused, and lets you own your data. You can connect custom S3 storage buckets, self-host the entire platform, and get a lightweight, faster experience. We focus strongly on design, user experience, and building with our community at the center of everything we do.",
-	},
-	{
-		title: "Can I self-host Cap?",
-		answer:
-			"Yes! Cap can be self-hosted on your own infrastructure, giving you full control over your data.",
-	},
-	{
-		title: "Is there a commercial license available?",
-		answer:
-			"Yes, we offer commercial licenses for businesses that want to use the Cap desktop app. The commercial license includes the Cap Recorder + Editor with local-only features. Our Pro plan also includes a commercial license for the desktop app.",
-	},
-	{
-		title: "What happens after the beta period ends?",
-		answer:
-			"Early adopters will keep their special pricing for the lifetime of their subscription, even after we move out of beta and adjust our regular pricing. This is our way of thanking our early supporters.",
-	},
+  {
+    title: "Who is Cap for?",
+    answer:
+      "Cap is for anyone who wants to record, edit, and share videos. It's a lightweight, powerful tool for creators, educators, marketers, developers, and remote teams who want to communicate more effectively through screen recordings.",
+  },
+  {
+    title: "How much does it cost?",
+    answer:
+      "Cap offers a free version for personal use. You can upgrade to Cap Pro for just $8.16/month (when billed annually) to unlock unlimited cloud storage, unlimited recording length, custom domain support, advanced team features, password-protected videos, analytics, and priority support. We also offer commercial licenses and self-hosted options for businesses.",
+  },
+  {
+    title: "Which platforms does Cap support?",
+    answer:
+      "Cap is cross-platform and works on macOS (both Apple Silicon and Intel) and Windows. For macOS, we recommend version 13.1 or newer. For Windows, we recommend Windows 10 or newer.",
+  },
+  {
+    title: "What makes Cap different from Loom?",
+    answer:
+      "Cap is open source, privacy-focused, and lets you own your data. You can connect custom S3 storage buckets, self-host the entire platform, and get a lightweight, faster experience. We focus strongly on design, user experience, and building with our community at the center of everything we do.",
+  },
+  {
+    title: "Can I self-host Cap?",
+    answer:
+      "Yes! Cap can be self-hosted on your own infrastructure, giving you full control over your data.",
+  },
+  {
+    title: "Is there a commercial license available?",
+    answer:
+      "Yes, we offer commercial licenses for businesses that want to use the Cap desktop app. The commercial license includes the Cap Recorder + Editor with local-only features. Our Pro plan also includes a commercial license for the desktop app.",
+  },
+  {
+    title: "What happens after the beta period ends?",
+    answer:
+      "Early adopters will keep their special pricing for the lifetime of their subscription, even after we move out of beta and adjust our regular pricing. This is our way of thanking our early supporters.",
+  },
 ];
 
 export const FaqPage = () => {
-	return (
-		<div className="py-32 md:py-40 wrapper wrapper-sm">
-			<div className="mb-14 text-center page-intro">
-				<h1>FAQ</h1>
-			</div>
-			<div className="mb-10">
-				{faqContent.map((section, index) => {
-					return (
-						<div key={index} className="mx-auto my-8 max-w-2xl">
-							<h2 className="mb-2 text-xl">{section.title}</h2>
-							<p className="text-lg">{section.answer}</p>
-						</div>
-					);
-				})}
-			</div>
-		</div>
-	);
+  return (
+    <div className="py-32 md:py-40 wrapper wrapper-sm">
+      <div className="mb-14 text-center page-intro">
+        <h1>FAQ</h1>
+      </div>
+      <div className="mb-10">
+        {faqContent.map((section, index) => {
+          return (
+            <div key={index} className="mx-auto my-8 max-w-2xl">
+              <h2 className="mb-2 text-xl">{section.title}</h2>
+              <p className="text-lg">{section.answer}</p>
+            </div>
+          );
+        })}
+      </div>
+    </div>
+  );
 };
diff --git a/apps/web/components/pages/seo/LoomAlternativePage.tsx b/apps/web/components/pages/seo/LoomAlternativePage.tsx
index c64d250391..73d4e4c341 100644
--- a/apps/web/components/pages/seo/LoomAlternativePage.tsx
+++ b/apps/web/components/pages/seo/LoomAlternativePage.tsx
@@ -4,195 +4,195 @@ import Script from "next/script";
 import { SeoPageTemplate } from "../../seo/SeoPageTemplate";
 
 export const loomAlternativeContent = {
-	title:
-		"The Ultimate Loom Alternative: Why Cap is the Best Open-Source Screen Recorder for Mac & Windows",
-	description:
-		"Looking for the best Loom alternative? Discover Cap, the open-source, privacy-focused screen recorder for Mac & Windows. See why users are switching today!",
+  title:
+    "The Ultimate Loom Alternative: Why Cap is the Best Open-Source Screen Recorder for Mac & Windows",
+  description:
+    "Looking for the best Loom alternative? Discover Cap, the open-source, privacy-focused screen recorder for Mac & Windows. See why users are switching today!",
 
-	featuresTitle: "Why Cap is the Best Loom Alternative",
-	featuresDescription:
-		"Cap offers everything you need in a privacy-focused, open-source screen recording solution",
+  featuresTitle: "Why Cap is the Best Loom Alternative",
+  featuresDescription:
+    "Cap offers everything you need in a privacy-focused, open-source screen recording solution",
 
-	features: [
-		{
-			title: "Open-Source Transparency",
-			description:
-				"Cap is fully open-source, giving you complete transparency and community-driven development. We believe in building in public and letting users help shape our roadmap. Looking for an <a href='/free-screen-recorder'>open-source screen recorder</a>? Cap is your best choice!",
-		},
-		{
-			title: "Enhanced Privacy & Security",
-			description:
-				"Cap prioritizes your privacy with GDPR compliance and the option to use your own S3 storage, ensuring your data remains under your control. Connect your own custom domain for a branded experience while maintaining 100% ownership of your data.",
-		},
-		{
-			title: "Half the Price of Loom",
-			description:
-				"Cap is just $9/month per user, compared to Loom's $18/month per user. Plus, Cap offers a generous free plan that includes Studio mode for personal use.",
-		},
-		{
-			title: "High-Quality Recordings",
-			description:
-				"Record smooth, high-definition videos at 60fps with synchronized audio up to 4K resolution, perfect for professional use.",
-		},
-		{
-			title: "Collaborative Features",
-			description:
-				"Cap includes built-in thread commenting on shareable links, making it easy to collaborate with teammates and collect feedback on your recordings without switching platforms.",
-		},
-		{
-			title: "Cross-Platform Support",
-			description:
-				"Available for both Mac and Windows, Cap delivers consistent performance across platforms. A perfect <a href='/screen-recording-software'>screen recording software</a> for all users.",
-		},
-	],
+  features: [
+    {
+      title: "Open-Source Transparency",
+      description:
+        "Cap is fully open-source, giving you complete transparency and community-driven development. We believe in building in public and letting users help shape our roadmap. Looking for an <a href='/free-screen-recorder'>open-source screen recorder</a>? Cap is your best choice!",
+    },
+    {
+      title: "Enhanced Privacy & Security",
+      description:
+        "Cap prioritizes your privacy with GDPR compliance and the option to use your own S3 storage, ensuring your data remains under your control. Connect your own custom domain for a branded experience while maintaining 100% ownership of your data.",
+    },
+    {
+      title: "Half the Price of Loom",
+      description:
+        "Cap stars from just $8.16/month per user, compared to Loom's $18/month per user. Plus, Cap offers a generous free plan that includes Studio mode for personal use.",
+    },
+    {
+      title: "High-Quality Recordings",
+      description:
+        "Record smooth, high-definition videos at 60fps with synchronized audio up to 4K resolution, perfect for professional use.",
+    },
+    {
+      title: "Collaborative Features",
+      description:
+        "Cap includes built-in thread commenting on shareable links, making it easy to collaborate with teammates and collect feedback on your recordings without switching platforms.",
+    },
+    {
+      title: "Cross-Platform Support",
+      description:
+        "Available for both Mac and Windows, Cap delivers consistent performance across platforms. A perfect <a href='/screen-recording-software'>screen recording software</a> for all users.",
+    },
+  ],
 
-	recordingModes: {
-		title: "Two Ways to Record with Cap",
-		description:
-			"Cap gives you flexible recording options to match your workflow needs, with both modes available in the free plan",
-		modes: [
-			{
-				title: "Instant Mode",
-				description:
-					"Share your screen right away with a simple link—no waiting, just record and share in seconds. Record up to 5-minute shareable links for free, perfect for quick demos and explanations. Includes built-in thread commenting for easy collaboration.",
-			},
-			{
-				title: "Studio Mode",
-				description:
-					"Available completely free for personal use! Records at top quality up to 4K. Captures both your screen and webcam separately so you can edit them later, giving you professional-level production control.",
-			},
-		],
-	},
+  recordingModes: {
+    title: "Two Ways to Record with Cap",
+    description:
+      "Cap gives you flexible recording options to match your workflow needs, with both modes available in the free plan",
+    modes: [
+      {
+        title: "Instant Mode",
+        description:
+          "Share your screen right away with a simple link—no waiting, just record and share in seconds. Record up to 5-minute shareable links for free, perfect for quick demos and explanations. Includes built-in thread commenting for easy collaboration.",
+      },
+      {
+        title: "Studio Mode",
+        description:
+          "Available completely free for personal use! Records at top quality up to 4K. Captures both your screen and webcam separately so you can edit them later, giving you professional-level production control.",
+      },
+    ],
+  },
 
-	useCasesTitle: "Why Users Choose Cap for Screen Recording",
-	useCasesDescription:
-		"Discover the features that make Cap a compelling option for screen recording",
+  useCasesTitle: "Why Users Choose Cap for Screen Recording",
+  useCasesDescription:
+    "Discover the features that make Cap a compelling option for screen recording",
 
-	useCases: [
-		{
-			title: "Budget-Friendly Options",
-			description:
-				"Many screen recording tools have complex pricing structures. Cap offers similar functionality with clear, affordable pricing options.",
-		},
-		{
-			title: "Complete Data Ownership",
-			description:
-				"Cap lets you connect your own S3 storage and custom domain, giving you 100% ownership and control over your content. No more being locked into proprietary platforms.",
-		},
-		{
-			title: "Community-Driven Development",
-			description:
-				"As an <a href='/screen-recorder'>open-source screen recorder</a>, Cap is built in the open with community input. User feedback directly shapes our roadmap and features.",
-		},
-		{
-			title: "Collaborative Feedback",
-			description:
-				"Cap's built-in thread commenting on shareable links makes it easy to collect feedback and collaborate without switching between different tools.",
-		},
-	],
+  useCases: [
+    {
+      title: "Budget-Friendly Options",
+      description:
+        "Many screen recording tools have complex pricing structures. Cap offers similar functionality with clear, affordable pricing options.",
+    },
+    {
+      title: "Complete Data Ownership",
+      description:
+        "Cap lets you connect your own S3 storage and custom domain, giving you 100% ownership and control over your content. No more being locked into proprietary platforms.",
+    },
+    {
+      title: "Community-Driven Development",
+      description:
+        "As an <a href='/screen-recorder'>open-source screen recorder</a>, Cap is built in the open with community input. User feedback directly shapes our roadmap and features.",
+    },
+    {
+      title: "Collaborative Feedback",
+      description:
+        "Cap's built-in thread commenting on shareable links makes it easy to collect feedback and collaborate without switching between different tools.",
+    },
+  ],
 
-	faqsTitle: "Frequently Asked Questions",
-	faqs: [
-		{
-			question: "Is there a free Loom alternative?",
-			answer:
-				"Yes, Cap offers a generous free tier that includes all essential screen recording features. You can use Studio mode completely free for personal use, record up to 5-minute shareable links, and record in up to 4K resolution. Cap's free plan offers more than Loom's free tier.",
-		},
-		{
-			question: "Why choose an open-source screen recorder?",
-			answer:
-				"Open-source screen recorders like Cap provide transparency, security, and community-driven development. You can verify the code, contribute improvements, and trust that your data isn't being misused. Cap's community focus means features are developed based on real user needs.",
-		},
-		{
-			question: "How does Cap compare in pricing with Loom?",
-			answer:
-				"Cap is significantly more affordable at just $9/month per user, compared to Loom's $18/month per user. Cap also has a more generous free plan that includes Studio mode for personal use and the ability to record shareable links up to 5 minutes in 4K quality.",
-		},
-		{
-			question: "Can I keep full ownership of my recordings with Cap?",
-			answer:
-				"Absolutely! Cap allows you to connect your own S3 storage and custom domain, giving you 100% ownership and control of your content. Your data remains yours, and you're never locked into our platform.",
-		},
-		{
-			question: "Does Cap support collaboration features?",
-			answer:
-				"Yes, Cap includes built-in thread commenting on shareable links, making it easy to collaborate with teammates and collect feedback directly on your recordings. This keeps all your communication in one place.",
-		},
-	],
+  faqsTitle: "Frequently Asked Questions",
+  faqs: [
+    {
+      question: "Is there a free Loom alternative?",
+      answer:
+        "Yes, Cap offers a generous free tier that includes all essential screen recording features. You can use Studio mode completely free for personal use, record up to 5-minute shareable links, and record in up to 4K resolution. Cap's free plan offers more than Loom's free tier.",
+    },
+    {
+      question: "Why choose an open-source screen recorder?",
+      answer:
+        "Open-source screen recorders like Cap provide transparency, security, and community-driven development. You can verify the code, contribute improvements, and trust that your data isn't being misused. Cap's community focus means features are developed based on real user needs.",
+    },
+    {
+      question: "How does Cap compare in pricing with Loom?",
+      answer:
+        "Cap is significantly more affordable at just $8.16/month per user when billed annually, compared to Loom's $18/month per user. Cap also has a more generous free plan that includes Studio mode for personal use and the ability to record shareable links up to 5 minutes in 4K quality.",
+    },
+    {
+      question: "Can I keep full ownership of my recordings with Cap?",
+      answer:
+        "Absolutely! Cap allows you to connect your own S3 storage and custom domain, giving you 100% ownership and control of your content. Your data remains yours, and you're never locked into our platform.",
+    },
+    {
+      question: "Does Cap support collaboration features?",
+      answer:
+        "Yes, Cap includes built-in thread commenting on shareable links, making it easy to collaborate with teammates and collect feedback directly on your recordings. This keeps all your communication in one place.",
+    },
+  ],
 
-	comparisonTable: {
-		title: "Feature Comparison: Cap vs. Loom",
-		headers: ["Feature", "Cap", "Loom"],
-		rows: [
-			["Open Source", "✅ Yes", "❌ No"],
-			["Pricing", "✅ $9/month per user", "⚠️ $18/month per user"],
-			[
-				"Free Plan",
-				"✅ Studio mode + 5 min shareable links",
-				"⚠️ Limited features & recording time",
-			],
-			[
-				"4K Recording",
-				"✅ Available in free & paid plans",
-				"⚠️ Only in paid plans",
-			],
-			["Thread Commenting", "✅ Built-in on shareable links", "☑️ Available"],
-			["Custom Domain", "✅ Yes", "☑️ Enterprise plan only"],
-			["Own Storage Integration", "✅ Connect your own S3", "❌ Not available"],
-			["Community Input", "✅ Direct via open source", "☑️ Limited"],
-			["Data Ownership", "✅ 100% with own storage", "☑️ Platform dependent"],
-		],
-	},
-	migrationGuide: {
-		title: "How to Get Started with Cap (Easy Guide)",
-		steps: [
-			"Download Cap for your operating system (Mac or Windows)",
-			"Launch the application",
-			"Start recording using either Instant Mode or Studio Mode",
-			"Share your recordings easily with Cap's built-in sharing features",
-			"Optional: Connect your own S3 storage and custom domain for complete data ownership",
-		],
-	},
+  comparisonTable: {
+    title: "Feature Comparison: Cap vs. Loom",
+    headers: ["Feature", "Cap", "Loom"],
+    rows: [
+      ["Open Source", "✅ Yes", "❌ No"],
+      ["Pricing", "✅ $from 8.16/month per user", "⚠️ $18/month per user"],
+      [
+        "Free Plan",
+        "✅ Studio mode + 5 min shareable links",
+        "⚠️ Limited features & recording time",
+      ],
+      [
+        "4K Recording",
+        "✅ Available in free & paid plans",
+        "⚠️ Only in paid plans",
+      ],
+      ["Thread Commenting", "✅ Built-in on shareable links", "☑️ Available"],
+      ["Custom Domain", "✅ Yes", "☑️ Enterprise plan only"],
+      ["Own Storage Integration", "✅ Connect your own S3", "❌ Not available"],
+      ["Community Input", "✅ Direct via open source", "☑️ Limited"],
+      ["Data Ownership", "✅ 100% with own storage", "☑️ Platform dependent"],
+    ],
+  },
+  migrationGuide: {
+    title: "How to Get Started with Cap (Easy Guide)",
+    steps: [
+      "Download Cap for your operating system (Mac or Windows)",
+      "Launch the application",
+      "Start recording using either Instant Mode or Studio Mode",
+      "Share your recordings easily with Cap's built-in sharing features",
+      "Optional: Connect your own S3 storage and custom domain for complete data ownership",
+    ],
+  },
 
-	video: {
-		url: "/videos/cap-vs-loom-comparison.mp4",
-		thumbnail: "/videos/cap-vs-loom-thumbnail.png",
-		alt: "Cap screen recorder demo showing privacy features and interface",
-	},
+  video: {
+    url: "/videos/cap-vs-loom-comparison.mp4",
+    thumbnail: "/videos/cap-vs-loom-thumbnail.png",
+    alt: "Cap screen recorder demo showing privacy features and interface",
+  },
 
-	cta: {
-		title: "Ready to Try Cap for Your Screen Recording Needs?",
-		buttonText: "Download Cap Free",
-	},
+  cta: {
+    title: "Ready to Try Cap for Your Screen Recording Needs?",
+    buttonText: "Download Cap Free",
+  },
 };
 
 // Create FAQ structured data for SEO
 const createFaqStructuredData = () => {
-	const faqStructuredData = {
-		"@context": "https://schema.org",
-		"@type": "FAQPage",
-		mainEntity: loomAlternativeContent.faqs.map((faq) => ({
-			"@type": "Question",
-			name: faq.question,
-			acceptedAnswer: {
-				"@type": "Answer",
-				text: faq.answer.replace(/<\/?[^>]+(>|$)/g, ""),
-			},
-		})),
-	};
+  const faqStructuredData = {
+    "@context": "https://schema.org",
+    "@type": "FAQPage",
+    mainEntity: loomAlternativeContent.faqs.map((faq) => ({
+      "@type": "Question",
+      name: faq.question,
+      acceptedAnswer: {
+        "@type": "Answer",
+        text: faq.answer.replace(/<\/?[^>]+(>|$)/g, ""),
+      },
+    })),
+  };
 
-	return JSON.stringify(faqStructuredData);
+  return JSON.stringify(faqStructuredData);
 };
 
 export const LoomAlternativePage = () => {
-	return (
-		<>
-			<Script
-				id="faq-structured-data"
-				type="application/ld+json"
-				dangerouslySetInnerHTML={{ __html: createFaqStructuredData() }}
-			/>
-			<SeoPageTemplate content={loomAlternativeContent} />
-		</>
-	);
+  return (
+    <>
+      <Script
+        id="faq-structured-data"
+        type="application/ld+json"
+        dangerouslySetInnerHTML={{ __html: createFaqStructuredData() }}
+      />
+      <SeoPageTemplate content={loomAlternativeContent} />
+    </>
+  );
 };
diff --git a/apps/web/public/llms.txt b/apps/web/public/llms.txt
index 3e24a8b970..0f2f4fd3d4 100644
--- a/apps/web/public/llms.txt
+++ b/apps/web/public/llms.txt
@@ -78,7 +78,7 @@ Provide visual answers to support tickets. Create help videos and documentation.
 
 - **Personal Use**: Free forever (5-minute recording limit)
 - **Desktop License**: $29/year or $58 lifetime (unlimited recording)
-- **Cap Pro**: $9/month ($6/month when billed annually) - includes cloud storage and AI features
+- **Cap Pro**: $12/month ($8.16/month when billed annually) - includes cloud storage and AI features
 - **Teams**: Custom pricing for organizations
 
 ## Privacy & Security
diff --git a/packages/ui-solid/src/auto-imports.d.ts b/packages/ui-solid/src/auto-imports.d.ts
index e39a4bd12b..ff67bd3fcf 100644
--- a/packages/ui-solid/src/auto-imports.d.ts
+++ b/packages/ui-solid/src/auto-imports.d.ts
@@ -6,14 +6,14 @@
 // biome-ignore lint: disable
 export {}
 declare global {
-  const IconCapArrows: typeof import("~icons/cap/arrows.jsx")["default"]
+  const IconCapArrows: typeof import('~icons/cap/arrows.jsx')['default']
   const IconCapAudioOn: typeof import('~icons/cap/audio-on.jsx')['default']
   const IconCapBgBlur: typeof import('~icons/cap/bg-blur.jsx')['default']
   const IconCapCamera: typeof import('~icons/cap/camera.jsx')['default']
   const IconCapCaptions: typeof import('~icons/cap/captions.jsx')['default']
   const IconCapCaretDown: typeof import('~icons/cap/caret-down.jsx')['default']
   const IconCapChevronDown: typeof import('~icons/cap/chevron-down.jsx')['default']
-  const IconCapCircle: typeof import("~icons/cap/circle.jsx")["default"]
+  const IconCapCircle: typeof import('~icons/cap/circle.jsx')['default']
   const IconCapCircleCheck: typeof import('~icons/cap/circle-check.jsx')['default']
   const IconCapCirclePlus: typeof import('~icons/cap/circle-plus.jsx')['default']
   const IconCapCircleX: typeof import('~icons/cap/circle-x.jsx')['default']
@@ -52,7 +52,7 @@ declare global {
   const IconCapScissors: typeof import('~icons/cap/scissors.jsx')['default']
   const IconCapSettings: typeof import('~icons/cap/settings.jsx')['default']
   const IconCapShadow: typeof import('~icons/cap/shadow.jsx')['default']
-  const IconCapSquare: typeof import("~icons/cap/square.jsx")["default"]
+  const IconCapSquare: typeof import('~icons/cap/square.jsx')['default']
   const IconCapStopCircle: typeof import("~icons/cap/stop-circle.jsx")["default"]
   const IconCapTrash: typeof import('~icons/cap/trash.jsx')['default']
   const IconCapUndo: typeof import('~icons/cap/undo.jsx')['default']
@@ -78,7 +78,7 @@ declare global {
   const IconLucideMessageSquarePlus: typeof import('~icons/lucide/message-square-plus.jsx')['default']
   const IconLucideMicOff: typeof import("~icons/lucide/mic-off.jsx")["default"]
   const IconLucideMonitor: typeof import('~icons/lucide/monitor.jsx')['default']
-  const IconLucideRectangleHorizontal: typeof import("~icons/lucide/rectangle-horizontal.jsx")["default"]
+  const IconLucideRectangleHorizontal: typeof import('~icons/lucide/rectangle-horizontal.jsx')['default']
   const IconLucideRotateCcw: typeof import('~icons/lucide/rotate-ccw.jsx')['default']
   const IconLucideSearch: typeof import('~icons/lucide/search.jsx')['default']
   const IconLucideSquarePlay: typeof import('~icons/lucide/square-play.jsx')['default']
diff --git a/packages/utils/src/constants/plans.ts b/packages/utils/src/constants/plans.ts
index 8259e8c90f..bbfb233dec 100644
--- a/packages/utils/src/constants/plans.ts
+++ b/packages/utils/src/constants/plans.ts
@@ -6,8 +6,8 @@ const planIds = {
 		monthly: "price_1P9C1DFJxA1XpeSsTwwuddnq",
 	},
 	production: {
-		yearly: "price_1Q29mcFJxA1XpeSsbti0xJpZ",
-		monthly: "price_1OtBMeFJxA1XpeSsfOu2SKp1",
+		yearly: "price_1S2al7FJxA1XpeSsJCI5Z2UD",
+		monthly: "price_1S2akxFJxA1XpeSsfoAUUbpJ",
 	},
 };
 

From 53ab7b712fd92b11917ffe23887916f484cbff96 Mon Sep 17 00:00:00 2001
From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com>
Date: Mon, 1 Sep 2025 18:06:19 +0100
Subject: [PATCH 2/3] feat: extra pricing bits

---
 apps/web/components/UpgradeModal.tsx          | 550 +++++++++---------
 .../pages/HomePage/Pricing/ProCard.tsx        | 464 +++++++--------
 apps/web/data/homepage-copy.ts                |   4 +-
 3 files changed, 509 insertions(+), 509 deletions(-)

diff --git a/apps/web/components/UpgradeModal.tsx b/apps/web/components/UpgradeModal.tsx
index 9a46b0918f..8ece5c67f5 100644
--- a/apps/web/components/UpgradeModal.tsx
+++ b/apps/web/components/UpgradeModal.tsx
@@ -7,313 +7,313 @@ import NumberFlow from "@number-flow/react";
 import { Fit, Layout, useRive } from "@rive-app/react-canvas";
 import { AnimatePresence, motion } from "framer-motion";
 import {
-	BarChart3,
-	Database,
-	Globe,
-	Headphones,
-	Infinity,
-	Lock,
-	Minus,
-	Plus,
-	Share2,
-	Shield,
-	Sparkles,
-	Video,
+  BarChart3,
+  Database,
+  Globe,
+  Headphones,
+  Infinity,
+  Lock,
+  Minus,
+  Plus,
+  Share2,
+  Shield,
+  Sparkles,
+  Video,
 } from "lucide-react";
 import { useRouter } from "next/navigation";
 import { memo, useState } from "react";
 import { toast } from "sonner";
 
 interface UpgradeModalProps {
-	open: boolean;
-	onOpenChange: (open: boolean) => void;
+  open: boolean;
+  onOpenChange: (open: boolean) => void;
 }
 
 const modalVariants = {
-	hidden: {
-		opacity: 0,
-		scale: 0.95,
-		y: 10,
-	},
-	visible: {
-		opacity: 1,
-		scale: 1,
-		y: 0,
-		transition: {
-			type: "spring",
-			duration: 0.4,
-			damping: 25,
-			stiffness: 500,
-		},
-	},
-	exit: {
-		opacity: 0,
-		scale: 0.95,
-		y: 10,
-		transition: {
-			duration: 0.2,
-		},
-	},
+  hidden: {
+    opacity: 0,
+    scale: 0.95,
+    y: 10,
+  },
+  visible: {
+    opacity: 1,
+    scale: 1,
+    y: 0,
+    transition: {
+      type: "spring",
+      duration: 0.4,
+      damping: 25,
+      stiffness: 500,
+    },
+  },
+  exit: {
+    opacity: 0,
+    scale: 0.95,
+    y: 10,
+    transition: {
+      duration: 0.2,
+    },
+  },
 };
 
 export const UpgradeModal = ({ open, onOpenChange }: UpgradeModalProps) => {
-	if (buildEnv.NEXT_PUBLIC_IS_CAP !== "true") return;
+  if (buildEnv.NEXT_PUBLIC_IS_CAP !== "true") return;
 
-	const [proLoading, setProLoading] = useState(false);
-	const [isAnnual, setIsAnnual] = useState(true);
-	const [proQuantity, setProQuantity] = useState(1);
-	const { push } = useRouter();
+  const [proLoading, setProLoading] = useState(false);
+  const [isAnnual, setIsAnnual] = useState(true);
+  const [proQuantity, setProQuantity] = useState(1);
+  const { push } = useRouter();
 
-	const pricePerUser = isAnnual ? 6 : 9;
-	const totalPrice = pricePerUser * proQuantity;
-	const billingText = isAnnual ? "billed annually" : "billed monthly";
+  const pricePerUser = isAnnual ? 8.16 : 12;
+  const totalPrice = pricePerUser * proQuantity;
+  const billingText = isAnnual ? "billed annually" : "billed monthly";
 
-	useRive({
-		src: "/rive/main.riv",
-		artboard: "cap-pro-modal",
-		animations: ["animation"],
-		layout: new Layout({
-			fit: Fit.Cover,
-		}),
-		autoplay: true,
-	});
+  useRive({
+    src: "/rive/main.riv",
+    artboard: "cap-pro-modal",
+    animations: ["animation"],
+    layout: new Layout({
+      fit: Fit.Cover,
+    }),
+    autoplay: true,
+  });
 
-	const iconStyling = "text-blue-500 size-[18px]";
-	const proFeatures = [
-		{
-			icon: <Globe className={iconStyling} />,
-			title: "Custom domain",
-			description: "Connect your own domain to Cap",
-		},
-		{
-			icon: <Share2 className={iconStyling} />,
-			title: "Unlimited sharing",
-			description: "Cloud storage & shareable links",
-		},
-		{
-			icon: <Sparkles className={iconStyling} />,
-			title: "Cap AI",
-			description: "Automatic video chapters, summaries & more",
-		},
-		{
-			icon: <Lock className={iconStyling} />,
-			title: "Password protected videos",
-			description: "Enhanced security for your content",
-		},
-		{
-			icon: <Database className={iconStyling} />,
-			title: "Custom storage",
-			description: "Connect your own S3 bucket",
-		},
-		{
-			icon: <Shield className={iconStyling} />,
-			title: "Commercial license",
-			description: "Commercial license for desktop app automatically included",
-		},
-		{
-			icon: <Video className={iconStyling} />,
-			title: "Upload videos",
-			description: "Upload custom videos directly to Cap",
-		},
-		{
-			icon: <Infinity className={iconStyling} />,
-			title: "Unlimited views",
-			description: "No limits on video views",
-		},
-		{
-			icon: <BarChart3 className={iconStyling} />,
-			title: "Analytics",
-			description: "Video viewing insights",
-		},
-		{
-			icon: <Headphones className={iconStyling} />,
-			title: "Priority support",
-			description: "Get help when you need it",
-		},
-	];
+  const iconStyling = "text-blue-500 size-[18px]";
+  const proFeatures = [
+    {
+      icon: <Globe className={iconStyling} />,
+      title: "Custom domain",
+      description: "Connect your own domain to Cap",
+    },
+    {
+      icon: <Share2 className={iconStyling} />,
+      title: "Unlimited sharing",
+      description: "Cloud storage & shareable links",
+    },
+    {
+      icon: <Sparkles className={iconStyling} />,
+      title: "Cap AI",
+      description: "Automatic video chapters, summaries & more",
+    },
+    {
+      icon: <Lock className={iconStyling} />,
+      title: "Password protected videos",
+      description: "Enhanced security for your content",
+    },
+    {
+      icon: <Database className={iconStyling} />,
+      title: "Custom storage",
+      description: "Connect your own S3 bucket",
+    },
+    {
+      icon: <Shield className={iconStyling} />,
+      title: "Commercial license",
+      description: "Commercial license for desktop app automatically included",
+    },
+    {
+      icon: <Video className={iconStyling} />,
+      title: "Upload videos",
+      description: "Upload custom videos directly to Cap",
+    },
+    {
+      icon: <Infinity className={iconStyling} />,
+      title: "Unlimited views",
+      description: "No limits on video views",
+    },
+    {
+      icon: <BarChart3 className={iconStyling} />,
+      title: "Analytics",
+      description: "Video viewing insights",
+    },
+    {
+      icon: <Headphones className={iconStyling} />,
+      title: "Priority support",
+      description: "Get help when you need it",
+    },
+  ];
 
-	const planCheckout = async () => {
-		setProLoading(true);
+  const planCheckout = async () => {
+    setProLoading(true);
 
-		const planId = getProPlanId(isAnnual ? "yearly" : "monthly");
+    const planId = getProPlanId(isAnnual ? "yearly" : "monthly");
 
-		const response = await fetch(`/api/settings/billing/subscribe`, {
-			method: "POST",
-			headers: {
-				"Content-Type": "application/json",
-			},
-			body: JSON.stringify({ priceId: planId, quantity: proQuantity }),
-		});
-		const data = await response.json();
+    const response = await fetch(`/api/settings/billing/subscribe`, {
+      method: "POST",
+      headers: {
+        "Content-Type": "application/json",
+      },
+      body: JSON.stringify({ priceId: planId, quantity: proQuantity }),
+    });
+    const data = await response.json();
 
-		if (data.auth === false) {
-			localStorage.setItem("pendingPriceId", planId);
-			localStorage.setItem("pendingQuantity", proQuantity.toString());
-			push(`/login?next=/dashboard`);
-			return;
-		}
+    if (data.auth === false) {
+      localStorage.setItem("pendingPriceId", planId);
+      localStorage.setItem("pendingQuantity", proQuantity.toString());
+      push(`/login?next=/dashboard`);
+      return;
+    }
 
-		if (data.subscription === true) {
-			toast.success("You are already on the Cap Pro plan");
-			onOpenChange(false);
-		}
+    if (data.subscription === true) {
+      toast.success("You are already on the Cap Pro plan");
+      onOpenChange(false);
+    }
 
-		if (data.url) {
-			window.location.href = data.url;
-		}
+    if (data.url) {
+      window.location.href = data.url;
+    }
 
-		setProLoading(false);
-	};
+    setProLoading(false);
+  };
 
-	return (
-		<Dialog open={open} onOpenChange={onOpenChange}>
-			<DialogContent
-				className="sm:max-w-[1100px] w-[calc(100%-20px)] custom-scroll bg-gray-2 border
+  return (
+    <Dialog open={open} onOpenChange={onOpenChange}>
+      <DialogContent
+        className="sm:max-w-[1100px] w-[calc(100%-20px)] custom-scroll bg-gray-2 border
       border-gray-4 overflow-y-auto md:overflow-hidden max-h-[90vh] p-0"
-			>
-				<AnimatePresence mode="wait">
-					{open && (
-						<motion.div
-							className="flex relative flex-col h-full md:flex-row"
-							variants={modalVariants}
-							initial="hidden"
-							animate="visible"
-							exit="exit"
-						>
-							<div className="flex relative flex-col flex-1 justify-between items-end self-stretch border-r-0 border-b md:border-b-0 md:border-r border-gray-4">
-								<div className="h-[275px] border-b border-gray-4 w-full overflow-hidden">
-									<ProRiveArt />
-								</div>
-								<div className="flex relative flex-col flex-1 justify-center items-center py-6 w-full">
-									<div className="flex flex-col items-center">
-										<h1 className="text-3xl font-medium text-gray-12">
-											Upgrade to Cap Pro
-										</h1>
-									</div>
-									<p className="mt-1 text-lg text-center text-gray-11">
-										You can cancel anytime. Early adopter pricing locked in.
-									</p>
+      >
+        <AnimatePresence mode="wait">
+          {open && (
+            <motion.div
+              className="flex relative flex-col h-full md:flex-row"
+              variants={modalVariants}
+              initial="hidden"
+              animate="visible"
+              exit="exit"
+            >
+              <div className="flex relative flex-col flex-1 justify-between items-end self-stretch border-r-0 border-b md:border-b-0 md:border-r border-gray-4">
+                <div className="h-[275px] border-b border-gray-4 w-full overflow-hidden">
+                  <ProRiveArt />
+                </div>
+                <div className="flex relative flex-col flex-1 justify-center items-center py-6 w-full">
+                  <div className="flex flex-col items-center">
+                    <h1 className="text-3xl font-medium text-gray-12">
+                      Upgrade to Cap Pro
+                    </h1>
+                  </div>
+                  <p className="mt-1 text-lg text-center text-gray-11">
+                    You can cancel anytime. Early adopter pricing locked in.
+                  </p>
 
-									<div className="flex flex-col items-center mt-3 mb-4 w-full">
-										<div className="flex flex-col items-center mb-1 sm:items-end sm:flex-row">
-											<NumberFlow
-												value={totalPrice}
-												className="text-3xl font-medium tabular-nums text-gray-12"
-												format={{
-													style: "currency",
-													currency: "USD",
-												}}
-											/>
-											<span className="mb-2 ml-2 text-gray-11">
-												{proQuantity === 1 ? (
-													`per user, ${billingText}`
-												) : (
-													<>
-														for{" "}
-														<NumberFlow
-															value={proQuantity}
-															className="tabular-nums text-gray-12"
-														/>{" "}
-														users, {billingText}
-													</>
-												)}
-											</span>
-										</div>
+                  <div className="flex flex-col items-center mt-3 mb-4 w-full">
+                    <div className="flex flex-col items-center mb-1 sm:items-end sm:flex-row">
+                      <NumberFlow
+                        value={totalPrice}
+                        className="text-3xl font-medium tabular-nums text-gray-12"
+                        format={{
+                          style: "currency",
+                          currency: "USD",
+                        }}
+                      />
+                      <span className="mb-2 ml-2 text-gray-11">
+                        {proQuantity === 1 ? (
+                          `per user, ${billingText}`
+                        ) : (
+                          <>
+                            for{" "}
+                            <NumberFlow
+                              value={proQuantity}
+                              className="tabular-nums text-gray-12"
+                            />{" "}
+                            users, {billingText}
+                          </>
+                        )}
+                      </span>
+                    </div>
 
-										<div className="flex flex-col gap-6 justify-evenly items-center mt-8 w-full max-w-md sm:gap-10 sm:flex-row">
-											<div className="flex gap-3 items-center">
-												<span className="text-gray-12">Annual billing</span>
-												<Switch
-													checked={isAnnual}
-													onCheckedChange={() => setIsAnnual(!isAnnual)}
-												/>
-											</div>
+                    <div className="flex flex-col gap-6 justify-evenly items-center mt-8 w-full max-w-md sm:gap-10 sm:flex-row">
+                      <div className="flex gap-3 items-center">
+                        <span className="text-gray-12">Annual billing</span>
+                        <Switch
+                          checked={isAnnual}
+                          onCheckedChange={() => setIsAnnual(!isAnnual)}
+                        />
+                      </div>
 
-											<div className="flex items-center">
-												<span className="mr-3 text-gray-12">Users:</span>
-												<div className="flex items-center">
-													<button
-														type="button"
-														onClick={() =>
-															proQuantity > 1 && setProQuantity(proQuantity - 1)
-														}
-														className="flex justify-center items-center w-8 h-8 rounded-l-md bg-gray-4 hover:bg-gray-5"
-														disabled={proQuantity <= 1}
-													>
-														<Minus className="w-4 h-4 text-gray-12" />
-													</button>
-													<NumberFlow
-														value={proQuantity}
-														className="mx-auto w-6 text-sm tabular-nums text-center text-gray-12"
-													/>
-													<button
-														type="button"
-														onClick={() => setProQuantity(proQuantity + 1)}
-														className="flex justify-center items-center w-8 h-8 rounded-r-md bg-gray-4 hover:bg-gray-5"
-													>
-														<Plus className="w-4 h-4 text-gray-12" />
-													</button>
-												</div>
-											</div>
-										</div>
-									</div>
+                      <div className="flex items-center">
+                        <span className="mr-3 text-gray-12">Users:</span>
+                        <div className="flex items-center">
+                          <button
+                            type="button"
+                            onClick={() =>
+                              proQuantity > 1 && setProQuantity(proQuantity - 1)
+                            }
+                            className="flex justify-center items-center w-8 h-8 rounded-l-md bg-gray-4 hover:bg-gray-5"
+                            disabled={proQuantity <= 1}
+                          >
+                            <Minus className="w-4 h-4 text-gray-12" />
+                          </button>
+                          <NumberFlow
+                            value={proQuantity}
+                            className="mx-auto w-6 text-sm tabular-nums text-center text-gray-12"
+                          />
+                          <button
+                            type="button"
+                            onClick={() => setProQuantity(proQuantity + 1)}
+                            className="flex justify-center items-center w-8 h-8 rounded-r-md bg-gray-4 hover:bg-gray-5"
+                          >
+                            <Plus className="w-4 h-4 text-gray-12" />
+                          </button>
+                        </div>
+                      </div>
+                    </div>
+                  </div>
 
-									<Button
-										variant="blue"
-										onClick={planCheckout}
-										className="mt-5 w-full max-w-sm h-14 text-lg"
-										disabled={proLoading}
-									>
-										{proLoading ? "Loading..." : "Upgrade to Cap Pro"}
-									</Button>
-									<button
-										type="button"
-										className="mt-2 w-full max-w-sm h-14 text-base rounded-xl hover:underline text-gray-11 hover:text-gray-12"
-										onClick={() => onOpenChange(false)}
-									>
-										Skip
-									</button>
-								</div>
-							</div>
+                  <Button
+                    variant="blue"
+                    onClick={planCheckout}
+                    className="mt-5 w-full max-w-sm h-14 text-lg"
+                    disabled={proLoading}
+                  >
+                    {proLoading ? "Loading..." : "Upgrade to Cap Pro"}
+                  </Button>
+                  <button
+                    type="button"
+                    className="mt-2 w-full max-w-sm h-14 text-base rounded-xl hover:underline text-gray-11 hover:text-gray-12"
+                    onClick={() => onOpenChange(false)}
+                  >
+                    Skip
+                  </button>
+                </div>
+              </div>
 
-							<div className="flex flex-1 justify-center items-center self-stretch p-8 bg-transparent md:bg-gray-3">
-								<div className="grid grid-cols-1 gap-8 md:grid-cols-2">
-									{proFeatures.map((feature, index) => (
-										<div
-											key={index.toString()}
-											className="flex flex-col justify-center items-center"
-										>
-											<div className="mb-3.5 bg-gray-5 rounded-full size-10 flex items-center justify-center">
-												{feature.icon}
-											</div>
-											<h3 className="text-base font-medium text-center text-gray-12">
-												{feature.title}
-											</h3>
-											<p className="text-sm text-center text-gray-11">
-												{feature.description}
-											</p>
-										</div>
-									))}
-								</div>
-							</div>
-						</motion.div>
-					)}
-				</AnimatePresence>
-			</DialogContent>
-		</Dialog>
-	);
+              <div className="flex flex-1 justify-center items-center self-stretch p-8 bg-transparent md:bg-gray-3">
+                <div className="grid grid-cols-1 gap-8 md:grid-cols-2">
+                  {proFeatures.map((feature, index) => (
+                    <div
+                      key={index.toString()}
+                      className="flex flex-col justify-center items-center"
+                    >
+                      <div className="mb-3.5 bg-gray-5 rounded-full size-10 flex items-center justify-center">
+                        {feature.icon}
+                      </div>
+                      <h3 className="text-base font-medium text-center text-gray-12">
+                        {feature.title}
+                      </h3>
+                      <p className="text-sm text-center text-gray-11">
+                        {feature.description}
+                      </p>
+                    </div>
+                  ))}
+                </div>
+              </div>
+            </motion.div>
+          )}
+        </AnimatePresence>
+      </DialogContent>
+    </Dialog>
+  );
 };
 
 const ProRiveArt = memo(() => {
-	const { RiveComponent: ProModal } = useRive({
-		src: "/rive/main.riv",
-		artboard: "cap-pro-modal",
-		animations: ["animation"],
-		layout: new Layout({
-			fit: Fit.Cover,
-		}),
-		autoplay: true,
-	});
+  const { RiveComponent: ProModal } = useRive({
+    src: "/rive/main.riv",
+    artboard: "cap-pro-modal",
+    animations: ["animation"],
+    layout: new Layout({
+      fit: Fit.Cover,
+    }),
+    autoplay: true,
+  });
 
-	return <ProModal className="w-full h-full" />;
+  return <ProModal className="w-full h-full" />;
 });
diff --git a/apps/web/components/pages/HomePage/Pricing/ProCard.tsx b/apps/web/components/pages/HomePage/Pricing/ProCard.tsx
index cd53a3c037..4bbf1acee7 100644
--- a/apps/web/components/pages/HomePage/Pricing/ProCard.tsx
+++ b/apps/web/components/pages/HomePage/Pricing/ProCard.tsx
@@ -11,255 +11,255 @@ import { homepageCopy } from "../../../../data/homepage-copy";
 import { ProArt, type ProArtRef } from "./ProArt";
 
 export const ProCard = () => {
-	const [users, setUsers] = useState(1);
-	const [isAnnually, setIsAnnually] = useState(true);
-	const [proLoading, setProLoading] = useState(false);
-	const [guestLoading, setGuestLoading] = useState(false);
-	const proArtRef = useRef<ProArtRef>(null);
-	const { push } = useRouter();
+  const [users, setUsers] = useState(1);
+  const [isAnnually, setIsAnnually] = useState(true);
+  const [proLoading, setProLoading] = useState(false);
+  const [guestLoading, setGuestLoading] = useState(false);
+  const proArtRef = useRef<ProArtRef>(null);
+  const { push } = useRouter();
 
-	const CAP_PRO_ANNUAL_PRICE_PER_USER = homepageCopy.pricing.pro.pricing.annual;
-	const CAP_PRO_MONTHLY_PRICE_PER_USER =
-		homepageCopy.pricing.pro.pricing.monthly;
+  const CAP_PRO_ANNUAL_PRICE_PER_USER = homepageCopy.pricing.pro.pricing.annual;
+  const CAP_PRO_MONTHLY_PRICE_PER_USER =
+    homepageCopy.pricing.pro.pricing.monthly;
 
-	const currentTotalPricePro =
-		users *
-		(isAnnually
-			? CAP_PRO_ANNUAL_PRICE_PER_USER
-			: CAP_PRO_MONTHLY_PRICE_PER_USER);
-	const billingCycleTextPro = isAnnually
-		? "per user, billed annually"
-		: "per user, billed monthly";
+  const currentTotalPricePro =
+    users *
+    (isAnnually
+      ? CAP_PRO_ANNUAL_PRICE_PER_USER
+      : CAP_PRO_MONTHLY_PRICE_PER_USER);
+  const billingCycleTextPro = isAnnually
+    ? "per user, billed annually"
+    : "per user, billed monthly";
 
-	const incrementUsers = () => setUsers((prev) => prev + 1);
-	const decrementUsers = () => setUsers((prev) => (prev > 1 ? prev - 1 : 1));
+  const incrementUsers = () => setUsers((prev) => prev + 1);
+  const decrementUsers = () => setUsers((prev) => (prev > 1 ? prev - 1 : 1));
 
-	const guestCheckout = async (planId: string) => {
-		setGuestLoading(true);
+  const guestCheckout = async (planId: string) => {
+    setGuestLoading(true);
 
-		try {
-			const response = await fetch(`/api/settings/billing/guest-checkout`, {
-				method: "POST",
-				headers: {
-					"Content-Type": "application/json",
-				},
-				body: JSON.stringify({ priceId: planId, quantity: users }),
-			});
-			const data = await response.json();
+    try {
+      const response = await fetch(`/api/settings/billing/guest-checkout`, {
+        method: "POST",
+        headers: {
+          "Content-Type": "application/json",
+        },
+        body: JSON.stringify({ priceId: planId, quantity: users }),
+      });
+      const data = await response.json();
 
-			if (data.url) {
-				window.location.href = data.url;
-			} else {
-				toast.error("Failed to create checkout session");
-			}
-		} catch (error) {
-			toast.error("An error occurred. Please try again.");
-		} finally {
-			setGuestLoading(false);
-		}
-	};
+      if (data.url) {
+        window.location.href = data.url;
+      } else {
+        toast.error("Failed to create checkout session");
+      }
+    } catch (error) {
+      toast.error("An error occurred. Please try again.");
+    } finally {
+      setGuestLoading(false);
+    }
+  };
 
-	const planCheckout = async (planId?: string) => {
-		setProLoading(true);
+  const planCheckout = async (planId?: string) => {
+    setProLoading(true);
 
-		if (!planId) {
-			planId = getProPlanId(isAnnually ? "yearly" : "monthly");
-		}
+    if (!planId) {
+      planId = getProPlanId(isAnnually ? "yearly" : "monthly");
+    }
 
-		const response = await fetch(`/api/settings/billing/subscribe`, {
-			method: "POST",
-			headers: {
-				"Content-Type": "application/json",
-			},
-			body: JSON.stringify({ priceId: planId, quantity: users }),
-		});
-		const data = await response.json();
+    const response = await fetch(`/api/settings/billing/subscribe`, {
+      method: "POST",
+      headers: {
+        "Content-Type": "application/json",
+      },
+      body: JSON.stringify({ priceId: planId, quantity: users }),
+    });
+    const data = await response.json();
 
-		if (data.auth === false) {
-			// User not authenticated, do guest checkout
-			setProLoading(false);
-			await guestCheckout(planId);
-			return;
-		}
+    if (data.auth === false) {
+      // User not authenticated, do guest checkout
+      setProLoading(false);
+      await guestCheckout(planId);
+      return;
+    }
 
-		if (data.subscription === true) {
-			toast.success("You are already on the Cap Pro plan");
-		}
+    if (data.subscription === true) {
+      toast.success("You are already on the Cap Pro plan");
+    }
 
-		if (data.url) {
-			window.location.href = data.url;
-		}
+    if (data.url) {
+      window.location.href = data.url;
+    }
 
-		setProLoading(false);
-	};
+    setProLoading(false);
+  };
 
-	return (
-		<div
-			onMouseEnter={() => {
-				proArtRef.current?.playHoverAnimation();
-			}}
-			onMouseLeave={() => {
-				proArtRef.current?.playDefaultAnimation();
-			}}
-			className="flex relative flex-col flex-1 justify-between p-8 text-white rounded-2xl shadow-2xl bg-gray-12"
-		>
-			<div>
-				<div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
-					<span className="rounded-full font-mono bg-blue-500 px-4 py-1.5 text-xs uppercase text-gray-1">
-						{homepageCopy.pricing.pro.badge}
-					</span>
-				</div>
-				<div className="md:h-[300px]">
-					<ProArt ref={proArtRef} />
-					<h3 className="mb-2 text-2xl text-center">
-						{homepageCopy.pricing.pro.title}
-					</h3>
-					<p className="mb-6 text-base text-center text-gray-8">
-						{homepageCopy.pricing.pro.description}
-					</p>
-				</div>
+  return (
+    <div
+      onMouseEnter={() => {
+        proArtRef.current?.playHoverAnimation();
+      }}
+      onMouseLeave={() => {
+        proArtRef.current?.playDefaultAnimation();
+      }}
+      className="flex relative flex-col flex-1 justify-between p-8 text-white rounded-2xl shadow-2xl bg-gray-12"
+    >
+      <div>
+        <div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
+          <span className="rounded-full font-mono bg-blue-500 px-4 py-1.5 text-xs uppercase text-gray-1">
+            {homepageCopy.pricing.pro.badge}
+          </span>
+        </div>
+        <div className="md:h-[300px]">
+          <ProArt ref={proArtRef} />
+          <h3 className="mb-2 text-2xl text-center">
+            {homepageCopy.pricing.pro.title}
+          </h3>
+          <p className="mb-6 text-base text-center text-gray-8">
+            {homepageCopy.pricing.pro.description}
+          </p>
+        </div>
 
-				<div className="mb-6 text-center">
-					<span className="mr-2 text-5xl tabular-nums text-gray-1">
-						$<NumberFlow suffix="/mo" value={currentTotalPricePro} />
-					</span>
-					<span className="text-lg tabular-nums text-gray-8">
-						{" "}
-						{billingCycleTextPro}
-					</span>
-					{isAnnually ? (
-						<p className="text-lg text-gray-8">
-							or,{" "}
-							<NumberFlow
-								value={9 * users}
-								className="text-lg tabular-nums"
-								format={{
-									notation: "compact",
-									style: "currency",
-									currency: "USD",
-								}}
-								suffix="/mo"
-							/>{" "}
-							{users === 1 ? (
-								"per user, "
-							) : (
-								<>
-									for{" "}
-									<NumberFlow value={users} className="text-lg tabular-nums" />{" "}
-									users,{" "}
-								</>
-							)}
-							billed monthly
-						</p>
-					) : (
-						<p className="text-lg text-gray-8">
-							or,{" "}
-							<NumberFlow
-								value={6 * users}
-								className="text-lg tabular-nums"
-								format={{
-									notation: "compact",
-									style: "currency",
-									currency: "USD",
-								}}
-								suffix="/mo"
-							/>{" "}
-							{users === 1 ? (
-								"per user, "
-							) : (
-								<>
-									for{" "}
-									<NumberFlow value={users} className="text-lg tabular-nums" />{" "}
-									users,{" "}
-								</>
-							)}
-							billed annually
-						</p>
-					)}
-				</div>
+        <div className="mb-6 text-center">
+          <span className="mr-2 text-5xl tabular-nums text-gray-1">
+            $<NumberFlow suffix="/mo" value={currentTotalPricePro} />
+          </span>
+          <span className="text-lg tabular-nums text-gray-8">
+            {" "}
+            {billingCycleTextPro}
+          </span>
+          {isAnnually ? (
+            <p className="text-lg text-gray-8">
+              or,{" "}
+              <NumberFlow
+                value={CAP_PRO_MONTHLY_PRICE_PER_USER * users}
+                className="text-lg tabular-nums"
+                format={{
+                  notation: "compact",
+                  style: "currency",
+                  currency: "USD",
+                }}
+                suffix="/mo"
+              />{" "}
+              {users === 1 ? (
+                "per user, "
+              ) : (
+                <>
+                  for{" "}
+                  <NumberFlow value={users} className="text-lg tabular-nums" />{" "}
+                  users,{" "}
+                </>
+              )}
+              billed monthly
+            </p>
+          ) : (
+            <p className="text-lg text-gray-8">
+              or,{" "}
+              <NumberFlow
+                value={CAP_PRO_ANNUAL_PRICE_PER_USER * users}
+                className="text-lg tabular-nums"
+                format={{
+                  notation: "compact",
+                  style: "currency",
+                  currency: "USD",
+                }}
+                suffix="/mo"
+              />{" "}
+              {users === 1 ? (
+                "per user, "
+              ) : (
+                <>
+                  for{" "}
+                  <NumberFlow value={users} className="text-lg tabular-nums" />{" "}
+                  users,{" "}
+                </>
+              )}
+              billed annually
+            </p>
+          )}
+        </div>
 
-				<div className="flex flex-wrap gap-5 justify-center items-center p-5 my-8 w-full rounded-xl border xs:gap-3 xs:p-3 xs:rounded-full xs:justify-between bg-zinc-700/50 border-zinc-700">
-					<div className="flex gap-3 justify-center items-center">
-						<p className="text-base text-gray-1">
-							{homepageCopy.pricing.pro.labels.users}
-						</p>
-						<div className="flex items-center">
-							<Button
-								onClick={decrementUsers}
-								className="px-1.5 py-1.5 bg-gray-1 hover:bg-gray-3 min-w-fit h-fit"
-								aria-label="Decrease user count"
-							>
-								<FontAwesomeIcon
-									icon={faMinus}
-									className="text-gray-12 size-3"
-								/>
-							</Button>
-							<span className="w-8 font-medium tabular-nums text-center text-white">
-								<NumberFlow value={users} />
-							</span>
-							<Button
-								onClick={incrementUsers}
-								className="px-1.5 py-1.5 bg-gray-1 hover:bg-gray-3 min-w-fit h-fit"
-								aria-label="Increase user count"
-							>
-								<FontAwesomeIcon
-									icon={faPlus}
-									className="text-gray-12 size-3"
-								/>
-							</Button>
-						</div>
-					</div>
+        <div className="flex flex-wrap gap-5 justify-center items-center p-5 my-8 w-full rounded-xl border xs:gap-3 xs:p-3 xs:rounded-full xs:justify-between bg-zinc-700/50 border-zinc-700">
+          <div className="flex gap-3 justify-center items-center">
+            <p className="text-base text-gray-1">
+              {homepageCopy.pricing.pro.labels.users}
+            </p>
+            <div className="flex items-center">
+              <Button
+                onClick={decrementUsers}
+                className="px-1.5 py-1.5 bg-gray-1 hover:bg-gray-3 min-w-fit h-fit"
+                aria-label="Decrease user count"
+              >
+                <FontAwesomeIcon
+                  icon={faMinus}
+                  className="text-gray-12 size-3"
+                />
+              </Button>
+              <span className="w-8 font-medium tabular-nums text-center text-white">
+                <NumberFlow value={users} />
+              </span>
+              <Button
+                onClick={incrementUsers}
+                className="px-1.5 py-1.5 bg-gray-1 hover:bg-gray-3 min-w-fit h-fit"
+                aria-label="Increase user count"
+              >
+                <FontAwesomeIcon
+                  icon={faPlus}
+                  className="text-gray-12 size-3"
+                />
+              </Button>
+            </div>
+          </div>
 
-					<div className="flex justify-center items-center">
-						<div className="flex gap-2 items-center">
-							<span
-								className={clsx(
-									"text-md",
-									!isAnnually ? "text-white" : "text-gray-8",
-								)}
-							>
-								{homepageCopy.pricing.pro.labels.monthly}
-							</span>
-							<Switch
-								checked={isAnnually}
-								onCheckedChange={setIsAnnually}
-								aria-label="Billing Cycle For Pro"
-								id="billing-cycle-cap-pro"
-							/>
-							<span
-								className={clsx(
-									"text-md",
-									isAnnually ? "text-white" : "text-gray-8",
-								)}
-							>
-								{homepageCopy.pricing.pro.labels.annually}
-							</span>
-						</div>
-					</div>
-				</div>
+          <div className="flex justify-center items-center">
+            <div className="flex gap-2 items-center">
+              <span
+                className={clsx(
+                  "text-md",
+                  !isAnnually ? "text-white" : "text-gray-8"
+                )}
+              >
+                {homepageCopy.pricing.pro.labels.monthly}
+              </span>
+              <Switch
+                checked={isAnnually}
+                onCheckedChange={setIsAnnually}
+                aria-label="Billing Cycle For Pro"
+                id="billing-cycle-cap-pro"
+              />
+              <span
+                className={clsx(
+                  "text-md",
+                  isAnnually ? "text-white" : "text-gray-8"
+                )}
+              >
+                {homepageCopy.pricing.pro.labels.annually}
+              </span>
+            </div>
+          </div>
+        </div>
 
-				<ul className="mb-8 space-y-3 text-base">
-					{homepageCopy.pricing.pro.features.map((feature) => (
-						<li key={feature} className="flex items-center text-gray-1">
-							<FontAwesomeIcon icon={faCheck} className="mr-2 text-gray-1" />
-							{feature}
-						</li>
-					))}
-				</ul>
-			</div>
+        <ul className="mb-8 space-y-3 text-base">
+          {homepageCopy.pricing.pro.features.map((feature) => (
+            <li key={feature} className="flex items-center text-gray-1">
+              <FontAwesomeIcon icon={faCheck} className="mr-2 text-gray-1" />
+              {feature}
+            </li>
+          ))}
+        </ul>
+      </div>
 
-			<Button
-				variant="blue"
-				size="lg"
-				onClick={() => planCheckout()}
-				disabled={proLoading || guestLoading}
-				className="w-full font-medium"
-				aria-label="Purchase Cap Pro License"
-			>
-				{proLoading || guestLoading
-					? "Loading..."
-					: homepageCopy.pricing.pro.cta}
-			</Button>
-		</div>
-	);
+      <Button
+        variant="blue"
+        size="lg"
+        onClick={() => planCheckout()}
+        disabled={proLoading || guestLoading}
+        className="w-full font-medium"
+        aria-label="Purchase Cap Pro License"
+      >
+        {proLoading || guestLoading
+          ? "Loading..."
+          : homepageCopy.pricing.pro.cta}
+      </Button>
+    </div>
+  );
 };
diff --git a/apps/web/data/homepage-copy.ts b/apps/web/data/homepage-copy.ts
index 22e0b6c72b..fa179ebb4e 100644
--- a/apps/web/data/homepage-copy.ts
+++ b/apps/web/data/homepage-copy.ts
@@ -238,8 +238,8 @@ export const homepageCopy: HomePageCopy = {
 			],
 			cta: "Get started",
 			pricing: {
-				annual: 6,
-				monthly: 9,
+				annual: 8.16,
+				monthly: 12,
 			},
 			labels: {
 				users: "Per user",

From 76676d7745b4db2fe5222268ae353f3d70c42260 Mon Sep 17 00:00:00 2001
From: Richie McIlroy <33632126+richiemcilroy@users.noreply.github.com>
Date: Mon, 1 Sep 2025 18:06:38 +0100
Subject: [PATCH 3/3] lint

---
 .../src/routes/(window-chrome)/upgrade.tsx    | 1128 ++++++++---------
 apps/web/components/UpgradeModal.tsx          |  550 ++++----
 apps/web/components/pages/FaqPage.tsx         |  104 +-
 .../pages/HomePage/Pricing/ProCard.tsx        |  464 +++----
 .../pages/seo/LoomAlternativePage.tsx         |  348 ++---
 5 files changed, 1297 insertions(+), 1297 deletions(-)

diff --git a/apps/desktop/src/routes/(window-chrome)/upgrade.tsx b/apps/desktop/src/routes/(window-chrome)/upgrade.tsx
index 58d7ce85c9..499323e32c 100644
--- a/apps/desktop/src/routes/(window-chrome)/upgrade.tsx
+++ b/apps/desktop/src/routes/(window-chrome)/upgrade.tsx
@@ -14,14 +14,14 @@ import { authStore } from "../../store";
 import { Dialog, DialogContent, Input } from "../editor/ui";
 
 const proFeatures = [
-  "Commercial License Included",
-  "Unlimited cloud storage & Shareable links",
-  "Connect custom S3 storage bucket",
-  "Advanced teams features",
-  "Unlimited views",
-  "Password protected videos",
-  "Advanced analytics",
-  "Priority support",
+	"Commercial License Included",
+	"Unlimited cloud storage & Shareable links",
+	"Connect custom S3 storage bucket",
+	"Advanced teams features",
+	"Unlimited views",
+	"Password protected videos",
+	"Advanced analytics",
+	"Priority support",
 ];
 
 import { RuntimeLoader } from "@rive-app/canvas";
@@ -31,566 +31,566 @@ import { createSignInMutation } from "~/utils/auth";
 RuntimeLoader.setWasmUrl(riveWASMResource);
 
 export default function Page() {
-  const [isProAnnual, setIsProAnnual] = createSignal(true);
-  const [isCommercialAnnual, setIsCommercialAnnual] = createSignal(true);
-  const [upgradeComplete, setUpgradeComplete] = createSignal(false);
-  const [loading, setLoading] = createSignal(false);
-  const signIn = createSignInMutation();
-  const license = createLicenseQuery();
-  const [openLicenseDialog, setOpenLicenseDialog] = createSignal(false);
-
-  const resetLicense = createMutation(() => ({
-    mutationFn: async () => {
-      const generalSettings = await generalSettingsStore.get();
-      if (
-        !generalSettings?.instanceId ||
-        !license.data ||
-        license.data.type !== "commercial"
-      ) {
-        throw new Error("No instance ID or valid commercial license found");
-      }
-
-      const resp = await licenseApiClient.activateCommercialLicense({
-        headers: {
-          licensekey: license.data.licenseKey,
-          instanceid: generalSettings.instanceId,
-        },
-        body: { reset: true },
-      });
-
-      if (resp.status !== 200) {
-        if (
-          typeof resp.body === "object" &&
-          resp.body &&
-          "message" in resp.body
-        )
-          throw resp.body.message;
-        throw new Error((resp.body as any).toString());
-      }
-    },
-    onSuccess: async () => {
-      await generalSettingsStore.set({
-        commercialLicense: undefined,
-      });
-      license.refetch();
-    },
-  }));
-
-  const openCheckoutInExternalBrowser = async () => {
-    console.log("Opening checkout in external browser");
-    setLoading(true);
-
-    try {
-      const auth = await authStore.get();
-
-      console.log({ auth });
-      if (!auth) {
-        console.log("No auth found, starting sign in flow");
-        await signIn.mutateAsync(new AbortController());
-      }
-
-      const planId = getProPlanId(isProAnnual() ? "yearly" : "monthly");
-      console.log("Getting checkout URL for plan:", planId);
-      const response = await apiClient.desktop.getProSubscribeURL({
-        body: { priceId: planId },
-        headers: await protectedHeaders(),
-      });
-
-      if (response.status === 200) {
-        console.log("Opening checkout URL in external browser");
-        commands.openExternalLink(response.body.url);
-        console.log("Minimizing upgrade window");
-        const window = await Window.getByLabel("upgrade");
-        if (window) await window.minimize();
-      } else {
-        console.error("Failed to get checkout URL, status:", response.status);
-      }
-    } catch (error) {
-      console.error("Error getting checkout URL:", error);
-    } finally {
-      setLoading(false);
-    }
-  };
-
-  const openCommercialCheckout = createMutation(() => ({
-    mutationFn: async () => {
-      const resp = await licenseApiClient.createCommercialCheckoutUrl({
-        body: { type: isCommercialAnnual() ? "yearly" : "lifetime" },
-      });
-
-      if (resp.status === 200) {
-        console.log("Opening checkout URL in external browser");
-        commands.openExternalLink(resp.body.url);
-        console.log("Minimizing upgrade window");
-        const window = await Window.getByLabel("upgrade");
-        if (window) {
-          await window.minimize();
-        }
-      } else {
-        throw resp.body;
-      }
-    },
-  }));
-
-  // onMount(async () => {
-  //   console.log("Component mounted");
-  //   const unsubscribeDeepLink = await onOpenUrl(async (urls) => {
-  //     console.log("Deep link received:", urls);
-  //     const isDevMode = import.meta.env.VITE_ENVIRONMENT === "development";
-  //     if (isDevMode) {
-  //       console.log("In dev mode, ignoring deep link");
-  //       return;
-  //     }
-
-  //     for (const url of urls) {
-  //       if (!url.includes("token=")) {
-  //         console.log("URL does not contain token, skipping");
-  //         return;
-  //       }
-
-  //       console.log("Processing auth URL");
-  //       const urlObject = new URL(url);
-  //       const token = urlObject.searchParams.get("token");
-  //       const user_id = urlObject.searchParams.get("user_id");
-  //       const expires = Number(urlObject.searchParams.get("expires"));
-
-  //       if (!token || !expires || !user_id) {
-  //         console.error("Invalid signin params");
-  //         throw new Error("Invalid signin params");
-  //       }
-
-  //       console.log("Setting auth store with new credentials");
-  //       const existingAuth = await authStore.get();
-  //       await authStore.set({
-  //         token,
-  //         user_id,
-  //         expires,
-  //         intercom_hash: existingAuth?.intercom_hash ?? "",
-  //         plan: {
-  //           upgraded: false,
-  //           last_checked: 0,
-  //           manual: existingAuth?.plan?.manual ?? false,
-  //         },
-  //       });
-
-  //       console.log("Identifying user in analytics");
-  //       identifyUser(user_id);
-  //       console.log("Tracking sign in event");
-  //       trackEvent("user_signed_in", { platform: "desktop" });
-
-  //       console.log("Reopening upgrade window");
-  //       await commands.showWindow("Upgrade");
-
-  //       console.log("Waiting for window to be ready");
-  //       await new Promise((resolve) => setTimeout(resolve, 500));
-
-  //       console.log("Getting upgrade window reference");
-  //       const upgradeWindow = await Window.getByLabel("upgrade");
-  //       if (upgradeWindow) {
-  //         try {
-  //           console.log("Setting focus on upgrade window");
-  //           await upgradeWindow.show();
-  //           await upgradeWindow.setFocus();
-  //         } catch (e) {
-  //           console.error("Failed to focus upgrade window:", e);
-  //         }
-  //       }
-
-  //       console.log("Getting checkout URL");
-  //       const planId = getProPlanId(isProAnnual() ? "yearly" : "monthly");
-  //       const response = await apiClient.desktop.getProSubscribeURL({
-  //         body: { priceId: planId },
-  //         headers: await protectedHeaders(),
-  //       });
-
-  //       if (response.status === 200) {
-  //         console.log("Opening checkout URL in external browser");
-  //         commands.openExternalLink(response.body.url);
-  //         console.log("Minimizing upgrade window");
-  //         if (upgradeWindow) {
-  //           await upgradeWindow.minimize();
-  //         }
-  //       }
-  //     }
-  //   });
-
-  //   onCleanup(() => {
-  //     console.log("Cleaning up deep link listener");
-  //     unsubscribeDeepLink();
-  //   });
-
-  //   console.log("Setting up upgrade status check interval");
-  //   const interval = setInterval(async () => {
-  //     console.log("Checking upgrade status");
-  //     const result = await commands.checkUpgradedAndUpdate();
-  //     if (result) {
-  //       console.log("Upgrade complete");
-  //       setUpgradeComplete(true);
-  //     }
-  //   }, 5000);
-  //   onCleanup(() => {
-  //     console.log("Cleaning up upgrade status check interval");
-  //     clearInterval(interval);
-  //   });
-  // });
-
-  const { rive: CommercialRive, RiveComponent: Commercial } = createRive(
-    () => ({
-      src: PricingRive,
-      autoplay: true,
-      artboard: "commercial",
-      animations: ["card-stack"],
-    })
-  );
-
-  const { rive: ProRive, RiveComponent: Pro } = createRive(() => ({
-    src: PricingRive,
-    autoplay: true,
-    artboard: "pro",
-    animations: ["items-coming-in"],
-  }));
-
-  return (
-    <div class="flex relative flex-col justify-center items-center p-5 mx-auto w-full h-full">
-      {upgradeComplete() && (
-        <div class="flex justify-center items-center h-full bg-opacity-75">
-          <div class="relative z-10 p-6 text-center bg-white rounded-lg shadow-lg">
-            <h2 class="mb-4 text-2xl font-bold">Upgrade complete</h2>
-            <p class="mb-4 text-sm text-gray-10">
-              You can now close this window - thank you for upgrading!
-            </p>
-            <Button
-              onClick={() => {
-                console.log("Closing window after upgrade");
-                const window = getCurrentWindow();
-                window.close();
-              }}
-              variant="primary"
-              size="lg"
-            >
-              Close window
-            </Button>
-          </div>
-        </div>
-      )}
-      {!upgradeComplete() &&
-        (license.data?.type === "commercial" ? (
-          <div class="p-8 mx-auto w-full max-w-[700px] rounded-xl border shadow-sm bg-gray-2 border-gray-3">
-            <div class="space-y-6">
-              <div class="flex flex-col items-center mb-6 text-center">
-                <h3 class="text-2xl font-medium">Commercial License</h3>
-                <p class="text-sm text-gray-11">
-                  Your license details for Cap commercial use
-                </p>
-              </div>
-
-              <div class="space-y-6">
-                <div>
-                  <label class="block mb-2 text-sm text-gray-12">
-                    License Key
-                  </label>
-                  <p class="overflow-x-auto p-3 font-mono text-xs whitespace-pre-wrap break-all rounded-lg border border-gray-4 text-gray-9 bg-gray-3">
-                    {license.data.licenseKey}
-                  </p>
-                </div>
-
-                <Show when={license.data.expiryDate}>
-                  {(expiryDate) => (
-                    <div class="space-y-1">
-                      <label class="text-sm text-gray-12">Expires</label>
-                      <p class="text-gray-10">
-                        {new Date(expiryDate()).toLocaleDateString(undefined, {
-                          year: "numeric",
-                          month: "long",
-                          day: "numeric",
-                        })}
-                      </p>
-                    </div>
-                  )}
-                </Show>
-
-                <div class="flex flex-col items-center pt-6 border-t border-gray-3">
-                  <Button
-                    variant="destructive"
-                    disabled={resetLicense.isPending}
-                    onClick={() => {
-                      resetLicense.mutate();
-                    }}
-                  >
-                    {resetLicense.isPending
-                      ? "Deactivating..."
-                      : "Deactivate License"}
-                  </Button>
-                </div>
-              </div>
-            </div>
-          </div>
-        ) : (
-          <>
-            <div class="text-center">
-              <h1 class="text-4xl md:text-4xl mb-6 tracking-[-.05em] font-medium text-[--text-primary]">
-                Early Adopter Pricing
-              </h1>
-            </div>
-            <div class="flex gap-4 w-full">
-              <div
-                onMouseEnter={() => {
-                  const riveInstance = CommercialRive();
-                  if (riveInstance) {
-                    // Stop any current animations first
-                    riveInstance.stop();
-                    // Play the enter animation
-                    riveInstance.play("cards");
-                  }
-                }}
-                onMouseLeave={() => {
-                  const riveInstance = CommercialRive();
-                  if (riveInstance) {
-                    // Stop any current animations first
-                    riveInstance.stop();
-                    // Play the leave animation
-                    riveInstance.play("card-stack");
-                  }
-                }}
-                class="flex flex-col flex-1 justify-between p-3 h-[700px ] bg-gray-3 rounded-2xl border border-gray-3 shadow-sm text-card-foreground md:p-3"
-              >
-                <div class="space-y-5">
-                  <div class="flex flex-col gap-6 items-center">
-                    <Commercial class="w-[250px]" />
-                    <div class="space-y-1 text-center">
-                      <h3 class="text-2xl font-medium tracking-tight leading-5">
-                        Commercial License
-                      </h3>
-                      <p class="mt-2 text-sm text-[--text-tertiary]">
-                        For commercial use
-                      </p>
-                    </div>
-                    <div class="flex flex-col justify-center items-center">
-                      <h3 class="text-4xl leading-6">
-                        {isCommercialAnnual() ? "$29" : "$58"}
-                        <span class="text-gray-11 text-[16px]">.00 /</span>
-                      </h3>
-                      {isCommercialAnnual() && (
-                        <p class="text-[16px] font-medium text-gray-11">
-                          billed annually
-                        </p>
-                      )}
-                      {!isCommercialAnnual() && (
-                        <p class="text-[16px] font-medium text-gray-11">
-                          one-time payment
-                        </p>
-                      )}
-                    </div>
-                    <div
-                      onClick={() => setIsCommercialAnnual((v) => !v)}
-                      class="px-3 py-2 text-center rounded-full border border-transparent transition-all duration-200 cursor-pointer bg-gray-5 hover:border-gray-400"
-                    >
-                      <p class="text-xs text-gray-12">
-                        Switch to {isCommercialAnnual() ? "lifetime" : "yearly"}
-                        :{" "}
-                        <span class="font-medium">
-                          {isCommercialAnnual() ? "$58" : "$29"}
-                        </span>
-                      </p>
-                    </div>
-                    <ul class="flex flex-col gap-2 justify-center list-none">
-                      {[
-                        "Commercial Use of Cap Recorder + Editor",
-                        "Community Support",
-                        "Local-only features",
-                        "Perpetual license option",
-                      ].map((feature) => (
-                        <li class="flex justify-start items-center">
-                          <div class="flex justify-center items-center p-0 m-0 w-6 h-6">
-                            <IconLucideCheck class="w-4 h-4 text-[--text-primary]" />
-                          </div>
-                          <span class="ml-1 text-[0.9rem] text-[--text-primary]">
-                            {feature}
-                          </span>
-                        </li>
-                      ))}
-                    </ul>
-                  </div>
-                </div>
-                <ActivateLicenseDialog
-                  open={openLicenseDialog}
-                  onOpenChange={setOpenLicenseDialog}
-                />
-                <div class="flex flex-col gap-4 items-center">
-                  <Button
-                    onClick={() => openCommercialCheckout.mutate()}
-                    disabled={openCommercialCheckout.isPending}
-                    variant="dark"
-                    class="w-full !rounded-full !h-[48px] text-lg font-medium"
-                    size="lg"
-                  >
-                    {openCommercialCheckout.isPending
-                      ? "Loading..."
-                      : "Purchase License"}
-                  </Button>
-                  <p
-                    onClick={() => setOpenLicenseDialog(true)}
-                    class="mb-2 text-sm transition-colors cursor-pointer text-gray-11 hover:text-gray-12"
-                  >
-                    Already have a license key?
-                  </p>
-                </div>
-              </div>
-
-              {/* Cap Pro */}
-              <div
-                onMouseEnter={() => {
-                  const riveInstance = ProRive();
-                  if (riveInstance) {
-                    // Stop any current animations first
-                    riveInstance.stop();
-                    // Play the enter animation
-                    riveInstance.play("items-coming-out");
-                  }
-                }}
-                onMouseLeave={() => {
-                  const riveInstance = ProRive();
-                  if (riveInstance) {
-                    // Stop any current animations first
-                    riveInstance.stop();
-                    // Play the leave animation
-                    riveInstance.play("items-coming-in");
-                  }
-                }}
-                class="flex-grow p-3 h-[700px] flex-1 bg-gray-12 rounded-2xl border shadow-sm text-card-foreground md:p-3"
-              >
-                <div class="flex flex-col justify-between space-y-5 h-full">
-                  <div class="flex flex-col gap-6 items-center px-6">
-                    <Pro class="w-[250px]" />
-                    <div class="space-y-1 text-center">
-                      <h3 class="text-2xl font-medium tracking-tight leading-5 text-gray-1">
-                        Cap Pro
-                      </h3>
-                      <p class="text-[0.875rem] text-gray-9">
-                        For professional use and teams.
-                      </p>
-                    </div>
-                    <div class="flex flex-col justify-center items-center">
-                      <h3 class="text-4xl leading-6 text-gray-1">
-                        {isProAnnual() ? "$8.16" : "$12"}
-                        <span class="text-gray-10 text-[16px]">.00 /</span>
-                      </h3>
-                      {isProAnnual() && (
-                        <p class="text-[16px] font-medium text-gray-9">
-                          per user, billed annually
-                        </p>
-                      )}
-                      {!isProAnnual() && (
-                        <p class="text-[16px] font-medium text-gray-9">
-                          per user, billed monthly
-                        </p>
-                      )}
-                    </div>
-                    <div
-                      onClick={() => setIsProAnnual((v) => !v)}
-                      class="px-3 py-2 text-center bg-blue-500 rounded-full border border-transparent transition-all duration-200 cursor-pointer hover:border-blue-400"
-                    >
-                      <p class="text-xs text-solid-white">
-                        Switch to {isProAnnual() ? "monthly" : "yearly"}:{" "}
-                        <span class="font-medium">
-                          {isProAnnual()
-                            ? "$12 per user, billed monthly"
-                            : "$8.16 per user, billed annually"}
-                        </span>
-                      </p>
-                    </div>
-                    <ul class="flex flex-col gap-2 justify-center list-none">
-                      {proFeatures.map((feature) => (
-                        <li class="flex justify-start items-center text-gray-1">
-                          <div class="flex justify-center items-center p-0 m-0 size-4">
-                            <IconLucideCheck class="size-4" />
-                          </div>
-                          <span class="ml-2 text-[0.9rem]">{feature}</span>
-                        </li>
-                      ))}
-                    </ul>
-                  </div>
-                  <Button
-                    variant="blue"
-                    class="!rounded-full !text-lg w-full mx-auto"
-                    onClick={openCheckoutInExternalBrowser}
-                  >
-                    {loading() ? "Loading..." : "Upgrade to Cap Pro"}
-                  </Button>
-                </div>
-              </div>
-            </div>
-          </>
-        ))}
-    </div>
-  );
+	const [isProAnnual, setIsProAnnual] = createSignal(true);
+	const [isCommercialAnnual, setIsCommercialAnnual] = createSignal(true);
+	const [upgradeComplete, setUpgradeComplete] = createSignal(false);
+	const [loading, setLoading] = createSignal(false);
+	const signIn = createSignInMutation();
+	const license = createLicenseQuery();
+	const [openLicenseDialog, setOpenLicenseDialog] = createSignal(false);
+
+	const resetLicense = createMutation(() => ({
+		mutationFn: async () => {
+			const generalSettings = await generalSettingsStore.get();
+			if (
+				!generalSettings?.instanceId ||
+				!license.data ||
+				license.data.type !== "commercial"
+			) {
+				throw new Error("No instance ID or valid commercial license found");
+			}
+
+			const resp = await licenseApiClient.activateCommercialLicense({
+				headers: {
+					licensekey: license.data.licenseKey,
+					instanceid: generalSettings.instanceId,
+				},
+				body: { reset: true },
+			});
+
+			if (resp.status !== 200) {
+				if (
+					typeof resp.body === "object" &&
+					resp.body &&
+					"message" in resp.body
+				)
+					throw resp.body.message;
+				throw new Error((resp.body as any).toString());
+			}
+		},
+		onSuccess: async () => {
+			await generalSettingsStore.set({
+				commercialLicense: undefined,
+			});
+			license.refetch();
+		},
+	}));
+
+	const openCheckoutInExternalBrowser = async () => {
+		console.log("Opening checkout in external browser");
+		setLoading(true);
+
+		try {
+			const auth = await authStore.get();
+
+			console.log({ auth });
+			if (!auth) {
+				console.log("No auth found, starting sign in flow");
+				await signIn.mutateAsync(new AbortController());
+			}
+
+			const planId = getProPlanId(isProAnnual() ? "yearly" : "monthly");
+			console.log("Getting checkout URL for plan:", planId);
+			const response = await apiClient.desktop.getProSubscribeURL({
+				body: { priceId: planId },
+				headers: await protectedHeaders(),
+			});
+
+			if (response.status === 200) {
+				console.log("Opening checkout URL in external browser");
+				commands.openExternalLink(response.body.url);
+				console.log("Minimizing upgrade window");
+				const window = await Window.getByLabel("upgrade");
+				if (window) await window.minimize();
+			} else {
+				console.error("Failed to get checkout URL, status:", response.status);
+			}
+		} catch (error) {
+			console.error("Error getting checkout URL:", error);
+		} finally {
+			setLoading(false);
+		}
+	};
+
+	const openCommercialCheckout = createMutation(() => ({
+		mutationFn: async () => {
+			const resp = await licenseApiClient.createCommercialCheckoutUrl({
+				body: { type: isCommercialAnnual() ? "yearly" : "lifetime" },
+			});
+
+			if (resp.status === 200) {
+				console.log("Opening checkout URL in external browser");
+				commands.openExternalLink(resp.body.url);
+				console.log("Minimizing upgrade window");
+				const window = await Window.getByLabel("upgrade");
+				if (window) {
+					await window.minimize();
+				}
+			} else {
+				throw resp.body;
+			}
+		},
+	}));
+
+	// onMount(async () => {
+	//   console.log("Component mounted");
+	//   const unsubscribeDeepLink = await onOpenUrl(async (urls) => {
+	//     console.log("Deep link received:", urls);
+	//     const isDevMode = import.meta.env.VITE_ENVIRONMENT === "development";
+	//     if (isDevMode) {
+	//       console.log("In dev mode, ignoring deep link");
+	//       return;
+	//     }
+
+	//     for (const url of urls) {
+	//       if (!url.includes("token=")) {
+	//         console.log("URL does not contain token, skipping");
+	//         return;
+	//       }
+
+	//       console.log("Processing auth URL");
+	//       const urlObject = new URL(url);
+	//       const token = urlObject.searchParams.get("token");
+	//       const user_id = urlObject.searchParams.get("user_id");
+	//       const expires = Number(urlObject.searchParams.get("expires"));
+
+	//       if (!token || !expires || !user_id) {
+	//         console.error("Invalid signin params");
+	//         throw new Error("Invalid signin params");
+	//       }
+
+	//       console.log("Setting auth store with new credentials");
+	//       const existingAuth = await authStore.get();
+	//       await authStore.set({
+	//         token,
+	//         user_id,
+	//         expires,
+	//         intercom_hash: existingAuth?.intercom_hash ?? "",
+	//         plan: {
+	//           upgraded: false,
+	//           last_checked: 0,
+	//           manual: existingAuth?.plan?.manual ?? false,
+	//         },
+	//       });
+
+	//       console.log("Identifying user in analytics");
+	//       identifyUser(user_id);
+	//       console.log("Tracking sign in event");
+	//       trackEvent("user_signed_in", { platform: "desktop" });
+
+	//       console.log("Reopening upgrade window");
+	//       await commands.showWindow("Upgrade");
+
+	//       console.log("Waiting for window to be ready");
+	//       await new Promise((resolve) => setTimeout(resolve, 500));
+
+	//       console.log("Getting upgrade window reference");
+	//       const upgradeWindow = await Window.getByLabel("upgrade");
+	//       if (upgradeWindow) {
+	//         try {
+	//           console.log("Setting focus on upgrade window");
+	//           await upgradeWindow.show();
+	//           await upgradeWindow.setFocus();
+	//         } catch (e) {
+	//           console.error("Failed to focus upgrade window:", e);
+	//         }
+	//       }
+
+	//       console.log("Getting checkout URL");
+	//       const planId = getProPlanId(isProAnnual() ? "yearly" : "monthly");
+	//       const response = await apiClient.desktop.getProSubscribeURL({
+	//         body: { priceId: planId },
+	//         headers: await protectedHeaders(),
+	//       });
+
+	//       if (response.status === 200) {
+	//         console.log("Opening checkout URL in external browser");
+	//         commands.openExternalLink(response.body.url);
+	//         console.log("Minimizing upgrade window");
+	//         if (upgradeWindow) {
+	//           await upgradeWindow.minimize();
+	//         }
+	//       }
+	//     }
+	//   });
+
+	//   onCleanup(() => {
+	//     console.log("Cleaning up deep link listener");
+	//     unsubscribeDeepLink();
+	//   });
+
+	//   console.log("Setting up upgrade status check interval");
+	//   const interval = setInterval(async () => {
+	//     console.log("Checking upgrade status");
+	//     const result = await commands.checkUpgradedAndUpdate();
+	//     if (result) {
+	//       console.log("Upgrade complete");
+	//       setUpgradeComplete(true);
+	//     }
+	//   }, 5000);
+	//   onCleanup(() => {
+	//     console.log("Cleaning up upgrade status check interval");
+	//     clearInterval(interval);
+	//   });
+	// });
+
+	const { rive: CommercialRive, RiveComponent: Commercial } = createRive(
+		() => ({
+			src: PricingRive,
+			autoplay: true,
+			artboard: "commercial",
+			animations: ["card-stack"],
+		}),
+	);
+
+	const { rive: ProRive, RiveComponent: Pro } = createRive(() => ({
+		src: PricingRive,
+		autoplay: true,
+		artboard: "pro",
+		animations: ["items-coming-in"],
+	}));
+
+	return (
+		<div class="flex relative flex-col justify-center items-center p-5 mx-auto w-full h-full">
+			{upgradeComplete() && (
+				<div class="flex justify-center items-center h-full bg-opacity-75">
+					<div class="relative z-10 p-6 text-center bg-white rounded-lg shadow-lg">
+						<h2 class="mb-4 text-2xl font-bold">Upgrade complete</h2>
+						<p class="mb-4 text-sm text-gray-10">
+							You can now close this window - thank you for upgrading!
+						</p>
+						<Button
+							onClick={() => {
+								console.log("Closing window after upgrade");
+								const window = getCurrentWindow();
+								window.close();
+							}}
+							variant="primary"
+							size="lg"
+						>
+							Close window
+						</Button>
+					</div>
+				</div>
+			)}
+			{!upgradeComplete() &&
+				(license.data?.type === "commercial" ? (
+					<div class="p-8 mx-auto w-full max-w-[700px] rounded-xl border shadow-sm bg-gray-2 border-gray-3">
+						<div class="space-y-6">
+							<div class="flex flex-col items-center mb-6 text-center">
+								<h3 class="text-2xl font-medium">Commercial License</h3>
+								<p class="text-sm text-gray-11">
+									Your license details for Cap commercial use
+								</p>
+							</div>
+
+							<div class="space-y-6">
+								<div>
+									<label class="block mb-2 text-sm text-gray-12">
+										License Key
+									</label>
+									<p class="overflow-x-auto p-3 font-mono text-xs whitespace-pre-wrap break-all rounded-lg border border-gray-4 text-gray-9 bg-gray-3">
+										{license.data.licenseKey}
+									</p>
+								</div>
+
+								<Show when={license.data.expiryDate}>
+									{(expiryDate) => (
+										<div class="space-y-1">
+											<label class="text-sm text-gray-12">Expires</label>
+											<p class="text-gray-10">
+												{new Date(expiryDate()).toLocaleDateString(undefined, {
+													year: "numeric",
+													month: "long",
+													day: "numeric",
+												})}
+											</p>
+										</div>
+									)}
+								</Show>
+
+								<div class="flex flex-col items-center pt-6 border-t border-gray-3">
+									<Button
+										variant="destructive"
+										disabled={resetLicense.isPending}
+										onClick={() => {
+											resetLicense.mutate();
+										}}
+									>
+										{resetLicense.isPending
+											? "Deactivating..."
+											: "Deactivate License"}
+									</Button>
+								</div>
+							</div>
+						</div>
+					</div>
+				) : (
+					<>
+						<div class="text-center">
+							<h1 class="text-4xl md:text-4xl mb-6 tracking-[-.05em] font-medium text-[--text-primary]">
+								Early Adopter Pricing
+							</h1>
+						</div>
+						<div class="flex gap-4 w-full">
+							<div
+								onMouseEnter={() => {
+									const riveInstance = CommercialRive();
+									if (riveInstance) {
+										// Stop any current animations first
+										riveInstance.stop();
+										// Play the enter animation
+										riveInstance.play("cards");
+									}
+								}}
+								onMouseLeave={() => {
+									const riveInstance = CommercialRive();
+									if (riveInstance) {
+										// Stop any current animations first
+										riveInstance.stop();
+										// Play the leave animation
+										riveInstance.play("card-stack");
+									}
+								}}
+								class="flex flex-col flex-1 justify-between p-3 h-[700px ] bg-gray-3 rounded-2xl border border-gray-3 shadow-sm text-card-foreground md:p-3"
+							>
+								<div class="space-y-5">
+									<div class="flex flex-col gap-6 items-center">
+										<Commercial class="w-[250px]" />
+										<div class="space-y-1 text-center">
+											<h3 class="text-2xl font-medium tracking-tight leading-5">
+												Commercial License
+											</h3>
+											<p class="mt-2 text-sm text-[--text-tertiary]">
+												For commercial use
+											</p>
+										</div>
+										<div class="flex flex-col justify-center items-center">
+											<h3 class="text-4xl leading-6">
+												{isCommercialAnnual() ? "$29" : "$58"}
+												<span class="text-gray-11 text-[16px]">.00 /</span>
+											</h3>
+											{isCommercialAnnual() && (
+												<p class="text-[16px] font-medium text-gray-11">
+													billed annually
+												</p>
+											)}
+											{!isCommercialAnnual() && (
+												<p class="text-[16px] font-medium text-gray-11">
+													one-time payment
+												</p>
+											)}
+										</div>
+										<div
+											onClick={() => setIsCommercialAnnual((v) => !v)}
+											class="px-3 py-2 text-center rounded-full border border-transparent transition-all duration-200 cursor-pointer bg-gray-5 hover:border-gray-400"
+										>
+											<p class="text-xs text-gray-12">
+												Switch to {isCommercialAnnual() ? "lifetime" : "yearly"}
+												:{" "}
+												<span class="font-medium">
+													{isCommercialAnnual() ? "$58" : "$29"}
+												</span>
+											</p>
+										</div>
+										<ul class="flex flex-col gap-2 justify-center list-none">
+											{[
+												"Commercial Use of Cap Recorder + Editor",
+												"Community Support",
+												"Local-only features",
+												"Perpetual license option",
+											].map((feature) => (
+												<li class="flex justify-start items-center">
+													<div class="flex justify-center items-center p-0 m-0 w-6 h-6">
+														<IconLucideCheck class="w-4 h-4 text-[--text-primary]" />
+													</div>
+													<span class="ml-1 text-[0.9rem] text-[--text-primary]">
+														{feature}
+													</span>
+												</li>
+											))}
+										</ul>
+									</div>
+								</div>
+								<ActivateLicenseDialog
+									open={openLicenseDialog}
+									onOpenChange={setOpenLicenseDialog}
+								/>
+								<div class="flex flex-col gap-4 items-center">
+									<Button
+										onClick={() => openCommercialCheckout.mutate()}
+										disabled={openCommercialCheckout.isPending}
+										variant="dark"
+										class="w-full !rounded-full !h-[48px] text-lg font-medium"
+										size="lg"
+									>
+										{openCommercialCheckout.isPending
+											? "Loading..."
+											: "Purchase License"}
+									</Button>
+									<p
+										onClick={() => setOpenLicenseDialog(true)}
+										class="mb-2 text-sm transition-colors cursor-pointer text-gray-11 hover:text-gray-12"
+									>
+										Already have a license key?
+									</p>
+								</div>
+							</div>
+
+							{/* Cap Pro */}
+							<div
+								onMouseEnter={() => {
+									const riveInstance = ProRive();
+									if (riveInstance) {
+										// Stop any current animations first
+										riveInstance.stop();
+										// Play the enter animation
+										riveInstance.play("items-coming-out");
+									}
+								}}
+								onMouseLeave={() => {
+									const riveInstance = ProRive();
+									if (riveInstance) {
+										// Stop any current animations first
+										riveInstance.stop();
+										// Play the leave animation
+										riveInstance.play("items-coming-in");
+									}
+								}}
+								class="flex-grow p-3 h-[700px] flex-1 bg-gray-12 rounded-2xl border shadow-sm text-card-foreground md:p-3"
+							>
+								<div class="flex flex-col justify-between space-y-5 h-full">
+									<div class="flex flex-col gap-6 items-center px-6">
+										<Pro class="w-[250px]" />
+										<div class="space-y-1 text-center">
+											<h3 class="text-2xl font-medium tracking-tight leading-5 text-gray-1">
+												Cap Pro
+											</h3>
+											<p class="text-[0.875rem] text-gray-9">
+												For professional use and teams.
+											</p>
+										</div>
+										<div class="flex flex-col justify-center items-center">
+											<h3 class="text-4xl leading-6 text-gray-1">
+												{isProAnnual() ? "$8.16" : "$12"}
+												<span class="text-gray-10 text-[16px]">.00 /</span>
+											</h3>
+											{isProAnnual() && (
+												<p class="text-[16px] font-medium text-gray-9">
+													per user, billed annually
+												</p>
+											)}
+											{!isProAnnual() && (
+												<p class="text-[16px] font-medium text-gray-9">
+													per user, billed monthly
+												</p>
+											)}
+										</div>
+										<div
+											onClick={() => setIsProAnnual((v) => !v)}
+											class="px-3 py-2 text-center bg-blue-500 rounded-full border border-transparent transition-all duration-200 cursor-pointer hover:border-blue-400"
+										>
+											<p class="text-xs text-solid-white">
+												Switch to {isProAnnual() ? "monthly" : "yearly"}:{" "}
+												<span class="font-medium">
+													{isProAnnual()
+														? "$12 per user, billed monthly"
+														: "$8.16 per user, billed annually"}
+												</span>
+											</p>
+										</div>
+										<ul class="flex flex-col gap-2 justify-center list-none">
+											{proFeatures.map((feature) => (
+												<li class="flex justify-start items-center text-gray-1">
+													<div class="flex justify-center items-center p-0 m-0 size-4">
+														<IconLucideCheck class="size-4" />
+													</div>
+													<span class="ml-2 text-[0.9rem]">{feature}</span>
+												</li>
+											))}
+										</ul>
+									</div>
+									<Button
+										variant="blue"
+										class="!rounded-full !text-lg w-full mx-auto"
+										onClick={openCheckoutInExternalBrowser}
+									>
+										{loading() ? "Loading..." : "Upgrade to Cap Pro"}
+									</Button>
+								</div>
+							</div>
+						</div>
+					</>
+				))}
+		</div>
+	);
 }
 
 interface Props {
-  open: Accessor<boolean>;
-  onOpenChange: (open: boolean) => void;
+	open: Accessor<boolean>;
+	onOpenChange: (open: boolean) => void;
 }
 
 const ActivateLicenseDialog = ({ open, onOpenChange }: Props) => {
-  const [licenseKey, setLicenseKey] = createSignal("");
-  const queryClient = useQueryClient();
-
-  const activateLicenseKey = createMutation(() => ({
-    mutationFn: async (vars: { licenseKey: string }) => {
-      const generalSettings = await generalSettingsStore.get();
-      if (!generalSettings?.instanceId) {
-        throw new Error("No instance ID found");
-      }
-      const resp = await licenseApiClient.activateCommercialLicense({
-        headers: {
-          licensekey: vars.licenseKey,
-          instanceid: generalSettings.instanceId,
-        },
-        body: { reset: false },
-      });
-
-      if (resp.status === 200)
-        return { ...resp.body, licenseKey: vars.licenseKey };
-      if (typeof resp.body === "object" && resp.body && "message" in resp.body)
-        throw resp.body.message;
-      throw new Error((resp.body as any).toString());
-    },
-    onSuccess: async (value) => {
-      await generalSettingsStore.set({
-        commercialLicense: {
-          activatedOn: Date.now(),
-          expiryDate: value.expiryDate ?? null,
-          refresh: value.refresh,
-          licenseKey: value.licenseKey,
-        },
-      });
-      await queryClient.refetchQueries({ queryKey: ["bruh"] });
-    },
-  }));
-  return (
-    <Dialog.Root open={open()} onOpenChange={onOpenChange}>
-      <DialogContent
-        title="Activate License"
-        confirm={
-          <Dialog.ConfirmButton
-            disabled={activateLicenseKey.isPending}
-            onClick={() =>
-              activateLicenseKey.mutate({
-                licenseKey: licenseKey(),
-              })
-            }
-          >
-            Activate
-          </Dialog.ConfirmButton>
-        }
-      >
-        <Input
-          class="mt-2"
-          placeholder="Enter license key..."
-          value={licenseKey()}
-          onInput={(e) => setLicenseKey(e.currentTarget.value)}
-        />
-      </DialogContent>
-    </Dialog.Root>
-  );
+	const [licenseKey, setLicenseKey] = createSignal("");
+	const queryClient = useQueryClient();
+
+	const activateLicenseKey = createMutation(() => ({
+		mutationFn: async (vars: { licenseKey: string }) => {
+			const generalSettings = await generalSettingsStore.get();
+			if (!generalSettings?.instanceId) {
+				throw new Error("No instance ID found");
+			}
+			const resp = await licenseApiClient.activateCommercialLicense({
+				headers: {
+					licensekey: vars.licenseKey,
+					instanceid: generalSettings.instanceId,
+				},
+				body: { reset: false },
+			});
+
+			if (resp.status === 200)
+				return { ...resp.body, licenseKey: vars.licenseKey };
+			if (typeof resp.body === "object" && resp.body && "message" in resp.body)
+				throw resp.body.message;
+			throw new Error((resp.body as any).toString());
+		},
+		onSuccess: async (value) => {
+			await generalSettingsStore.set({
+				commercialLicense: {
+					activatedOn: Date.now(),
+					expiryDate: value.expiryDate ?? null,
+					refresh: value.refresh,
+					licenseKey: value.licenseKey,
+				},
+			});
+			await queryClient.refetchQueries({ queryKey: ["bruh"] });
+		},
+	}));
+	return (
+		<Dialog.Root open={open()} onOpenChange={onOpenChange}>
+			<DialogContent
+				title="Activate License"
+				confirm={
+					<Dialog.ConfirmButton
+						disabled={activateLicenseKey.isPending}
+						onClick={() =>
+							activateLicenseKey.mutate({
+								licenseKey: licenseKey(),
+							})
+						}
+					>
+						Activate
+					</Dialog.ConfirmButton>
+				}
+			>
+				<Input
+					class="mt-2"
+					placeholder="Enter license key..."
+					value={licenseKey()}
+					onInput={(e) => setLicenseKey(e.currentTarget.value)}
+				/>
+			</DialogContent>
+		</Dialog.Root>
+	);
 };
diff --git a/apps/web/components/UpgradeModal.tsx b/apps/web/components/UpgradeModal.tsx
index 8ece5c67f5..a5b2e9bf44 100644
--- a/apps/web/components/UpgradeModal.tsx
+++ b/apps/web/components/UpgradeModal.tsx
@@ -7,313 +7,313 @@ import NumberFlow from "@number-flow/react";
 import { Fit, Layout, useRive } from "@rive-app/react-canvas";
 import { AnimatePresence, motion } from "framer-motion";
 import {
-  BarChart3,
-  Database,
-  Globe,
-  Headphones,
-  Infinity,
-  Lock,
-  Minus,
-  Plus,
-  Share2,
-  Shield,
-  Sparkles,
-  Video,
+	BarChart3,
+	Database,
+	Globe,
+	Headphones,
+	Infinity,
+	Lock,
+	Minus,
+	Plus,
+	Share2,
+	Shield,
+	Sparkles,
+	Video,
 } from "lucide-react";
 import { useRouter } from "next/navigation";
 import { memo, useState } from "react";
 import { toast } from "sonner";
 
 interface UpgradeModalProps {
-  open: boolean;
-  onOpenChange: (open: boolean) => void;
+	open: boolean;
+	onOpenChange: (open: boolean) => void;
 }
 
 const modalVariants = {
-  hidden: {
-    opacity: 0,
-    scale: 0.95,
-    y: 10,
-  },
-  visible: {
-    opacity: 1,
-    scale: 1,
-    y: 0,
-    transition: {
-      type: "spring",
-      duration: 0.4,
-      damping: 25,
-      stiffness: 500,
-    },
-  },
-  exit: {
-    opacity: 0,
-    scale: 0.95,
-    y: 10,
-    transition: {
-      duration: 0.2,
-    },
-  },
+	hidden: {
+		opacity: 0,
+		scale: 0.95,
+		y: 10,
+	},
+	visible: {
+		opacity: 1,
+		scale: 1,
+		y: 0,
+		transition: {
+			type: "spring",
+			duration: 0.4,
+			damping: 25,
+			stiffness: 500,
+		},
+	},
+	exit: {
+		opacity: 0,
+		scale: 0.95,
+		y: 10,
+		transition: {
+			duration: 0.2,
+		},
+	},
 };
 
 export const UpgradeModal = ({ open, onOpenChange }: UpgradeModalProps) => {
-  if (buildEnv.NEXT_PUBLIC_IS_CAP !== "true") return;
+	if (buildEnv.NEXT_PUBLIC_IS_CAP !== "true") return;
 
-  const [proLoading, setProLoading] = useState(false);
-  const [isAnnual, setIsAnnual] = useState(true);
-  const [proQuantity, setProQuantity] = useState(1);
-  const { push } = useRouter();
+	const [proLoading, setProLoading] = useState(false);
+	const [isAnnual, setIsAnnual] = useState(true);
+	const [proQuantity, setProQuantity] = useState(1);
+	const { push } = useRouter();
 
-  const pricePerUser = isAnnual ? 8.16 : 12;
-  const totalPrice = pricePerUser * proQuantity;
-  const billingText = isAnnual ? "billed annually" : "billed monthly";
+	const pricePerUser = isAnnual ? 8.16 : 12;
+	const totalPrice = pricePerUser * proQuantity;
+	const billingText = isAnnual ? "billed annually" : "billed monthly";
 
-  useRive({
-    src: "/rive/main.riv",
-    artboard: "cap-pro-modal",
-    animations: ["animation"],
-    layout: new Layout({
-      fit: Fit.Cover,
-    }),
-    autoplay: true,
-  });
+	useRive({
+		src: "/rive/main.riv",
+		artboard: "cap-pro-modal",
+		animations: ["animation"],
+		layout: new Layout({
+			fit: Fit.Cover,
+		}),
+		autoplay: true,
+	});
 
-  const iconStyling = "text-blue-500 size-[18px]";
-  const proFeatures = [
-    {
-      icon: <Globe className={iconStyling} />,
-      title: "Custom domain",
-      description: "Connect your own domain to Cap",
-    },
-    {
-      icon: <Share2 className={iconStyling} />,
-      title: "Unlimited sharing",
-      description: "Cloud storage & shareable links",
-    },
-    {
-      icon: <Sparkles className={iconStyling} />,
-      title: "Cap AI",
-      description: "Automatic video chapters, summaries & more",
-    },
-    {
-      icon: <Lock className={iconStyling} />,
-      title: "Password protected videos",
-      description: "Enhanced security for your content",
-    },
-    {
-      icon: <Database className={iconStyling} />,
-      title: "Custom storage",
-      description: "Connect your own S3 bucket",
-    },
-    {
-      icon: <Shield className={iconStyling} />,
-      title: "Commercial license",
-      description: "Commercial license for desktop app automatically included",
-    },
-    {
-      icon: <Video className={iconStyling} />,
-      title: "Upload videos",
-      description: "Upload custom videos directly to Cap",
-    },
-    {
-      icon: <Infinity className={iconStyling} />,
-      title: "Unlimited views",
-      description: "No limits on video views",
-    },
-    {
-      icon: <BarChart3 className={iconStyling} />,
-      title: "Analytics",
-      description: "Video viewing insights",
-    },
-    {
-      icon: <Headphones className={iconStyling} />,
-      title: "Priority support",
-      description: "Get help when you need it",
-    },
-  ];
+	const iconStyling = "text-blue-500 size-[18px]";
+	const proFeatures = [
+		{
+			icon: <Globe className={iconStyling} />,
+			title: "Custom domain",
+			description: "Connect your own domain to Cap",
+		},
+		{
+			icon: <Share2 className={iconStyling} />,
+			title: "Unlimited sharing",
+			description: "Cloud storage & shareable links",
+		},
+		{
+			icon: <Sparkles className={iconStyling} />,
+			title: "Cap AI",
+			description: "Automatic video chapters, summaries & more",
+		},
+		{
+			icon: <Lock className={iconStyling} />,
+			title: "Password protected videos",
+			description: "Enhanced security for your content",
+		},
+		{
+			icon: <Database className={iconStyling} />,
+			title: "Custom storage",
+			description: "Connect your own S3 bucket",
+		},
+		{
+			icon: <Shield className={iconStyling} />,
+			title: "Commercial license",
+			description: "Commercial license for desktop app automatically included",
+		},
+		{
+			icon: <Video className={iconStyling} />,
+			title: "Upload videos",
+			description: "Upload custom videos directly to Cap",
+		},
+		{
+			icon: <Infinity className={iconStyling} />,
+			title: "Unlimited views",
+			description: "No limits on video views",
+		},
+		{
+			icon: <BarChart3 className={iconStyling} />,
+			title: "Analytics",
+			description: "Video viewing insights",
+		},
+		{
+			icon: <Headphones className={iconStyling} />,
+			title: "Priority support",
+			description: "Get help when you need it",
+		},
+	];
 
-  const planCheckout = async () => {
-    setProLoading(true);
+	const planCheckout = async () => {
+		setProLoading(true);
 
-    const planId = getProPlanId(isAnnual ? "yearly" : "monthly");
+		const planId = getProPlanId(isAnnual ? "yearly" : "monthly");
 
-    const response = await fetch(`/api/settings/billing/subscribe`, {
-      method: "POST",
-      headers: {
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify({ priceId: planId, quantity: proQuantity }),
-    });
-    const data = await response.json();
+		const response = await fetch(`/api/settings/billing/subscribe`, {
+			method: "POST",
+			headers: {
+				"Content-Type": "application/json",
+			},
+			body: JSON.stringify({ priceId: planId, quantity: proQuantity }),
+		});
+		const data = await response.json();
 
-    if (data.auth === false) {
-      localStorage.setItem("pendingPriceId", planId);
-      localStorage.setItem("pendingQuantity", proQuantity.toString());
-      push(`/login?next=/dashboard`);
-      return;
-    }
+		if (data.auth === false) {
+			localStorage.setItem("pendingPriceId", planId);
+			localStorage.setItem("pendingQuantity", proQuantity.toString());
+			push(`/login?next=/dashboard`);
+			return;
+		}
 
-    if (data.subscription === true) {
-      toast.success("You are already on the Cap Pro plan");
-      onOpenChange(false);
-    }
+		if (data.subscription === true) {
+			toast.success("You are already on the Cap Pro plan");
+			onOpenChange(false);
+		}
 
-    if (data.url) {
-      window.location.href = data.url;
-    }
+		if (data.url) {
+			window.location.href = data.url;
+		}
 
-    setProLoading(false);
-  };
+		setProLoading(false);
+	};
 
-  return (
-    <Dialog open={open} onOpenChange={onOpenChange}>
-      <DialogContent
-        className="sm:max-w-[1100px] w-[calc(100%-20px)] custom-scroll bg-gray-2 border
+	return (
+		<Dialog open={open} onOpenChange={onOpenChange}>
+			<DialogContent
+				className="sm:max-w-[1100px] w-[calc(100%-20px)] custom-scroll bg-gray-2 border
       border-gray-4 overflow-y-auto md:overflow-hidden max-h-[90vh] p-0"
-      >
-        <AnimatePresence mode="wait">
-          {open && (
-            <motion.div
-              className="flex relative flex-col h-full md:flex-row"
-              variants={modalVariants}
-              initial="hidden"
-              animate="visible"
-              exit="exit"
-            >
-              <div className="flex relative flex-col flex-1 justify-between items-end self-stretch border-r-0 border-b md:border-b-0 md:border-r border-gray-4">
-                <div className="h-[275px] border-b border-gray-4 w-full overflow-hidden">
-                  <ProRiveArt />
-                </div>
-                <div className="flex relative flex-col flex-1 justify-center items-center py-6 w-full">
-                  <div className="flex flex-col items-center">
-                    <h1 className="text-3xl font-medium text-gray-12">
-                      Upgrade to Cap Pro
-                    </h1>
-                  </div>
-                  <p className="mt-1 text-lg text-center text-gray-11">
-                    You can cancel anytime. Early adopter pricing locked in.
-                  </p>
+			>
+				<AnimatePresence mode="wait">
+					{open && (
+						<motion.div
+							className="flex relative flex-col h-full md:flex-row"
+							variants={modalVariants}
+							initial="hidden"
+							animate="visible"
+							exit="exit"
+						>
+							<div className="flex relative flex-col flex-1 justify-between items-end self-stretch border-r-0 border-b md:border-b-0 md:border-r border-gray-4">
+								<div className="h-[275px] border-b border-gray-4 w-full overflow-hidden">
+									<ProRiveArt />
+								</div>
+								<div className="flex relative flex-col flex-1 justify-center items-center py-6 w-full">
+									<div className="flex flex-col items-center">
+										<h1 className="text-3xl font-medium text-gray-12">
+											Upgrade to Cap Pro
+										</h1>
+									</div>
+									<p className="mt-1 text-lg text-center text-gray-11">
+										You can cancel anytime. Early adopter pricing locked in.
+									</p>
 
-                  <div className="flex flex-col items-center mt-3 mb-4 w-full">
-                    <div className="flex flex-col items-center mb-1 sm:items-end sm:flex-row">
-                      <NumberFlow
-                        value={totalPrice}
-                        className="text-3xl font-medium tabular-nums text-gray-12"
-                        format={{
-                          style: "currency",
-                          currency: "USD",
-                        }}
-                      />
-                      <span className="mb-2 ml-2 text-gray-11">
-                        {proQuantity === 1 ? (
-                          `per user, ${billingText}`
-                        ) : (
-                          <>
-                            for{" "}
-                            <NumberFlow
-                              value={proQuantity}
-                              className="tabular-nums text-gray-12"
-                            />{" "}
-                            users, {billingText}
-                          </>
-                        )}
-                      </span>
-                    </div>
+									<div className="flex flex-col items-center mt-3 mb-4 w-full">
+										<div className="flex flex-col items-center mb-1 sm:items-end sm:flex-row">
+											<NumberFlow
+												value={totalPrice}
+												className="text-3xl font-medium tabular-nums text-gray-12"
+												format={{
+													style: "currency",
+													currency: "USD",
+												}}
+											/>
+											<span className="mb-2 ml-2 text-gray-11">
+												{proQuantity === 1 ? (
+													`per user, ${billingText}`
+												) : (
+													<>
+														for{" "}
+														<NumberFlow
+															value={proQuantity}
+															className="tabular-nums text-gray-12"
+														/>{" "}
+														users, {billingText}
+													</>
+												)}
+											</span>
+										</div>
 
-                    <div className="flex flex-col gap-6 justify-evenly items-center mt-8 w-full max-w-md sm:gap-10 sm:flex-row">
-                      <div className="flex gap-3 items-center">
-                        <span className="text-gray-12">Annual billing</span>
-                        <Switch
-                          checked={isAnnual}
-                          onCheckedChange={() => setIsAnnual(!isAnnual)}
-                        />
-                      </div>
+										<div className="flex flex-col gap-6 justify-evenly items-center mt-8 w-full max-w-md sm:gap-10 sm:flex-row">
+											<div className="flex gap-3 items-center">
+												<span className="text-gray-12">Annual billing</span>
+												<Switch
+													checked={isAnnual}
+													onCheckedChange={() => setIsAnnual(!isAnnual)}
+												/>
+											</div>
 
-                      <div className="flex items-center">
-                        <span className="mr-3 text-gray-12">Users:</span>
-                        <div className="flex items-center">
-                          <button
-                            type="button"
-                            onClick={() =>
-                              proQuantity > 1 && setProQuantity(proQuantity - 1)
-                            }
-                            className="flex justify-center items-center w-8 h-8 rounded-l-md bg-gray-4 hover:bg-gray-5"
-                            disabled={proQuantity <= 1}
-                          >
-                            <Minus className="w-4 h-4 text-gray-12" />
-                          </button>
-                          <NumberFlow
-                            value={proQuantity}
-                            className="mx-auto w-6 text-sm tabular-nums text-center text-gray-12"
-                          />
-                          <button
-                            type="button"
-                            onClick={() => setProQuantity(proQuantity + 1)}
-                            className="flex justify-center items-center w-8 h-8 rounded-r-md bg-gray-4 hover:bg-gray-5"
-                          >
-                            <Plus className="w-4 h-4 text-gray-12" />
-                          </button>
-                        </div>
-                      </div>
-                    </div>
-                  </div>
+											<div className="flex items-center">
+												<span className="mr-3 text-gray-12">Users:</span>
+												<div className="flex items-center">
+													<button
+														type="button"
+														onClick={() =>
+															proQuantity > 1 && setProQuantity(proQuantity - 1)
+														}
+														className="flex justify-center items-center w-8 h-8 rounded-l-md bg-gray-4 hover:bg-gray-5"
+														disabled={proQuantity <= 1}
+													>
+														<Minus className="w-4 h-4 text-gray-12" />
+													</button>
+													<NumberFlow
+														value={proQuantity}
+														className="mx-auto w-6 text-sm tabular-nums text-center text-gray-12"
+													/>
+													<button
+														type="button"
+														onClick={() => setProQuantity(proQuantity + 1)}
+														className="flex justify-center items-center w-8 h-8 rounded-r-md bg-gray-4 hover:bg-gray-5"
+													>
+														<Plus className="w-4 h-4 text-gray-12" />
+													</button>
+												</div>
+											</div>
+										</div>
+									</div>
 
-                  <Button
-                    variant="blue"
-                    onClick={planCheckout}
-                    className="mt-5 w-full max-w-sm h-14 text-lg"
-                    disabled={proLoading}
-                  >
-                    {proLoading ? "Loading..." : "Upgrade to Cap Pro"}
-                  </Button>
-                  <button
-                    type="button"
-                    className="mt-2 w-full max-w-sm h-14 text-base rounded-xl hover:underline text-gray-11 hover:text-gray-12"
-                    onClick={() => onOpenChange(false)}
-                  >
-                    Skip
-                  </button>
-                </div>
-              </div>
+									<Button
+										variant="blue"
+										onClick={planCheckout}
+										className="mt-5 w-full max-w-sm h-14 text-lg"
+										disabled={proLoading}
+									>
+										{proLoading ? "Loading..." : "Upgrade to Cap Pro"}
+									</Button>
+									<button
+										type="button"
+										className="mt-2 w-full max-w-sm h-14 text-base rounded-xl hover:underline text-gray-11 hover:text-gray-12"
+										onClick={() => onOpenChange(false)}
+									>
+										Skip
+									</button>
+								</div>
+							</div>
 
-              <div className="flex flex-1 justify-center items-center self-stretch p-8 bg-transparent md:bg-gray-3">
-                <div className="grid grid-cols-1 gap-8 md:grid-cols-2">
-                  {proFeatures.map((feature, index) => (
-                    <div
-                      key={index.toString()}
-                      className="flex flex-col justify-center items-center"
-                    >
-                      <div className="mb-3.5 bg-gray-5 rounded-full size-10 flex items-center justify-center">
-                        {feature.icon}
-                      </div>
-                      <h3 className="text-base font-medium text-center text-gray-12">
-                        {feature.title}
-                      </h3>
-                      <p className="text-sm text-center text-gray-11">
-                        {feature.description}
-                      </p>
-                    </div>
-                  ))}
-                </div>
-              </div>
-            </motion.div>
-          )}
-        </AnimatePresence>
-      </DialogContent>
-    </Dialog>
-  );
+							<div className="flex flex-1 justify-center items-center self-stretch p-8 bg-transparent md:bg-gray-3">
+								<div className="grid grid-cols-1 gap-8 md:grid-cols-2">
+									{proFeatures.map((feature, index) => (
+										<div
+											key={index.toString()}
+											className="flex flex-col justify-center items-center"
+										>
+											<div className="mb-3.5 bg-gray-5 rounded-full size-10 flex items-center justify-center">
+												{feature.icon}
+											</div>
+											<h3 className="text-base font-medium text-center text-gray-12">
+												{feature.title}
+											</h3>
+											<p className="text-sm text-center text-gray-11">
+												{feature.description}
+											</p>
+										</div>
+									))}
+								</div>
+							</div>
+						</motion.div>
+					)}
+				</AnimatePresence>
+			</DialogContent>
+		</Dialog>
+	);
 };
 
 const ProRiveArt = memo(() => {
-  const { RiveComponent: ProModal } = useRive({
-    src: "/rive/main.riv",
-    artboard: "cap-pro-modal",
-    animations: ["animation"],
-    layout: new Layout({
-      fit: Fit.Cover,
-    }),
-    autoplay: true,
-  });
+	const { RiveComponent: ProModal } = useRive({
+		src: "/rive/main.riv",
+		artboard: "cap-pro-modal",
+		animations: ["animation"],
+		layout: new Layout({
+			fit: Fit.Cover,
+		}),
+		autoplay: true,
+	});
 
-  return <ProModal className="w-full h-full" />;
+	return <ProModal className="w-full h-full" />;
 });
diff --git a/apps/web/components/pages/FaqPage.tsx b/apps/web/components/pages/FaqPage.tsx
index 65a2e3a286..f9fe475d52 100644
--- a/apps/web/components/pages/FaqPage.tsx
+++ b/apps/web/components/pages/FaqPage.tsx
@@ -1,59 +1,59 @@
 "use client";
 
 const faqContent = [
-  {
-    title: "Who is Cap for?",
-    answer:
-      "Cap is for anyone who wants to record, edit, and share videos. It's a lightweight, powerful tool for creators, educators, marketers, developers, and remote teams who want to communicate more effectively through screen recordings.",
-  },
-  {
-    title: "How much does it cost?",
-    answer:
-      "Cap offers a free version for personal use. You can upgrade to Cap Pro for just $8.16/month (when billed annually) to unlock unlimited cloud storage, unlimited recording length, custom domain support, advanced team features, password-protected videos, analytics, and priority support. We also offer commercial licenses and self-hosted options for businesses.",
-  },
-  {
-    title: "Which platforms does Cap support?",
-    answer:
-      "Cap is cross-platform and works on macOS (both Apple Silicon and Intel) and Windows. For macOS, we recommend version 13.1 or newer. For Windows, we recommend Windows 10 or newer.",
-  },
-  {
-    title: "What makes Cap different from Loom?",
-    answer:
-      "Cap is open source, privacy-focused, and lets you own your data. You can connect custom S3 storage buckets, self-host the entire platform, and get a lightweight, faster experience. We focus strongly on design, user experience, and building with our community at the center of everything we do.",
-  },
-  {
-    title: "Can I self-host Cap?",
-    answer:
-      "Yes! Cap can be self-hosted on your own infrastructure, giving you full control over your data.",
-  },
-  {
-    title: "Is there a commercial license available?",
-    answer:
-      "Yes, we offer commercial licenses for businesses that want to use the Cap desktop app. The commercial license includes the Cap Recorder + Editor with local-only features. Our Pro plan also includes a commercial license for the desktop app.",
-  },
-  {
-    title: "What happens after the beta period ends?",
-    answer:
-      "Early adopters will keep their special pricing for the lifetime of their subscription, even after we move out of beta and adjust our regular pricing. This is our way of thanking our early supporters.",
-  },
+	{
+		title: "Who is Cap for?",
+		answer:
+			"Cap is for anyone who wants to record, edit, and share videos. It's a lightweight, powerful tool for creators, educators, marketers, developers, and remote teams who want to communicate more effectively through screen recordings.",
+	},
+	{
+		title: "How much does it cost?",
+		answer:
+			"Cap offers a free version for personal use. You can upgrade to Cap Pro for just $8.16/month (when billed annually) to unlock unlimited cloud storage, unlimited recording length, custom domain support, advanced team features, password-protected videos, analytics, and priority support. We also offer commercial licenses and self-hosted options for businesses.",
+	},
+	{
+		title: "Which platforms does Cap support?",
+		answer:
+			"Cap is cross-platform and works on macOS (both Apple Silicon and Intel) and Windows. For macOS, we recommend version 13.1 or newer. For Windows, we recommend Windows 10 or newer.",
+	},
+	{
+		title: "What makes Cap different from Loom?",
+		answer:
+			"Cap is open source, privacy-focused, and lets you own your data. You can connect custom S3 storage buckets, self-host the entire platform, and get a lightweight, faster experience. We focus strongly on design, user experience, and building with our community at the center of everything we do.",
+	},
+	{
+		title: "Can I self-host Cap?",
+		answer:
+			"Yes! Cap can be self-hosted on your own infrastructure, giving you full control over your data.",
+	},
+	{
+		title: "Is there a commercial license available?",
+		answer:
+			"Yes, we offer commercial licenses for businesses that want to use the Cap desktop app. The commercial license includes the Cap Recorder + Editor with local-only features. Our Pro plan also includes a commercial license for the desktop app.",
+	},
+	{
+		title: "What happens after the beta period ends?",
+		answer:
+			"Early adopters will keep their special pricing for the lifetime of their subscription, even after we move out of beta and adjust our regular pricing. This is our way of thanking our early supporters.",
+	},
 ];
 
 export const FaqPage = () => {
-  return (
-    <div className="py-32 md:py-40 wrapper wrapper-sm">
-      <div className="mb-14 text-center page-intro">
-        <h1>FAQ</h1>
-      </div>
-      <div className="mb-10">
-        {faqContent.map((section, index) => {
-          return (
-            <div key={index} className="mx-auto my-8 max-w-2xl">
-              <h2 className="mb-2 text-xl">{section.title}</h2>
-              <p className="text-lg">{section.answer}</p>
-            </div>
-          );
-        })}
-      </div>
-    </div>
-  );
+	return (
+		<div className="py-32 md:py-40 wrapper wrapper-sm">
+			<div className="mb-14 text-center page-intro">
+				<h1>FAQ</h1>
+			</div>
+			<div className="mb-10">
+				{faqContent.map((section, index) => {
+					return (
+						<div key={index} className="mx-auto my-8 max-w-2xl">
+							<h2 className="mb-2 text-xl">{section.title}</h2>
+							<p className="text-lg">{section.answer}</p>
+						</div>
+					);
+				})}
+			</div>
+		</div>
+	);
 };
diff --git a/apps/web/components/pages/HomePage/Pricing/ProCard.tsx b/apps/web/components/pages/HomePage/Pricing/ProCard.tsx
index 4bbf1acee7..68846d3998 100644
--- a/apps/web/components/pages/HomePage/Pricing/ProCard.tsx
+++ b/apps/web/components/pages/HomePage/Pricing/ProCard.tsx
@@ -11,255 +11,255 @@ import { homepageCopy } from "../../../../data/homepage-copy";
 import { ProArt, type ProArtRef } from "./ProArt";
 
 export const ProCard = () => {
-  const [users, setUsers] = useState(1);
-  const [isAnnually, setIsAnnually] = useState(true);
-  const [proLoading, setProLoading] = useState(false);
-  const [guestLoading, setGuestLoading] = useState(false);
-  const proArtRef = useRef<ProArtRef>(null);
-  const { push } = useRouter();
+	const [users, setUsers] = useState(1);
+	const [isAnnually, setIsAnnually] = useState(true);
+	const [proLoading, setProLoading] = useState(false);
+	const [guestLoading, setGuestLoading] = useState(false);
+	const proArtRef = useRef<ProArtRef>(null);
+	const { push } = useRouter();
 
-  const CAP_PRO_ANNUAL_PRICE_PER_USER = homepageCopy.pricing.pro.pricing.annual;
-  const CAP_PRO_MONTHLY_PRICE_PER_USER =
-    homepageCopy.pricing.pro.pricing.monthly;
+	const CAP_PRO_ANNUAL_PRICE_PER_USER = homepageCopy.pricing.pro.pricing.annual;
+	const CAP_PRO_MONTHLY_PRICE_PER_USER =
+		homepageCopy.pricing.pro.pricing.monthly;
 
-  const currentTotalPricePro =
-    users *
-    (isAnnually
-      ? CAP_PRO_ANNUAL_PRICE_PER_USER
-      : CAP_PRO_MONTHLY_PRICE_PER_USER);
-  const billingCycleTextPro = isAnnually
-    ? "per user, billed annually"
-    : "per user, billed monthly";
+	const currentTotalPricePro =
+		users *
+		(isAnnually
+			? CAP_PRO_ANNUAL_PRICE_PER_USER
+			: CAP_PRO_MONTHLY_PRICE_PER_USER);
+	const billingCycleTextPro = isAnnually
+		? "per user, billed annually"
+		: "per user, billed monthly";
 
-  const incrementUsers = () => setUsers((prev) => prev + 1);
-  const decrementUsers = () => setUsers((prev) => (prev > 1 ? prev - 1 : 1));
+	const incrementUsers = () => setUsers((prev) => prev + 1);
+	const decrementUsers = () => setUsers((prev) => (prev > 1 ? prev - 1 : 1));
 
-  const guestCheckout = async (planId: string) => {
-    setGuestLoading(true);
+	const guestCheckout = async (planId: string) => {
+		setGuestLoading(true);
 
-    try {
-      const response = await fetch(`/api/settings/billing/guest-checkout`, {
-        method: "POST",
-        headers: {
-          "Content-Type": "application/json",
-        },
-        body: JSON.stringify({ priceId: planId, quantity: users }),
-      });
-      const data = await response.json();
+		try {
+			const response = await fetch(`/api/settings/billing/guest-checkout`, {
+				method: "POST",
+				headers: {
+					"Content-Type": "application/json",
+				},
+				body: JSON.stringify({ priceId: planId, quantity: users }),
+			});
+			const data = await response.json();
 
-      if (data.url) {
-        window.location.href = data.url;
-      } else {
-        toast.error("Failed to create checkout session");
-      }
-    } catch (error) {
-      toast.error("An error occurred. Please try again.");
-    } finally {
-      setGuestLoading(false);
-    }
-  };
+			if (data.url) {
+				window.location.href = data.url;
+			} else {
+				toast.error("Failed to create checkout session");
+			}
+		} catch (error) {
+			toast.error("An error occurred. Please try again.");
+		} finally {
+			setGuestLoading(false);
+		}
+	};
 
-  const planCheckout = async (planId?: string) => {
-    setProLoading(true);
+	const planCheckout = async (planId?: string) => {
+		setProLoading(true);
 
-    if (!planId) {
-      planId = getProPlanId(isAnnually ? "yearly" : "monthly");
-    }
+		if (!planId) {
+			planId = getProPlanId(isAnnually ? "yearly" : "monthly");
+		}
 
-    const response = await fetch(`/api/settings/billing/subscribe`, {
-      method: "POST",
-      headers: {
-        "Content-Type": "application/json",
-      },
-      body: JSON.stringify({ priceId: planId, quantity: users }),
-    });
-    const data = await response.json();
+		const response = await fetch(`/api/settings/billing/subscribe`, {
+			method: "POST",
+			headers: {
+				"Content-Type": "application/json",
+			},
+			body: JSON.stringify({ priceId: planId, quantity: users }),
+		});
+		const data = await response.json();
 
-    if (data.auth === false) {
-      // User not authenticated, do guest checkout
-      setProLoading(false);
-      await guestCheckout(planId);
-      return;
-    }
+		if (data.auth === false) {
+			// User not authenticated, do guest checkout
+			setProLoading(false);
+			await guestCheckout(planId);
+			return;
+		}
 
-    if (data.subscription === true) {
-      toast.success("You are already on the Cap Pro plan");
-    }
+		if (data.subscription === true) {
+			toast.success("You are already on the Cap Pro plan");
+		}
 
-    if (data.url) {
-      window.location.href = data.url;
-    }
+		if (data.url) {
+			window.location.href = data.url;
+		}
 
-    setProLoading(false);
-  };
+		setProLoading(false);
+	};
 
-  return (
-    <div
-      onMouseEnter={() => {
-        proArtRef.current?.playHoverAnimation();
-      }}
-      onMouseLeave={() => {
-        proArtRef.current?.playDefaultAnimation();
-      }}
-      className="flex relative flex-col flex-1 justify-between p-8 text-white rounded-2xl shadow-2xl bg-gray-12"
-    >
-      <div>
-        <div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
-          <span className="rounded-full font-mono bg-blue-500 px-4 py-1.5 text-xs uppercase text-gray-1">
-            {homepageCopy.pricing.pro.badge}
-          </span>
-        </div>
-        <div className="md:h-[300px]">
-          <ProArt ref={proArtRef} />
-          <h3 className="mb-2 text-2xl text-center">
-            {homepageCopy.pricing.pro.title}
-          </h3>
-          <p className="mb-6 text-base text-center text-gray-8">
-            {homepageCopy.pricing.pro.description}
-          </p>
-        </div>
+	return (
+		<div
+			onMouseEnter={() => {
+				proArtRef.current?.playHoverAnimation();
+			}}
+			onMouseLeave={() => {
+				proArtRef.current?.playDefaultAnimation();
+			}}
+			className="flex relative flex-col flex-1 justify-between p-8 text-white rounded-2xl shadow-2xl bg-gray-12"
+		>
+			<div>
+				<div className="absolute top-0 left-1/2 transform -translate-x-1/2 -translate-y-1/2">
+					<span className="rounded-full font-mono bg-blue-500 px-4 py-1.5 text-xs uppercase text-gray-1">
+						{homepageCopy.pricing.pro.badge}
+					</span>
+				</div>
+				<div className="md:h-[300px]">
+					<ProArt ref={proArtRef} />
+					<h3 className="mb-2 text-2xl text-center">
+						{homepageCopy.pricing.pro.title}
+					</h3>
+					<p className="mb-6 text-base text-center text-gray-8">
+						{homepageCopy.pricing.pro.description}
+					</p>
+				</div>
 
-        <div className="mb-6 text-center">
-          <span className="mr-2 text-5xl tabular-nums text-gray-1">
-            $<NumberFlow suffix="/mo" value={currentTotalPricePro} />
-          </span>
-          <span className="text-lg tabular-nums text-gray-8">
-            {" "}
-            {billingCycleTextPro}
-          </span>
-          {isAnnually ? (
-            <p className="text-lg text-gray-8">
-              or,{" "}
-              <NumberFlow
-                value={CAP_PRO_MONTHLY_PRICE_PER_USER * users}
-                className="text-lg tabular-nums"
-                format={{
-                  notation: "compact",
-                  style: "currency",
-                  currency: "USD",
-                }}
-                suffix="/mo"
-              />{" "}
-              {users === 1 ? (
-                "per user, "
-              ) : (
-                <>
-                  for{" "}
-                  <NumberFlow value={users} className="text-lg tabular-nums" />{" "}
-                  users,{" "}
-                </>
-              )}
-              billed monthly
-            </p>
-          ) : (
-            <p className="text-lg text-gray-8">
-              or,{" "}
-              <NumberFlow
-                value={CAP_PRO_ANNUAL_PRICE_PER_USER * users}
-                className="text-lg tabular-nums"
-                format={{
-                  notation: "compact",
-                  style: "currency",
-                  currency: "USD",
-                }}
-                suffix="/mo"
-              />{" "}
-              {users === 1 ? (
-                "per user, "
-              ) : (
-                <>
-                  for{" "}
-                  <NumberFlow value={users} className="text-lg tabular-nums" />{" "}
-                  users,{" "}
-                </>
-              )}
-              billed annually
-            </p>
-          )}
-        </div>
+				<div className="mb-6 text-center">
+					<span className="mr-2 text-5xl tabular-nums text-gray-1">
+						$<NumberFlow suffix="/mo" value={currentTotalPricePro} />
+					</span>
+					<span className="text-lg tabular-nums text-gray-8">
+						{" "}
+						{billingCycleTextPro}
+					</span>
+					{isAnnually ? (
+						<p className="text-lg text-gray-8">
+							or,{" "}
+							<NumberFlow
+								value={CAP_PRO_MONTHLY_PRICE_PER_USER * users}
+								className="text-lg tabular-nums"
+								format={{
+									notation: "compact",
+									style: "currency",
+									currency: "USD",
+								}}
+								suffix="/mo"
+							/>{" "}
+							{users === 1 ? (
+								"per user, "
+							) : (
+								<>
+									for{" "}
+									<NumberFlow value={users} className="text-lg tabular-nums" />{" "}
+									users,{" "}
+								</>
+							)}
+							billed monthly
+						</p>
+					) : (
+						<p className="text-lg text-gray-8">
+							or,{" "}
+							<NumberFlow
+								value={CAP_PRO_ANNUAL_PRICE_PER_USER * users}
+								className="text-lg tabular-nums"
+								format={{
+									notation: "compact",
+									style: "currency",
+									currency: "USD",
+								}}
+								suffix="/mo"
+							/>{" "}
+							{users === 1 ? (
+								"per user, "
+							) : (
+								<>
+									for{" "}
+									<NumberFlow value={users} className="text-lg tabular-nums" />{" "}
+									users,{" "}
+								</>
+							)}
+							billed annually
+						</p>
+					)}
+				</div>
 
-        <div className="flex flex-wrap gap-5 justify-center items-center p-5 my-8 w-full rounded-xl border xs:gap-3 xs:p-3 xs:rounded-full xs:justify-between bg-zinc-700/50 border-zinc-700">
-          <div className="flex gap-3 justify-center items-center">
-            <p className="text-base text-gray-1">
-              {homepageCopy.pricing.pro.labels.users}
-            </p>
-            <div className="flex items-center">
-              <Button
-                onClick={decrementUsers}
-                className="px-1.5 py-1.5 bg-gray-1 hover:bg-gray-3 min-w-fit h-fit"
-                aria-label="Decrease user count"
-              >
-                <FontAwesomeIcon
-                  icon={faMinus}
-                  className="text-gray-12 size-3"
-                />
-              </Button>
-              <span className="w-8 font-medium tabular-nums text-center text-white">
-                <NumberFlow value={users} />
-              </span>
-              <Button
-                onClick={incrementUsers}
-                className="px-1.5 py-1.5 bg-gray-1 hover:bg-gray-3 min-w-fit h-fit"
-                aria-label="Increase user count"
-              >
-                <FontAwesomeIcon
-                  icon={faPlus}
-                  className="text-gray-12 size-3"
-                />
-              </Button>
-            </div>
-          </div>
+				<div className="flex flex-wrap gap-5 justify-center items-center p-5 my-8 w-full rounded-xl border xs:gap-3 xs:p-3 xs:rounded-full xs:justify-between bg-zinc-700/50 border-zinc-700">
+					<div className="flex gap-3 justify-center items-center">
+						<p className="text-base text-gray-1">
+							{homepageCopy.pricing.pro.labels.users}
+						</p>
+						<div className="flex items-center">
+							<Button
+								onClick={decrementUsers}
+								className="px-1.5 py-1.5 bg-gray-1 hover:bg-gray-3 min-w-fit h-fit"
+								aria-label="Decrease user count"
+							>
+								<FontAwesomeIcon
+									icon={faMinus}
+									className="text-gray-12 size-3"
+								/>
+							</Button>
+							<span className="w-8 font-medium tabular-nums text-center text-white">
+								<NumberFlow value={users} />
+							</span>
+							<Button
+								onClick={incrementUsers}
+								className="px-1.5 py-1.5 bg-gray-1 hover:bg-gray-3 min-w-fit h-fit"
+								aria-label="Increase user count"
+							>
+								<FontAwesomeIcon
+									icon={faPlus}
+									className="text-gray-12 size-3"
+								/>
+							</Button>
+						</div>
+					</div>
 
-          <div className="flex justify-center items-center">
-            <div className="flex gap-2 items-center">
-              <span
-                className={clsx(
-                  "text-md",
-                  !isAnnually ? "text-white" : "text-gray-8"
-                )}
-              >
-                {homepageCopy.pricing.pro.labels.monthly}
-              </span>
-              <Switch
-                checked={isAnnually}
-                onCheckedChange={setIsAnnually}
-                aria-label="Billing Cycle For Pro"
-                id="billing-cycle-cap-pro"
-              />
-              <span
-                className={clsx(
-                  "text-md",
-                  isAnnually ? "text-white" : "text-gray-8"
-                )}
-              >
-                {homepageCopy.pricing.pro.labels.annually}
-              </span>
-            </div>
-          </div>
-        </div>
+					<div className="flex justify-center items-center">
+						<div className="flex gap-2 items-center">
+							<span
+								className={clsx(
+									"text-md",
+									!isAnnually ? "text-white" : "text-gray-8",
+								)}
+							>
+								{homepageCopy.pricing.pro.labels.monthly}
+							</span>
+							<Switch
+								checked={isAnnually}
+								onCheckedChange={setIsAnnually}
+								aria-label="Billing Cycle For Pro"
+								id="billing-cycle-cap-pro"
+							/>
+							<span
+								className={clsx(
+									"text-md",
+									isAnnually ? "text-white" : "text-gray-8",
+								)}
+							>
+								{homepageCopy.pricing.pro.labels.annually}
+							</span>
+						</div>
+					</div>
+				</div>
 
-        <ul className="mb-8 space-y-3 text-base">
-          {homepageCopy.pricing.pro.features.map((feature) => (
-            <li key={feature} className="flex items-center text-gray-1">
-              <FontAwesomeIcon icon={faCheck} className="mr-2 text-gray-1" />
-              {feature}
-            </li>
-          ))}
-        </ul>
-      </div>
+				<ul className="mb-8 space-y-3 text-base">
+					{homepageCopy.pricing.pro.features.map((feature) => (
+						<li key={feature} className="flex items-center text-gray-1">
+							<FontAwesomeIcon icon={faCheck} className="mr-2 text-gray-1" />
+							{feature}
+						</li>
+					))}
+				</ul>
+			</div>
 
-      <Button
-        variant="blue"
-        size="lg"
-        onClick={() => planCheckout()}
-        disabled={proLoading || guestLoading}
-        className="w-full font-medium"
-        aria-label="Purchase Cap Pro License"
-      >
-        {proLoading || guestLoading
-          ? "Loading..."
-          : homepageCopy.pricing.pro.cta}
-      </Button>
-    </div>
-  );
+			<Button
+				variant="blue"
+				size="lg"
+				onClick={() => planCheckout()}
+				disabled={proLoading || guestLoading}
+				className="w-full font-medium"
+				aria-label="Purchase Cap Pro License"
+			>
+				{proLoading || guestLoading
+					? "Loading..."
+					: homepageCopy.pricing.pro.cta}
+			</Button>
+		</div>
+	);
 };
diff --git a/apps/web/components/pages/seo/LoomAlternativePage.tsx b/apps/web/components/pages/seo/LoomAlternativePage.tsx
index 73d4e4c341..749a4db710 100644
--- a/apps/web/components/pages/seo/LoomAlternativePage.tsx
+++ b/apps/web/components/pages/seo/LoomAlternativePage.tsx
@@ -4,195 +4,195 @@ import Script from "next/script";
 import { SeoPageTemplate } from "../../seo/SeoPageTemplate";
 
 export const loomAlternativeContent = {
-  title:
-    "The Ultimate Loom Alternative: Why Cap is the Best Open-Source Screen Recorder for Mac & Windows",
-  description:
-    "Looking for the best Loom alternative? Discover Cap, the open-source, privacy-focused screen recorder for Mac & Windows. See why users are switching today!",
+	title:
+		"The Ultimate Loom Alternative: Why Cap is the Best Open-Source Screen Recorder for Mac & Windows",
+	description:
+		"Looking for the best Loom alternative? Discover Cap, the open-source, privacy-focused screen recorder for Mac & Windows. See why users are switching today!",
 
-  featuresTitle: "Why Cap is the Best Loom Alternative",
-  featuresDescription:
-    "Cap offers everything you need in a privacy-focused, open-source screen recording solution",
+	featuresTitle: "Why Cap is the Best Loom Alternative",
+	featuresDescription:
+		"Cap offers everything you need in a privacy-focused, open-source screen recording solution",
 
-  features: [
-    {
-      title: "Open-Source Transparency",
-      description:
-        "Cap is fully open-source, giving you complete transparency and community-driven development. We believe in building in public and letting users help shape our roadmap. Looking for an <a href='/free-screen-recorder'>open-source screen recorder</a>? Cap is your best choice!",
-    },
-    {
-      title: "Enhanced Privacy & Security",
-      description:
-        "Cap prioritizes your privacy with GDPR compliance and the option to use your own S3 storage, ensuring your data remains under your control. Connect your own custom domain for a branded experience while maintaining 100% ownership of your data.",
-    },
-    {
-      title: "Half the Price of Loom",
-      description:
-        "Cap stars from just $8.16/month per user, compared to Loom's $18/month per user. Plus, Cap offers a generous free plan that includes Studio mode for personal use.",
-    },
-    {
-      title: "High-Quality Recordings",
-      description:
-        "Record smooth, high-definition videos at 60fps with synchronized audio up to 4K resolution, perfect for professional use.",
-    },
-    {
-      title: "Collaborative Features",
-      description:
-        "Cap includes built-in thread commenting on shareable links, making it easy to collaborate with teammates and collect feedback on your recordings without switching platforms.",
-    },
-    {
-      title: "Cross-Platform Support",
-      description:
-        "Available for both Mac and Windows, Cap delivers consistent performance across platforms. A perfect <a href='/screen-recording-software'>screen recording software</a> for all users.",
-    },
-  ],
+	features: [
+		{
+			title: "Open-Source Transparency",
+			description:
+				"Cap is fully open-source, giving you complete transparency and community-driven development. We believe in building in public and letting users help shape our roadmap. Looking for an <a href='/free-screen-recorder'>open-source screen recorder</a>? Cap is your best choice!",
+		},
+		{
+			title: "Enhanced Privacy & Security",
+			description:
+				"Cap prioritizes your privacy with GDPR compliance and the option to use your own S3 storage, ensuring your data remains under your control. Connect your own custom domain for a branded experience while maintaining 100% ownership of your data.",
+		},
+		{
+			title: "Half the Price of Loom",
+			description:
+				"Cap stars from just $8.16/month per user, compared to Loom's $18/month per user. Plus, Cap offers a generous free plan that includes Studio mode for personal use.",
+		},
+		{
+			title: "High-Quality Recordings",
+			description:
+				"Record smooth, high-definition videos at 60fps with synchronized audio up to 4K resolution, perfect for professional use.",
+		},
+		{
+			title: "Collaborative Features",
+			description:
+				"Cap includes built-in thread commenting on shareable links, making it easy to collaborate with teammates and collect feedback on your recordings without switching platforms.",
+		},
+		{
+			title: "Cross-Platform Support",
+			description:
+				"Available for both Mac and Windows, Cap delivers consistent performance across platforms. A perfect <a href='/screen-recording-software'>screen recording software</a> for all users.",
+		},
+	],
 
-  recordingModes: {
-    title: "Two Ways to Record with Cap",
-    description:
-      "Cap gives you flexible recording options to match your workflow needs, with both modes available in the free plan",
-    modes: [
-      {
-        title: "Instant Mode",
-        description:
-          "Share your screen right away with a simple link—no waiting, just record and share in seconds. Record up to 5-minute shareable links for free, perfect for quick demos and explanations. Includes built-in thread commenting for easy collaboration.",
-      },
-      {
-        title: "Studio Mode",
-        description:
-          "Available completely free for personal use! Records at top quality up to 4K. Captures both your screen and webcam separately so you can edit them later, giving you professional-level production control.",
-      },
-    ],
-  },
+	recordingModes: {
+		title: "Two Ways to Record with Cap",
+		description:
+			"Cap gives you flexible recording options to match your workflow needs, with both modes available in the free plan",
+		modes: [
+			{
+				title: "Instant Mode",
+				description:
+					"Share your screen right away with a simple link—no waiting, just record and share in seconds. Record up to 5-minute shareable links for free, perfect for quick demos and explanations. Includes built-in thread commenting for easy collaboration.",
+			},
+			{
+				title: "Studio Mode",
+				description:
+					"Available completely free for personal use! Records at top quality up to 4K. Captures both your screen and webcam separately so you can edit them later, giving you professional-level production control.",
+			},
+		],
+	},
 
-  useCasesTitle: "Why Users Choose Cap for Screen Recording",
-  useCasesDescription:
-    "Discover the features that make Cap a compelling option for screen recording",
+	useCasesTitle: "Why Users Choose Cap for Screen Recording",
+	useCasesDescription:
+		"Discover the features that make Cap a compelling option for screen recording",
 
-  useCases: [
-    {
-      title: "Budget-Friendly Options",
-      description:
-        "Many screen recording tools have complex pricing structures. Cap offers similar functionality with clear, affordable pricing options.",
-    },
-    {
-      title: "Complete Data Ownership",
-      description:
-        "Cap lets you connect your own S3 storage and custom domain, giving you 100% ownership and control over your content. No more being locked into proprietary platforms.",
-    },
-    {
-      title: "Community-Driven Development",
-      description:
-        "As an <a href='/screen-recorder'>open-source screen recorder</a>, Cap is built in the open with community input. User feedback directly shapes our roadmap and features.",
-    },
-    {
-      title: "Collaborative Feedback",
-      description:
-        "Cap's built-in thread commenting on shareable links makes it easy to collect feedback and collaborate without switching between different tools.",
-    },
-  ],
+	useCases: [
+		{
+			title: "Budget-Friendly Options",
+			description:
+				"Many screen recording tools have complex pricing structures. Cap offers similar functionality with clear, affordable pricing options.",
+		},
+		{
+			title: "Complete Data Ownership",
+			description:
+				"Cap lets you connect your own S3 storage and custom domain, giving you 100% ownership and control over your content. No more being locked into proprietary platforms.",
+		},
+		{
+			title: "Community-Driven Development",
+			description:
+				"As an <a href='/screen-recorder'>open-source screen recorder</a>, Cap is built in the open with community input. User feedback directly shapes our roadmap and features.",
+		},
+		{
+			title: "Collaborative Feedback",
+			description:
+				"Cap's built-in thread commenting on shareable links makes it easy to collect feedback and collaborate without switching between different tools.",
+		},
+	],
 
-  faqsTitle: "Frequently Asked Questions",
-  faqs: [
-    {
-      question: "Is there a free Loom alternative?",
-      answer:
-        "Yes, Cap offers a generous free tier that includes all essential screen recording features. You can use Studio mode completely free for personal use, record up to 5-minute shareable links, and record in up to 4K resolution. Cap's free plan offers more than Loom's free tier.",
-    },
-    {
-      question: "Why choose an open-source screen recorder?",
-      answer:
-        "Open-source screen recorders like Cap provide transparency, security, and community-driven development. You can verify the code, contribute improvements, and trust that your data isn't being misused. Cap's community focus means features are developed based on real user needs.",
-    },
-    {
-      question: "How does Cap compare in pricing with Loom?",
-      answer:
-        "Cap is significantly more affordable at just $8.16/month per user when billed annually, compared to Loom's $18/month per user. Cap also has a more generous free plan that includes Studio mode for personal use and the ability to record shareable links up to 5 minutes in 4K quality.",
-    },
-    {
-      question: "Can I keep full ownership of my recordings with Cap?",
-      answer:
-        "Absolutely! Cap allows you to connect your own S3 storage and custom domain, giving you 100% ownership and control of your content. Your data remains yours, and you're never locked into our platform.",
-    },
-    {
-      question: "Does Cap support collaboration features?",
-      answer:
-        "Yes, Cap includes built-in thread commenting on shareable links, making it easy to collaborate with teammates and collect feedback directly on your recordings. This keeps all your communication in one place.",
-    },
-  ],
+	faqsTitle: "Frequently Asked Questions",
+	faqs: [
+		{
+			question: "Is there a free Loom alternative?",
+			answer:
+				"Yes, Cap offers a generous free tier that includes all essential screen recording features. You can use Studio mode completely free for personal use, record up to 5-minute shareable links, and record in up to 4K resolution. Cap's free plan offers more than Loom's free tier.",
+		},
+		{
+			question: "Why choose an open-source screen recorder?",
+			answer:
+				"Open-source screen recorders like Cap provide transparency, security, and community-driven development. You can verify the code, contribute improvements, and trust that your data isn't being misused. Cap's community focus means features are developed based on real user needs.",
+		},
+		{
+			question: "How does Cap compare in pricing with Loom?",
+			answer:
+				"Cap is significantly more affordable at just $8.16/month per user when billed annually, compared to Loom's $18/month per user. Cap also has a more generous free plan that includes Studio mode for personal use and the ability to record shareable links up to 5 minutes in 4K quality.",
+		},
+		{
+			question: "Can I keep full ownership of my recordings with Cap?",
+			answer:
+				"Absolutely! Cap allows you to connect your own S3 storage and custom domain, giving you 100% ownership and control of your content. Your data remains yours, and you're never locked into our platform.",
+		},
+		{
+			question: "Does Cap support collaboration features?",
+			answer:
+				"Yes, Cap includes built-in thread commenting on shareable links, making it easy to collaborate with teammates and collect feedback directly on your recordings. This keeps all your communication in one place.",
+		},
+	],
 
-  comparisonTable: {
-    title: "Feature Comparison: Cap vs. Loom",
-    headers: ["Feature", "Cap", "Loom"],
-    rows: [
-      ["Open Source", "✅ Yes", "❌ No"],
-      ["Pricing", "✅ $from 8.16/month per user", "⚠️ $18/month per user"],
-      [
-        "Free Plan",
-        "✅ Studio mode + 5 min shareable links",
-        "⚠️ Limited features & recording time",
-      ],
-      [
-        "4K Recording",
-        "✅ Available in free & paid plans",
-        "⚠️ Only in paid plans",
-      ],
-      ["Thread Commenting", "✅ Built-in on shareable links", "☑️ Available"],
-      ["Custom Domain", "✅ Yes", "☑️ Enterprise plan only"],
-      ["Own Storage Integration", "✅ Connect your own S3", "❌ Not available"],
-      ["Community Input", "✅ Direct via open source", "☑️ Limited"],
-      ["Data Ownership", "✅ 100% with own storage", "☑️ Platform dependent"],
-    ],
-  },
-  migrationGuide: {
-    title: "How to Get Started with Cap (Easy Guide)",
-    steps: [
-      "Download Cap for your operating system (Mac or Windows)",
-      "Launch the application",
-      "Start recording using either Instant Mode or Studio Mode",
-      "Share your recordings easily with Cap's built-in sharing features",
-      "Optional: Connect your own S3 storage and custom domain for complete data ownership",
-    ],
-  },
+	comparisonTable: {
+		title: "Feature Comparison: Cap vs. Loom",
+		headers: ["Feature", "Cap", "Loom"],
+		rows: [
+			["Open Source", "✅ Yes", "❌ No"],
+			["Pricing", "✅ $from 8.16/month per user", "⚠️ $18/month per user"],
+			[
+				"Free Plan",
+				"✅ Studio mode + 5 min shareable links",
+				"⚠️ Limited features & recording time",
+			],
+			[
+				"4K Recording",
+				"✅ Available in free & paid plans",
+				"⚠️ Only in paid plans",
+			],
+			["Thread Commenting", "✅ Built-in on shareable links", "☑️ Available"],
+			["Custom Domain", "✅ Yes", "☑️ Enterprise plan only"],
+			["Own Storage Integration", "✅ Connect your own S3", "❌ Not available"],
+			["Community Input", "✅ Direct via open source", "☑️ Limited"],
+			["Data Ownership", "✅ 100% with own storage", "☑️ Platform dependent"],
+		],
+	},
+	migrationGuide: {
+		title: "How to Get Started with Cap (Easy Guide)",
+		steps: [
+			"Download Cap for your operating system (Mac or Windows)",
+			"Launch the application",
+			"Start recording using either Instant Mode or Studio Mode",
+			"Share your recordings easily with Cap's built-in sharing features",
+			"Optional: Connect your own S3 storage and custom domain for complete data ownership",
+		],
+	},
 
-  video: {
-    url: "/videos/cap-vs-loom-comparison.mp4",
-    thumbnail: "/videos/cap-vs-loom-thumbnail.png",
-    alt: "Cap screen recorder demo showing privacy features and interface",
-  },
+	video: {
+		url: "/videos/cap-vs-loom-comparison.mp4",
+		thumbnail: "/videos/cap-vs-loom-thumbnail.png",
+		alt: "Cap screen recorder demo showing privacy features and interface",
+	},
 
-  cta: {
-    title: "Ready to Try Cap for Your Screen Recording Needs?",
-    buttonText: "Download Cap Free",
-  },
+	cta: {
+		title: "Ready to Try Cap for Your Screen Recording Needs?",
+		buttonText: "Download Cap Free",
+	},
 };
 
 // Create FAQ structured data for SEO
 const createFaqStructuredData = () => {
-  const faqStructuredData = {
-    "@context": "https://schema.org",
-    "@type": "FAQPage",
-    mainEntity: loomAlternativeContent.faqs.map((faq) => ({
-      "@type": "Question",
-      name: faq.question,
-      acceptedAnswer: {
-        "@type": "Answer",
-        text: faq.answer.replace(/<\/?[^>]+(>|$)/g, ""),
-      },
-    })),
-  };
+	const faqStructuredData = {
+		"@context": "https://schema.org",
+		"@type": "FAQPage",
+		mainEntity: loomAlternativeContent.faqs.map((faq) => ({
+			"@type": "Question",
+			name: faq.question,
+			acceptedAnswer: {
+				"@type": "Answer",
+				text: faq.answer.replace(/<\/?[^>]+(>|$)/g, ""),
+			},
+		})),
+	};
 
-  return JSON.stringify(faqStructuredData);
+	return JSON.stringify(faqStructuredData);
 };
 
 export const LoomAlternativePage = () => {
-  return (
-    <>
-      <Script
-        id="faq-structured-data"
-        type="application/ld+json"
-        dangerouslySetInnerHTML={{ __html: createFaqStructuredData() }}
-      />
-      <SeoPageTemplate content={loomAlternativeContent} />
-    </>
-  );
+	return (
+		<>
+			<Script
+				id="faq-structured-data"
+				type="application/ld+json"
+				dangerouslySetInnerHTML={{ __html: createFaqStructuredData() }}
+			/>
+			<SeoPageTemplate content={loomAlternativeContent} />
+		</>
+	);
 };
