Skip to content

Commit 1e8dba9

Browse files
author
iexitdev
committed
Add Polar checkout flow to site
1 parent 4b77704 commit 1e8dba9

4 files changed

Lines changed: 255 additions & 51 deletions

File tree

apps/site/src/components/Footer.astro

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
---
22
import { ChevronsUpDown } from "lucide-astro";
33
4+
const { homeHrefPrefix = "" } = Astro.props;
5+
const hrefFor = (href: string) =>
6+
href.startsWith("#") ? `${homeHrefPrefix}${href}` : href;
7+
48
const footerGroups = [
59
{
610
title: "Product",
@@ -86,7 +90,7 @@ const footerGroups = [
8690
{group.links.map((link) => (
8791
<li>
8892
<a
89-
href={link.href}
93+
href={hrefFor(link.href)}
9094
class="text-sm font-medium text-white/42 transition-colors hover:text-white [html[data-theme='light']_&]:text-black/42 [html[data-theme='light']_&]:hover:text-black"
9195
>
9296
{link.label}

apps/site/src/components/Header.astro

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
---
22
import { Menu, Moon, X } from "lucide-astro";
33
4+
const { homeHrefPrefix = "" } = Astro.props;
5+
const hrefFor = (href: string) =>
6+
href.startsWith("#") ? `${homeHrefPrefix}${href}` : href;
7+
48
const navigationLinks = [
59
{
610
href: "#charts",
@@ -27,7 +31,7 @@ const navigationLinks = [
2731
<div
2832
class="mx-auto flex h-16 max-w-[1320px] items-center justify-between gap-4 px-6 sm:px-8 md:px-10 lg:px-12 xl:px-16"
2933
>
30-
<a href="#hero" class="flex min-w-0 items-center gap-3">
34+
<a href={hrefFor("#hero")} class="flex min-w-0 items-center gap-3">
3135
<img
3236
src="/images/logo.svg"
3337
alt=""
@@ -49,7 +53,7 @@ const navigationLinks = [
4953
{
5054
navigationLinks.map((link) => (
5155
<a
52-
href={link.href}
56+
href={hrefFor(link.href)}
5357
class="rounded-lg px-3 py-2 text-sm font-medium text-white/65 transition-colors hover:text-white [html[data-theme='light']_&]:text-black/60 [html[data-theme='light']_&]:hover:text-black"
5458
>
5559
{link.label}
@@ -70,7 +74,7 @@ const navigationLinks = [
7074
class="-mr-1 hidden bg-transparent [color-scheme:light] sm:block"
7175
></iframe>
7276
<a
73-
href="#pricing"
77+
href={hrefFor("#pricing")}
7478
class="inline-flex h-8 items-center rounded-full bg-white/95 px-3 text-[13px] font-semibold tracking-[-0.01em] text-black shadow-[0_8px_22px_rgba(255,255,255,0.16)] ring-1 ring-white/25 transition-all hover:-translate-y-px hover:bg-white hover:shadow-[0_10px_28px_rgba(255,255,255,0.22)] focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-white/45 active:translate-y-0 [html[data-theme='light']_&]:bg-black [html[data-theme='light']_&]:text-white [html[data-theme='light']_&]:shadow-[0_8px_22px_rgba(0,0,0,0.14)] [html[data-theme='light']_&]:ring-black/10 [html[data-theme='light']_&]:hover:bg-black/90 [html[data-theme='light']_&]:hover:shadow-[0_10px_28px_rgba(0,0,0,0.2)] [html[data-theme='light']_&]:focus-visible:outline-black/40"
7579
>
7680
Get pro
@@ -114,7 +118,7 @@ const navigationLinks = [
114118
{
115119
navigationLinks.map((link) => (
116120
<a
117-
href={link.href}
121+
href={hrefFor(link.href)}
118122
class="py-3 text-sm font-medium text-white/70 transition-colors hover:text-white [html[data-theme='light']_&]:text-black/65 [html[data-theme='light']_&]:hover:text-black"
119123
data-mobile-menu-link
120124
>

apps/site/src/components/Pricing.astro

Lines changed: 11 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,20 @@
11
---
22
import { Building2, Check, Gift, Rocket } from "lucide-astro";
33
4+
const polarCheckoutUrl =
5+
"https://buy.polar.sh/polar_cl_Lo2DzeNXDXbFkuvPr1ZDVREe9wXs9zsz3FvJF2ZjW9Z";
6+
47
const proTiers = [
58
{
69
key: "solo",
10+
productId: "f522fac9-b6d5-4e60-8c6f-35c1c10827c9",
711
buttonLabel: "1 dev",
812
name: "Solo",
913
price: "$149",
1014
cadence: "/ year",
1115
description: "For solo devs and independent apps.",
1216
cta: "Get Solo",
13-
href: "mailto:sales@chartkit.io?subject=Chart%20Kit%20Pro%20Solo%20license",
17+
href: `${polarCheckoutUrl}?product_id=f522fac9-b6d5-4e60-8c6f-35c1c10827c9`,
1418
features: [
1519
"1 developer",
1620
"1 production app",
@@ -20,13 +24,14 @@ const proTiers = [
2024
},
2125
{
2226
key: "startup",
27+
productId: "f2a31f7f-5719-4103-8406-3caad5d14843",
2328
buttonLabel: "2-3 devs",
2429
name: "Startup",
2530
price: "$399",
2631
cadence: "/ year",
2732
description: "For small teams shipping one app.",
2833
cta: "Get Startup",
29-
href: "mailto:sales@chartkit.io?subject=Chart%20Kit%20Pro%20Startup%20license",
34+
href: `${polarCheckoutUrl}?product_id=f2a31f7f-5719-4103-8406-3caad5d14843`,
3035
features: [
3136
"Up to 3 developers",
3237
"1 production app",
@@ -36,13 +41,14 @@ const proTiers = [
3641
},
3742
{
3843
key: "business",
44+
productId: "54c32948-3865-400b-991f-f14ffd0692fb",
3945
buttonLabel: "4-6 devs",
4046
name: "Business",
4147
price: "$1,499",
4248
cadence: "/ year",
4349
description: "For growing teams and multiple apps.",
4450
cta: "Get Business",
45-
href: "mailto:sales@chartkit.io?subject=Chart%20Kit%20Pro%20Business%20license",
51+
href: `${polarCheckoutUrl}?product_id=54c32948-3865-400b-991f-f14ffd0692fb`,
4652
features: [
4753
"Up to 6 developers",
4854
"Up to 2 production apps",
@@ -170,7 +176,7 @@ const proTiersByKey = Object.fromEntries(
170176
<span
171177
class="inline-flex items-center rounded-full bg-white/[0.075] px-3 py-1.5 text-[11px] font-semibold text-white/78 transition-colors duration-300 [html[data-theme='light']_&]:bg-black/[0.055] [html[data-theme='light']_&]:text-black/70"
172178
>
173-
Coming soon
179+
Annual
174180
</span>
175181
</div>
176182

@@ -250,7 +256,6 @@ const proTiersByKey = Object.fromEntries(
250256
<a
251257
href={defaultProTier.href}
252258
data-pro-cta
253-
data-pro-coming-soon
254259
class="inline-flex h-10 items-center justify-center rounded-full bg-white px-5 text-sm font-semibold text-black transition-colors hover:bg-white/88 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-white/45 [html[data-theme='light']_&]:bg-black [html[data-theme='light']_&]:text-white [html[data-theme='light']_&]:hover:bg-black/82 [html[data-theme='light']_&]:focus-visible:outline-black/40"
255260
>
256261
{defaultProTier.cta}
@@ -305,7 +310,6 @@ const proTiersByKey = Object.fromEntries(
305310

306311
<a
307312
href="mailto:sales@chartkit.io?subject=Chart%20Kit%20Pro%20Enterprise"
308-
data-pro-coming-soon
309313
class="inline-flex h-10 items-center justify-center rounded-full border border-white/15 px-5 text-sm font-semibold text-white/78 transition-colors hover:border-white/28 hover:text-white focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-4 focus-visible:outline-white/45 [html[data-theme='light']_&]:border-black/15 [html[data-theme='light']_&]:text-black/70 [html[data-theme='light']_&]:hover:border-black/28 [html[data-theme='light']_&]:hover:text-black [html[data-theme='light']_&]:focus-visible:outline-black/40"
310314
>
311315
Talk to sales
@@ -324,15 +328,6 @@ const proTiersByKey = Object.fromEntries(
324328
</a>
325329
</p>
326330
</div>
327-
<div
328-
data-pro-toast
329-
data-visible="false"
330-
role="status"
331-
aria-live="polite"
332-
class="pointer-events-none fixed bottom-5 left-1/2 z-[80] -translate-x-1/2 translate-y-2 rounded-full border border-white/12 bg-white/92 px-4 py-2 text-sm font-medium whitespace-nowrap text-black opacity-0 shadow-[0_18px_60px_rgba(0,0,0,0.28)] backdrop-blur-xl transition duration-200 data-[visible=true]:translate-y-0 data-[visible=true]:opacity-100 [html[data-theme='light']_&]:border-black/12 [html[data-theme='light']_&]:bg-black/90 [html[data-theme='light']_&]:text-white"
333-
>
334-
Pro version is coming soon
335-
</div>
336331
</section>
337332

338333
<script
@@ -351,6 +346,7 @@ const proTiersByKey = Object.fromEntries(
351346
href: string;
352347
name: string;
353348
price: string;
349+
productId: string;
354350
};
355351

356352
const hydrateProPricing = () => {
@@ -377,8 +373,6 @@ const proTiersByKey = Object.fromEntries(
377373
const indicator = root.querySelector<HTMLElement>(
378374
"[data-pro-tier-indicator]"
379375
);
380-
const toast = document.querySelector<HTMLElement>("[data-pro-toast]");
381-
let toastTimer: number | undefined;
382376

383377
const renderFeature = (feature: string) => `
384378
<li class="flex items-center gap-3 text-sm font-medium text-white/62 transition-colors duration-300 [html[data-theme='light']_&]:text-black/62">
@@ -426,40 +420,11 @@ const proTiersByKey = Object.fromEntries(
426420
}
427421
};
428422

429-
const showComingSoonToast = () => {
430-
if (!toast) {
431-
return;
432-
}
433-
434-
if (toastTimer) {
435-
window.clearTimeout(toastTimer);
436-
}
437-
438-
toast.dataset.visible = "true";
439-
toastTimer = window.setTimeout(() => {
440-
toast.dataset.visible = "false";
441-
}, 2200);
442-
};
443-
444423
buttons.forEach((button) => {
445424
button.addEventListener("click", () =>
446425
selectTier(button.dataset.proTier)
447426
);
448427
});
449-
450-
document
451-
.querySelectorAll<HTMLAnchorElement>("[data-pro-coming-soon]")
452-
.forEach((link) => {
453-
if (link.dataset.proComingSoonBound === "true") {
454-
return;
455-
}
456-
457-
link.dataset.proComingSoonBound = "true";
458-
link.addEventListener("click", (event) => {
459-
event.preventDefault();
460-
showComingSoonToast();
461-
});
462-
});
463428
};
464429

465430
if (document.readyState === "loading") {

0 commit comments

Comments
 (0)