diff --git a/frontend/public/android-chrome-192x192.png b/frontend/public/android-chrome-192x192.png index 99b03d7d7..0c7d53131 100644 Binary files a/frontend/public/android-chrome-192x192.png and b/frontend/public/android-chrome-192x192.png differ diff --git a/frontend/public/app-store-badge.svg b/frontend/public/app-store-badge.svg new file mode 100755 index 000000000..072b425a1 --- /dev/null +++ b/frontend/public/app-store-badge.svg @@ -0,0 +1,46 @@ + + Download_on_the_App_Store_Badge_US-UK_RGB_blk_4SVG_092917 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/apple-touch-icon.png b/frontend/public/apple-touch-icon.png index 215202c53..b9ec8c9eb 100644 Binary files a/frontend/public/apple-touch-icon.png and b/frontend/public/apple-touch-icon.png differ diff --git a/frontend/public/favicon.png b/frontend/public/favicon.png index dcfd32ccc..b1bd71484 100644 Binary files a/frontend/public/favicon.png and b/frontend/public/favicon.png differ diff --git a/frontend/public/google-play-badge.png b/frontend/public/google-play-badge.png new file mode 100644 index 000000000..7a06997a5 Binary files /dev/null and b/frontend/public/google-play-badge.png differ diff --git a/frontend/public/javier-r.jpg b/frontend/public/javier-r.jpg new file mode 100644 index 000000000..e221d5476 Binary files /dev/null and b/frontend/public/javier-r.jpg differ diff --git a/frontend/public/lauren-t.jpg b/frontend/public/lauren-t.jpg new file mode 100644 index 000000000..47e68916b Binary files /dev/null and b/frontend/public/lauren-t.jpg differ diff --git a/frontend/public/maple-app-icon-vector.svg b/frontend/public/maple-app-icon-vector.svg new file mode 100644 index 000000000..ec71f046d --- /dev/null +++ b/frontend/public/maple-app-icon-vector.svg @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + diff --git a/frontend/public/maple-icon-nobg.png b/frontend/public/maple-icon-nobg.png new file mode 100644 index 000000000..6309c9d2f Binary files /dev/null and b/frontend/public/maple-icon-nobg.png differ diff --git a/frontend/public/maple-icon.png b/frontend/public/maple-icon.png new file mode 100644 index 000000000..be76918ae Binary files /dev/null and b/frontend/public/maple-icon.png differ diff --git a/frontend/public/maple-logo-dark.svg b/frontend/public/maple-logo-dark.svg new file mode 100644 index 000000000..7fe0aba8d --- /dev/null +++ b/frontend/public/maple-logo-dark.svg @@ -0,0 +1,9 @@ + + + + + + + + + diff --git a/frontend/public/october-light.webp b/frontend/public/october-light.webp deleted file mode 100644 index df2ac9775..000000000 Binary files a/frontend/public/october-light.webp and /dev/null differ diff --git a/frontend/public/october.webp b/frontend/public/october.webp deleted file mode 100644 index 244567d93..000000000 Binary files a/frontend/public/october.webp and /dev/null differ diff --git a/frontend/public/pandora.jpg b/frontend/public/pandora.jpg deleted file mode 100644 index 897736237..000000000 Binary files a/frontend/public/pandora.jpg and /dev/null differ diff --git a/frontend/public/pandora.webp b/frontend/public/pandora.webp deleted file mode 100644 index 742d3fa9b..000000000 Binary files a/frontend/public/pandora.webp and /dev/null differ diff --git a/frontend/public/ryan-g.jpg b/frontend/public/ryan-g.jpg new file mode 100644 index 000000000..44ee2c844 Binary files /dev/null and b/frontend/public/ryan-g.jpg differ diff --git a/frontend/public/twitter-card.jpg b/frontend/public/twitter-card.jpg index 68d2cdf01..44d5a437d 100644 Binary files a/frontend/public/twitter-card.jpg and b/frontend/public/twitter-card.jpg differ diff --git a/frontend/src/components/AccountMenu.tsx b/frontend/src/components/AccountMenu.tsx index e1b14cceb..b01ee3fa2 100644 --- a/frontend/src/components/AccountMenu.tsx +++ b/frontend/src/components/AccountMenu.tsx @@ -125,7 +125,7 @@ export function AccountMenu() { {billingStatus ? `${billingStatus.product_name} Plan` : "Loading..."} diff --git a/frontend/src/components/AuthMain.tsx b/frontend/src/components/AuthMain.tsx index 486781584..710a230f4 100644 --- a/frontend/src/components/AuthMain.tsx +++ b/frontend/src/components/AuthMain.tsx @@ -10,24 +10,35 @@ type AuthMainProps = { export function AuthMain({ children, title, description }: AuthMainProps) { return ( -
- - Maple AI logo - - - - {title} - {description && {description}} - - {children} - -
+
+
+ + Maple AI logo + Maple AI logo + + + + {title} + {description && {description}} + + {children} + +
+
+
+
); } diff --git a/frontend/src/components/BillingStatus.tsx b/frontend/src/components/BillingStatus.tsx index 543b25ff0..9f92badba 100644 --- a/frontend/src/components/BillingStatus.tsx +++ b/frontend/src/components/BillingStatus.tsx @@ -64,7 +64,7 @@ export function BillingStatus() { {isFree && (
navigate({ to: "/pricing" })} - className="bg-white/10 backdrop-blur-sm px-6 py-2 rounded-full border border-white/20 text-sm font-light hover:bg-white/20 transition-colors cursor-pointer flex items-center gap-2 w-fit" + className="dark:bg-white/10 bg-[hsl(var(--primary))]/5 backdrop-blur-sm px-6 py-2 rounded-full dark:border-white/20 border-[hsl(var(--primary))]/20 border text-sm font-light dark:hover:bg-white/20 hover:bg-[hsl(var(--primary))]/10 transition-colors cursor-pointer flex items-center gap-2 w-fit dark:text-white text-foreground" > Save 10% with yearly Bitcoin plans → diff --git a/frontend/src/components/CreditUsage.tsx b/frontend/src/components/CreditUsage.tsx index 3fbc2c799..c6ad5b84b 100644 --- a/frontend/src/components/CreditUsage.tsx +++ b/frontend/src/components/CreditUsage.tsx @@ -15,18 +15,26 @@ export function CreditUsage() { ); const roundedPercent = Math.round(percentUsed); + // Set bar color based on usage + const getBarColor = () => { + if (percentUsed >= 90) return "rgb(239, 68, 68)"; // Tailwind red-500 + if (percentUsed >= 75) return "rgb(245, 158, 11)"; // Tailwind amber-500 + return "rgb(16, 185, 129)"; // Tailwind emerald-500 + }; + return (
Credit Usage {roundedPercent}%
-
+
= 90 ? "bg-destructive" : percentUsed >= 75 ? "bg-amber-500" : "bg-primary" - }`} - style={{ width: `${percentUsed}%` }} + className="h-full transition-all" + style={{ + width: `${percentUsed}%`, + backgroundColor: getBarColor() + }} />
Resets Monthly
diff --git a/frontend/src/components/Explainer.tsx b/frontend/src/components/Explainer.tsx index cbb4fca33..3a34c6d20 100644 --- a/frontend/src/components/Explainer.tsx +++ b/frontend/src/components/Explainer.tsx @@ -90,9 +90,14 @@ export function InfoContent() {
- + Learn more - +
); diff --git a/frontend/src/components/Footer.tsx b/frontend/src/components/Footer.tsx index 221a9be23..11577ced4 100644 --- a/frontend/src/components/Footer.tsx +++ b/frontend/src/components/Footer.tsx @@ -3,68 +3,131 @@ import { DiscordIcon } from "./icons/DiscordIcon"; export function Footer() { return ( -
-

- Powered by{" "} - - OpenSecret - -

- -
- - - - - - - - - - - - +
+
+
+
+ Maple + Maple +

+ Private AI chat with end-to-end encryption. Your conversations stay yours. +

+ +
+ + + + + + +
+ +
+

+ © {new Date().getFullYear()} Maple AI. All rights reserved. Powered by{" "} + + OpenSecret + +

+
); diff --git a/frontend/src/components/Marketing.tsx b/frontend/src/components/Marketing.tsx index 5a0e657dc..88b7dc931 100644 --- a/frontend/src/components/Marketing.tsx +++ b/frontend/src/components/Marketing.tsx @@ -1,8 +1,9 @@ import { Link } from "@tanstack/react-router"; import { VerificationStatus } from "./VerificationStatus"; -import { MessageSquareMore } from "lucide-react"; -import { MarketingHeader } from "./MarketingHeader"; +import { ArrowRight, Check, Lock, MessageSquareMore, Shield, Sparkles } from "lucide-react"; import { Footer } from "./Footer"; +import { useQuery } from "@tanstack/react-query"; +import { getBillingService } from "@/billing/billingService"; function CTAButton({ children, @@ -14,81 +15,647 @@ function CTAButton({ primary?: boolean; }) { return ( - + {children} + {primary && ( +
+
+
+ )} ); } -export function Marketing() { +function FeatureCard({ + icon: Icon, + title, + description, + gradient = "from-[hsl(var(--purple))]/10 to-[hsl(var(--blue))]/10" +}: { + icon: React.ElementType; + title: string; + description: string; + gradient?: string; +}) { return ( -
-
- - 🎉 Now Live • Read the Announcement → - - - Encrypted. At every step. -
- Nobody can read your chats but you. - - } - /> +
+
+
-
- - - Start Chatting Securely - - Log In +

{title}

+

{description}

+
+ ); +} + +function TestimonialCard({ + quote, + author, + role, + avatar +}: { + quote: string; + author: string; + role: string; + avatar: string; +}) { + return ( +
+

“{quote}”

+
+ {author} +
+

{author}

+

{role}

+
-
-
- mask test -

Your Device

-

- All your communications are encrypted locally before being sent to our servers. -

+
+ ); +} + +function PricingTier({ + name, + price, + description, + features, + ctaText, + popular = false, + productId = "" // Add productId parameter +}: { + name: string; + price: string; + description: string; + features: string[]; + ctaText: string; + popular?: boolean; + productId?: string; // Add type for productId +}) { + const isTeamPlan = name.toLowerCase().includes("team"); + + return ( +
+ {popular && ( +
+ Most Popular +
+ )} +

{name}

+
+ {price} + {name === "Team" ? ( + /user /mo + ) : ( + price !== "Free" && ( + /mo + ) + )} +
+

{description}

+
+ {features.map((feature, index) => ( +
+ {feature !== "Included from Free" && feature !== "" && ( + + )} + {feature} +
+ ))} +
+ {isTeamPlan ? ( + // For team plans, add "Contact Us" button that opens email + + ) : // For non-team plans, redirect to signup with pricing selection + productId ? ( + // When we have a product ID, create a button that handles the navigation + + ) : ( + // Default link when no product ID is available + + {ctaText} + + )} +
+ ); +} + +export function Marketing() { + // Fetch products to get product IDs for pricing tiers + const { + data: products + // We don't need to use loading state as we provide empty string fallback + } = useQuery({ + queryKey: ["marketing-products"], + queryFn: async () => { + try { + const billingService = getBillingService(); + return await billingService.getProducts(); + } catch (error) { + console.error("Error fetching products:", error); + return []; + } + }, + retry: 1 // Only retry once for faster error feedback + }); + + // Find product IDs for each tier + const getProductId = (name: string) => { + if (!products || products.length === 0) return ""; + + const product = products.find((p) => p.name.toLowerCase() === name.toLowerCase() && p.active); + return product ? product.id : ""; + }; + + return ( +
+ {/* Hero Section */} +
+
+
+
+

+ + Private AI Chat + {" "} +
that's truly secure +

+

+ End-to-end encryption means your conversations are confidential and protected at + every step. Only you can access your data — not even we can read your chats. +

+
+
+ + + Start Secure Chat + + Log In +
+ +
+
+
+
+
+
+
+
+
+
+ Encrypted Chat +
+
+
+
+
+ AI +
+
+ How can I help you today? Your conversation is fully encrypted. +
+
+
+
+ I need to discuss some sensitive information. Is this really secure? +
+
+ U +
+
+
+
+ AI +
+
+ Yes, absolutely. Your messages are end-to-end encrypted. Even the server admins + can't read your conversations. We use secure enclaves and open-source code to + verify this. +
+
+
+
+
+ End-to-End Encrypted +
+
-
- mask test -

Secure Server

-

- Our servers can't be spied on, even by us. And we can prove it. -

- +
+ + {/* Features Section */} +
+
+
+

+ Privacy at Every Layer +

+

+ Your security is our primary concern. We've engineered Maple to ensure your data + remains yours alone, protected by cutting-edge encryption. +

+
+ +
+ + + +
-
- mask test -

AI Cloud

-

- Your chats are encrypted and sent to a GPU, providing a highly secure transmission - that's resistant to interception. -

+
+ + {/* Proof/Verification Section */} +
+
+
+
+

+ We{" "} + + Prove + {" "} + Our Security +

+

+ Unlike other services that merely claim to be secure, we provide cryptographic + proof. Our commitment to transparency means you don't have to trust us - you can + verify it yourself. +

+
+ Live Secure Enclave Verification +
+
+ +
+ + Learn more about our verification system + +
+
+
+ {/* Header */} +
+
+ Secure Server +
+
+ + {/* Main Content */} +
+
+ {/* Container for mobile view to ensure proper spacing */} +
+ {/* Phone - Mobile */} +
+
+
+
+
+
+
+
+
+
+
+
+ + {/* Vertical Connection Line - Mobile */} +
+
+
+
+ Encrypted Connection +
+
+ + {/* Server - Mobile */} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + {/* Desktop layout - hidden on mobile */} +
+ {/* Phone - Desktop */} +
+ {/* Same phone content as mobile */} +
+
+
+
+
+
+
+
+
+
+
+ + {/* Horizontal Connection Line - Desktop */} +
+
+
+
+
+ Encrypted Connection +
+
+
+ + {/* Server - Desktop */} +
+ {/* Same server content as mobile */} +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + {/* Crypto Text */} +
+
0x7B4...
+
ECDSA P-384
+
SHA-384
+
+
+
+ + {/* Status Indicator */} +
+ Secure Enclave Verified +
+
+
-
+ + + {/* Testimonials */} +
+
+
+

+ What Our Users Say +

+

+ Hear from those who've made privacy a priority with Maple AI. +
+ (Quotes are real, names are changed for privacy) +

+
+ +
+ + + +
+
+
+ + {/* Pricing Section */} +
+
+
+

+ Simple, Transparent{" "} + Pricing +

+

+ No hidden fees. Choose the plan that works for your needs. +

+
+ + {/* Free Account Callout */} +
+

+ Free account comes with 10 free chats per week +

+
+ +
+ + + +
+
+
+ + {/* CTA Section */} +
+
+
+
+

+ Ready to Chat Securely? +

+

+ Join privacy-conscious users who've made the switch to truly secure AI chat. +

+
+ + + Start Chatting Securely + + Log In +
+
+
+
+
+
); diff --git a/frontend/src/components/MarketingHeader.tsx b/frontend/src/components/MarketingHeader.tsx index 6b9289d7f..8bed7bef8 100644 --- a/frontend/src/components/MarketingHeader.tsx +++ b/frontend/src/components/MarketingHeader.tsx @@ -1,18 +1,18 @@ -interface MarketingHeaderProps { - title: string; +type MarketingHeaderProps = { + title: React.ReactNode; subtitle: React.ReactNode; className?: string; -} +}; export function MarketingHeader({ title, subtitle, className = "pt-12" }: MarketingHeaderProps) { return (
-

+

{title}

-

+

{subtitle}

diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx index f64473c14..65b6c56cc 100644 --- a/frontend/src/components/Sidebar.tsx +++ b/frontend/src/components/Sidebar.tsx @@ -108,9 +108,9 @@ export function Sidebar({ isOpen ? "block w-[280px]" : "hidden md:block md:w-[280px]" ])} > -
+
- diff --git a/frontend/src/components/SimplifiedFooter.tsx b/frontend/src/components/SimplifiedFooter.tsx new file mode 100644 index 000000000..0bd208eaf --- /dev/null +++ b/frontend/src/components/SimplifiedFooter.tsx @@ -0,0 +1,37 @@ +export function SimplifiedFooter() { + return ( +
+
+

+ © {new Date().getFullYear()} Maple AI. All rights reserved. Powered by{" "} + + OpenSecret + +

+ +
+
+ ); +} diff --git a/frontend/src/components/TopNav.tsx b/frontend/src/components/TopNav.tsx index 28601f84c..adaf93441 100644 --- a/frontend/src/components/TopNav.tsx +++ b/frontend/src/components/TopNav.tsx @@ -26,8 +26,8 @@ export function TopNav() { to={to} onClick={onClick} className={cn( - "transition-colors font-light tracking-tight text-xl text-white", - isActive ? "text-white" : "text-white/80 hover:text-white" + "transition-colors font-light tracking-tight text-lg", + isActive ? "text-[#E2E2E2]" : "text-[#E2E2E2]/70 hover:text-[#E2E2E2]" )} > {children} @@ -36,33 +36,39 @@ export function TopNav() { }; return ( -
-