fix stripe configuration

This commit is contained in:
2026-05-26 13:47:43 -04:00
parent 72609755f8
commit 3bcbdae678
35 changed files with 1189 additions and 1727 deletions

View File

@@ -26,7 +26,12 @@ const plans: Plan[] = [
price: "$9",
period: "/month",
description: "Essential identity protection for individuals",
features: ["Dark web monitoring", "Email breach alerts", "Basic scam call blocking", "Monthly reports"],
features: [
"Dark web monitoring",
"Email breach alerts",
"Basic scam call blocking",
"Monthly reports",
],
cta: "Start Free Trial",
popular: false,
},
@@ -35,7 +40,13 @@ const plans: Plan[] = [
price: "$19",
period: "/month",
description: "Advanced protection for you and your family",
features: ["Everything in Basic", "VoicePrint AI detection", "HomeTitle fraud alerts", "RemoveBrokers automation", "Family sharing (up to 5)"],
features: [
"Everything in Basic",
"VoicePrint AI detection",
"HomeTitle fraud alerts",
"RemoveBrokers automation",
"Family sharing (up to 5)",
],
cta: "Start Free Trial",
popular: true,
},
@@ -44,7 +55,14 @@ const plans: Plan[] = [
price: "$39",
period: "/month",
description: "Maximum security for the whole household",
features: ["Everything in Plus", "Unlimited family members", "Priority support 24/7", "Real-time alert correlation", "Advanced analytics dashboard", "Data broker suppression"],
features: [
"Everything in Plus",
"Unlimited family members",
"Priority support 24/7",
"Real-time alert correlation",
"Advanced analytics dashboard",
"Data broker suppression",
],
cta: "Start Free Trial",
popular: false,
},
@@ -80,30 +98,90 @@ const faqs: FAQ[] = [
const comparisonFeatures = [
{ feature: "Dark web monitoring", basic: true, plus: true, premium: true },
{ feature: "Email breach alerts", basic: true, plus: true, premium: true },
{ feature: "Basic scam call blocking", basic: true, plus: true, premium: true },
{
feature: "Basic scam call blocking",
basic: true,
plus: true,
premium: true,
},
{ feature: "Monthly reports", basic: true, plus: true, premium: true },
{ feature: "VoicePrint AI detection", basic: false, plus: true, premium: true },
{ feature: "HomeTitle fraud alerts", basic: false, plus: true, premium: true },
{ feature: "RemoveBrokers automation", basic: false, plus: true, premium: true },
{ feature: "Family sharing", basic: false, plus: "Up to 5", premium: "Unlimited" },
{ feature: "Priority support 24/7", basic: false, plus: false, premium: true },
{ feature: "Real-time alert correlation", basic: false, plus: false, premium: true },
{
feature: "VoicePrint AI detection",
basic: false,
plus: true,
premium: true,
},
{
feature: "HomeTitle fraud alerts",
basic: false,
plus: true,
premium: true,
},
{
feature: "RemoveBrokers automation",
basic: false,
plus: true,
premium: true,
},
{
feature: "Family sharing",
basic: false,
plus: "Up to 5",
premium: "Unlimited",
},
{
feature: "Priority support 24/7",
basic: false,
plus: false,
premium: true,
},
{
feature: "Real-time alert correlation",
basic: false,
plus: false,
premium: true,
},
{ feature: "Advanced analytics", basic: false, plus: false, premium: true },
{ feature: "Data broker suppression", basic: false, plus: false, premium: true },
{
feature: "Data broker suppression",
basic: false,
plus: false,
premium: true,
},
];
function CheckIcon() {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" class="flex-shrink-0">
<path d="M6.5 11.5L3 8l1.1-1.1L6.5 9.3l5.9-5.9L13.5 4.5l-7 7z" fill="var(--color-success)"/>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
class="flex-shrink-0"
>
<path
d="M6.5 11.5L3 8l1.1-1.1L6.5 9.3l5.9-5.9L13.5 4.5l-7 7z"
fill="var(--color-success)"
/>
</svg>
);
}
function XIcon() {
return (
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" class="flex-shrink-0">
<path d="M4 4l8 8M12 4l-8 8" stroke="var(--color-text-muted)" stroke-width="1.5" stroke-linecap="round"/>
<svg
width="16"
height="16"
viewBox="0 0 16 16"
fill="none"
class="flex-shrink-0"
>
<path
d="M4 4l8 8M12 4l-8 8"
stroke="var(--color-text-muted)"
stroke-width="1.5"
stroke-linecap="round"
/>
</svg>
);
}
@@ -112,33 +190,52 @@ export default function PricingPage() {
const [searchParams] = useSearchParams();
const [openFaq, setOpenFaq] = createSignal<string | null>(null);
const signupUrl = () => `/signup${searchParams.utm_source ? `?utm_source=${searchParams.utm_source}&utm_medium=${searchParams.utm_medium || ""}&utm_campaign=${searchParams.utm_campaign || ""}` : ""}`;
const signupUrl = () =>
`/signup${
searchParams.utm_source
? `?utm_source=${searchParams.utm_source}&utm_medium=${
searchParams.utm_medium || ""
}&utm_campaign=${searchParams.utm_campaign || ""}`
: ""
}`;
const planToId: Record<string, string> = {
Basic: "basic",
Plus: "plus",
Premium: "premium",
};
return (
<main>
<Title>Kordant Pricing AI-Powered Identity Protection Plans</Title>
<section class="relative py-20 md:py-28 overflow-hidden">
<div class="absolute inset-0 bg-gradient-to-b from-[var(--color-brand-primary)]/5 to-transparent" />
<div class="absolute inset-0 bg-linear-to-b from-(--color-brand-primary)/5 to-transparent" />
<PageContainer class="relative z-10">
<div class="text-center max-w-3xl mx-auto">
<Badge variant="info" class="mb-4">Simple Pricing</Badge>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-[var(--color-text-primary)] mb-6">
<Badge variant="info" class="mb-4">
Simple Pricing
</Badge>
<h1 class="text-4xl md:text-5xl lg:text-6xl font-bold text-text-primary mb-6">
Protection That Fits{" "}
<span class="text-gradient-primary">Your Budget</span>
</h1>
<p class="text-xl text-[var(--color-text-secondary)] mb-8 max-w-2xl mx-auto">
Start with a 14-day free trial. No credit card required. Cancel anytime.
<p class="text-xl text-text-secondary mb-8 max-w-2xl mx-auto">
Start with a 14-day free trial. No credit card required. Cancel
anytime.
</p>
<div class="flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm text-[var(--color-text-tertiary)]">
<div class="flex flex-wrap items-center justify-center gap-x-6 gap-y-2 text-sm text-text-tertiary">
<span class="flex items-center gap-1.5">
<CheckIcon />14-day free trial
<CheckIcon />
14-day free trial
</span>
<span class="flex items-center gap-1.5">
<CheckIcon />No credit card required
<CheckIcon />
No credit card required
</span>
<span class="flex items-center gap-1.5">
<CheckIcon />Cancel anytime
<CheckIcon />
Cancel anytime
</span>
</div>
</div>
@@ -153,7 +250,8 @@ export default function PricingPage() {
<Card
class={cn(
"relative flex flex-col",
plan.popular && "ring-2 ring-[var(--color-brand-primary)] shadow-glow-primary",
plan.popular &&
"ring-2 ring-(--color-brand-primary) shadow-glow-primary",
)}
>
<Show when={plan.popular}>
@@ -162,25 +260,36 @@ export default function PricingPage() {
</div>
</Show>
<div class="mb-6">
<h3 class="text-lg font-semibold text-[var(--color-text-primary)] mb-1">{plan.name}</h3>
<p class="text-sm text-[var(--color-text-secondary)] mb-4">{plan.description}</p>
<h3 class="text-lg font-semibold text-text-primary mb-1">
{plan.name}
</h3>
<p class="text-sm text-text-secondary mb-4">
{plan.description}
</p>
<div class="flex items-baseline gap-0.5">
<span class="text-4xl font-bold text-[var(--color-text-primary)]">{plan.price}</span>
<span class="text-sm text-[var(--color-text-tertiary)]">{plan.period}</span>
<span class="text-4xl font-bold text-text-primary">
{plan.price}
</span>
<span class="text-sm text-text-tertiary">
{plan.period}
</span>
</div>
</div>
<ul class="space-y-3 mb-8 flex-1">
<For each={plan.features}>
{(feature) => (
<li class="flex items-start gap-2 text-sm text-[var(--color-text-secondary)]">
<li class="flex items-start gap-2 text-sm text-text-secondary">
<CheckIcon />
{feature}
</li>
)}
</For>
</ul>
<A href={signupUrl()}>
<Button variant={plan.popular ? "primary" : "secondary"} class="w-full">
<A href={`/billing/checkout?plan=${planToId[plan.name]}`}>
<Button
variant={plan.popular ? "primary" : "secondary"}
class="w-full"
>
{plan.cta}
</Button>
</A>
@@ -202,25 +311,59 @@ export default function PricingPage() {
<table class="w-full">
<thead>
<tr class="border-b-2 border-[var(--color-border)]">
<th class="text-left px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">Feature</th>
<th class="text-center px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">Basic</th>
<th class="text-center px-4 py-3 text-sm font-semibold text-[var(--color-brand-primary)]">Plus</th>
<th class="text-center px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">Premium</th>
<th class="text-left px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">
Feature
</th>
<th class="text-center px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">
Basic
</th>
<th class="text-center px-4 py-3 text-sm font-semibold text-[var(--color-brand-primary)]">
Plus
</th>
<th class="text-center px-4 py-3 text-sm font-medium text-[var(--color-text-secondary)]">
Premium
</th>
</tr>
</thead>
<tbody>
<For each={comparisonFeatures}>
{(row) => (
<tr class="border-b border-[var(--color-border)]">
<td class="px-4 py-3 text-sm text-[var(--color-text-primary)]">{row.feature}</td>
<td class="text-center px-4 py-3">
{row.basic === true ? <CheckIcon /> : row.basic === false ? <XIcon /> : <span class="text-xs text-[var(--color-text-secondary)]">{row.basic}</span>}
<td class="px-4 py-3 text-sm text-[var(--color-text-primary)]">
{row.feature}
</td>
<td class="text-center px-4 py-3">
{row.plus === true ? <CheckIcon /> : row.plus === false ? <XIcon /> : <span class="text-xs text-[var(--color-text-secondary)]">{row.plus}</span>}
{row.basic === true ? (
<CheckIcon />
) : row.basic === false ? (
<XIcon />
) : (
<span class="text-xs text-[var(--color-text-secondary)]">
{row.basic}
</span>
)}
</td>
<td class="text-center px-4 py-3">
{row.premium === true ? <CheckIcon /> : row.premium === false ? <XIcon /> : <span class="text-xs text-[var(--color-text-secondary)]">{row.premium}</span>}
{row.plus === true ? (
<CheckIcon />
) : row.plus === false ? (
<XIcon />
) : (
<span class="text-xs text-[var(--color-text-secondary)]">
{row.plus}
</span>
)}
</td>
<td class="text-center px-4 py-3">
{row.premium === true ? (
<CheckIcon />
) : row.premium === false ? (
<XIcon />
) : (
<span class="text-xs text-[var(--color-text-secondary)]">
{row.premium}
</span>
)}
</td>
</tr>
)}
@@ -244,7 +387,7 @@ export default function PricingPage() {
{(faq) => {
const isOpen = () => openFaq() === faq.q;
return (
<div class="border border-[var(--color-border)] rounded-xl overflow-hidden">
<div class="border border-(--color-border) rounded-xl overflow-hidden">
<button
type="button"
class="w-full flex items-center justify-between px-5 py-4 text-left text-sm font-medium text-[var(--color-text-primary)] hover:bg-[var(--color-bg-secondary)] transition-colors"
@@ -256,9 +399,18 @@ export default function PricingPage() {
height="16"
viewBox="0 0 16 16"
fill="none"
class={cn("transition-transform duration-200", isOpen() && "rotate-180")}
class={cn(
"transition-transform duration-200",
isOpen() && "rotate-180",
)}
>
<path d="M4 6l4 4 4-4" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
<path
d="M4 6l4 4 4-4"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
</button>
<Show when={isOpen()}>
@@ -275,17 +427,22 @@ export default function PricingPage() {
</PageContainer>
</section>
<section class="py-16 bg-[var(--color-brand-primary)]">
<section class="py-16 bg-(--color-brand-primary)">
<PageContainer>
<div class="text-center">
<h2 class="text-3xl md:text-4xl font-bold text-white mb-4">
Ready to protect your identity?
</h2>
<p class="text-lg text-white/80 mb-8 max-w-2xl mx-auto">
Join 50,000+ users who trust Kordant for AI-powered identity protection.
Join 50,000+ users who trust Kordant for AI-powered identity
protection.
</p>
<A href={signupUrl()}>
<Button variant="primary" size="lg" class="bg-white text-[var(--color-brand-primary)] hover:bg-white/90 shadow-lg">
<Button
variant="primary"
size="lg"
class="bg-white text-[var(--color-brand-primary)] hover:bg-white/90 shadow-lg"
>
Get Started Free
</Button>
</A>