1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
|
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 (
<div className="text-center">
<h1 className="text-4xl font-bold sm:text-6xl">
Simple{" "}
<span className="bg-gradient-to-r from-purple-600 to-red-600 bg-clip-text text-transparent">
Pricing
</span>
</h1>
<p className="mt-4 text-lg text-gray-600">
Choose the plan that works best for you
</p>
</div>
);
}
function PricingCards() {
return (
<div className="mx-auto mt-16 grid max-w-6xl grid-cols-1 gap-8 px-6 md:grid-cols-3">
{pricingTiers.map((tier) => (
<div
key={tier.name}
className={cn(
"relative rounded-2xl border bg-white p-8 shadow-sm",
tier.popular && "border-purple-500 shadow-lg",
)}
>
<div className="text-center">
<h3 className="text-xl font-semibold">{tier.name}</h3>
<div className="mt-4 flex items-baseline justify-center">
<span className="text-4xl font-bold">{tier.price}</span>
{tier.period && (
<span className="ml-1 text-gray-500">/{tier.period}</span>
)}
</div>
<p className="mt-2 text-gray-600">{tier.description}</p>
</div>
<ul className="mt-8 space-y-3">
{tier.features.map((feature) => (
<li key={feature} className="flex items-center">
<Check className="h-5 w-5 text-green-500" />
<span className="ml-3 text-gray-700">{feature}</span>
</li>
))}
</ul>
<div className="mt-8">
{tier.isGitHub ? (
<a
href={GITHUB_LINK}
target="_blank"
className={cn(
"flex w-full items-center justify-center gap-2",
buttonVariants({ variant: tier.buttonVariant, size: "lg" }),
)}
rel="noreferrer"
>
<ExternalLink className="h-4 w-4" />
{tier.buttonText}
</a>
) : (
<a
href={WAITLIST_LINK}
target="_blank"
className={cn(
"flex w-full items-center justify-center",
buttonVariants({ variant: tier.buttonVariant, size: "lg" }),
)}
rel="noreferrer"
>
{tier.buttonText}
</a>
)}
</div>
</div>
))}
</div>
);
}
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.",
},
{
question: "How should I contact you if I have any questions?",
answer: "You can reach us at support@karakeep.app",
},
];
return (
<div className="mx-auto mt-24 max-w-4xl px-6">
<h2 className="text-center text-3xl font-bold">
Frequently Asked Questions
</h2>
<div className="mt-12 grid gap-8 md:grid-cols-2">
{faqs.map((faq) => (
<div key={faq.question}>
<h3 className="text-lg font-semibold">{faq.question}</h3>
<p className="mt-2 text-gray-600">{faq.answer}</p>
</div>
))}
</div>
</div>
);
}
function Footer() {
const currentYear = new Date().getFullYear();
return (
<div className="mt-24 flex items-center justify-between bg-gray-100 px-10 py-6 text-sm">
<div>
© 2024-{currentYear}{" "}
<a href="https://localhostlabs.co.uk" target="_blank" rel="noreferrer">
Localhost Labs Ltd
</a>
</div>
<div className="flex items-center gap-6">
<a
href={DOCS_LINK}
target="_blank"
className="flex justify-center gap-2 text-center"
rel="noreferrer"
>
Docs
</a>
<a
href={GITHUB_LINK}
target="_blank"
className="flex justify-center gap-2 text-center"
rel="noreferrer"
>
GitHub
</a>
</div>
</div>
);
}
export default function Pricing() {
return (
<div className="min-h-screen bg-gray-50">
<div className="container mx-auto">
<NavBar />
<div className="py-16">
<PricingHeader />
<PricingCards />
<FAQ />
</div>
</div>
<Footer />
</div>
);
}
|