From 141f411b714b88516071d7dba73cec54f32d3a23 Mon Sep 17 00:00:00 2001 From: Mohamed Bassem Date: Sat, 19 Jul 2025 17:49:48 +0000 Subject: feat(landing): The pricing page --- apps/landing/package.json | 1 + apps/landing/src/App.tsx | 17 ++-- apps/landing/src/Homepage.tsx | 44 +-------- apps/landing/src/Navbar.tsx | 59 +++++++++++ apps/landing/src/Pricing.tsx | 224 ++++++++++++++++++++++++++++++++++++++++++ apps/landing/src/constants.ts | 4 + 6 files changed, 301 insertions(+), 48 deletions(-) create mode 100644 apps/landing/src/Navbar.tsx create mode 100644 apps/landing/src/Pricing.tsx create mode 100644 apps/landing/src/constants.ts (limited to 'apps') diff --git a/apps/landing/package.json b/apps/landing/package.json index 3343a542..e6db4d83 100644 --- a/apps/landing/package.json +++ b/apps/landing/package.json @@ -22,6 +22,7 @@ "lucide-react": "^0.501.0", "react": "^18.3.1", "react-dom": "^18.3.1", + "react-router": "^7.7.1", "react-select": "^5.8.0", "sharp": "^0.33.3", "tailwind-merge": "^2.2.1", diff --git a/apps/landing/src/App.tsx b/apps/landing/src/App.tsx index ddf92e32..45a019c5 100644 --- a/apps/landing/src/App.tsx +++ b/apps/landing/src/App.tsx @@ -1,13 +1,18 @@ import Homepage from "@/src/Homepage"; +import Pricing from "@/src/Pricing"; import Privacy from "@/src/Privacy"; +import { BrowserRouter, Route, Routes } from "react-router"; import "@karakeep/tailwind-config/globals.css"; export default function App() { - // Poor man router - if (window.location.pathname === "/privacy") { - return ; - } - - return ; + return ( + + + } /> + } /> + } /> + + + ); } diff --git a/apps/landing/src/Homepage.tsx b/apps/landing/src/Homepage.tsx index 7ab7fdfd..f88f35af 100644 --- a/apps/landing/src/Homepage.tsx +++ b/apps/landing/src/Homepage.tsx @@ -12,16 +12,13 @@ import { WalletCards, } from "lucide-react"; +import { DEMO_LINK, DOCS_LINK, GITHUB_LINK } from "./constants"; +import NavBar from "./Navbar"; import appStoreBadge from "/app-store-badge.png?url"; import chromeExtensionBadge from "/chrome-extension-badge.png?url"; import firefoxAddonBadge from "/firefox-addon.png?url"; import playStoreBadge from "/google-play-badge.webp?url"; import screenshot from "/hero.webp?url"; -import Logo from "/icons/karakeep-full.svg?url"; - -const GITHUB_LINK = "https://github.com/karakeep-app/karakeep"; -const DOCS_LINK = "https://docs.karakeep.app"; -const DEMO_LINK = "https://try.karakeep.app"; const platforms = [ { @@ -93,43 +90,6 @@ const featuresList = [ const currentYear = new Date().getFullYear(); -function NavBar() { - return ( -
- logo -
- - Docs - - - GitHub - - - Try Demo - -
-
- ); -} - function Hero() { return (
diff --git a/apps/landing/src/Navbar.tsx b/apps/landing/src/Navbar.tsx new file mode 100644 index 00000000..6d252db4 --- /dev/null +++ b/apps/landing/src/Navbar.tsx @@ -0,0 +1,59 @@ +import { buttonVariants } from "@/components/ui/button"; +import { cn } from "@/lib/utils"; +import { Link } from "react-router"; + +import { DEMO_LINK, DOCS_LINK, GITHUB_LINK } from "./constants"; +import Logo from "/icons/karakeep-full.svg?url"; + +export default function NavBar() { + return ( +
+ + logo + + +
+ ); +} diff --git a/apps/landing/src/Pricing.tsx b/apps/landing/src/Pricing.tsx new file mode 100644 index 00000000..9a1c06f0 --- /dev/null +++ b/apps/landing/src/Pricing.tsx @@ -0,0 +1,224 @@ +import { buttonVariants } from "@/components/ui/button"; +import { cn } from "@/lib/utils"; +import { Check, ExternalLink } from "lucide-react"; + +import { DOCS_LINK, GITHUB_LINK, WAITLIST_LINK } from "./constants"; +import NavBar from "./Navbar"; + +const pricingTiers = [ + { + name: "Free", + price: "$0", + period: "", + description: "Trying Karakeep out", + features: [ + "10 bookmarks", + "20MB storage", + "Mobile & web apps", + "Browser extensions", + ], + buttonText: "Join Waitlist", + buttonVariant: "outline" as const, + popular: false, + }, + { + name: "Pro", + price: "$4", + period: "per month", + description: "For serious bookmark collectors", + features: [ + "50,000 bookmarks", + "50GB storage", + "AI-powered tagging", + "Full-text search", + "Mobile & web apps", + "Browser extensions", + ], + buttonText: "Join Waitlist", + buttonVariant: "default" as const, + popular: true, + }, + { + name: "Self-Hosted", + price: "Free", + period: "forever", + description: "Complete control and privacy", + features: [ + "Unlimited bookmarks", + "Unlimited storage", + "Complete data control", + "Mobile & web apps", + "Browser extensions", + "Community support", + ], + buttonText: "View on GitHub", + buttonVariant: "outline" as const, + popular: false, + isGitHub: true, + }, +]; + +function PricingHeader() { + return ( +
+

+ Simple{" "} + + Pricing + +

+

+ Choose the plan that works best for you +

+
+ ); +} + +function PricingCards() { + return ( +
+ {pricingTiers.map((tier) => ( +
+
+

{tier.name}

+
+ {tier.price} + {tier.period && ( + /{tier.period} + )} +
+

{tier.description}

+
+ +
    + {tier.features.map((feature) => ( +
  • + + {feature} +
  • + ))} +
+ +
+ {tier.isGitHub ? ( + + + {tier.buttonText} + + ) : ( + + {tier.buttonText} + + )} +
+
+ ))} +
+ ); +} + +function FAQ() { + const faqs = [ + { + question: "What happens to my data if I cancel?", + answer: + "Your data will be available for 30 days after cancellation. You can export your bookmarks at any time.", + }, + { + question: "Are there any restrictions in the self-hosted version?", + answer: + "No. The selhosted version is completely free, fully-featured, and open source. You just need to provide your own hosting infrastructure.", + }, + { + question: "Do you offer refunds?", + answer: "Yes, we offer a 7-day money-back guarantee for all paid plans.", + }, + ]; + + return ( +
+

+ Frequently Asked Questions +

+
+ {faqs.map((faq) => ( +
+

{faq.question}

+

{faq.answer}

+
+ ))} +
+
+ ); +} + +function Footer() { + const currentYear = new Date().getFullYear(); + + return ( +
+
+ © 2024-{currentYear}{" "} + + Localhost Labs Ltd + +
+ +
+ ); +} + +export default function Pricing() { + return ( +
+
+ +
+ + + +
+
+
+ ); +} diff --git a/apps/landing/src/constants.ts b/apps/landing/src/constants.ts new file mode 100644 index 00000000..b75cecae --- /dev/null +++ b/apps/landing/src/constants.ts @@ -0,0 +1,4 @@ +export const GITHUB_LINK = "https://github.com/karakeep-app/karakeep"; +export const DOCS_LINK = "https://docs.karakeep.app"; +export const DEMO_LINK = "https://try.karakeep.app"; +export const WAITLIST_LINK = "https://tally.so/r/wo8zzx"; -- cgit v1.2.3-70-g09d2