kofi-stack-template-generator 2.1.51 → 2.1.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +6 -6
- package/dist/index.js +1906 -146
- package/package.json +2 -2
- package/src/generator.ts +9 -0
- package/src/templates.generated.ts +51 -5
- package/templates/marketing/astro/astro.config.ts.hbs +12 -0
- package/templates/marketing/astro/package.json.hbs +31 -0
- package/templates/marketing/astro/postcss.config.mjs.hbs +5 -0
- package/templates/marketing/astro/public/favicon.svg +4 -0
- package/templates/marketing/astro/public/media/hero-bg.png +1 -0
- package/templates/marketing/astro/src/components/Footer.astro +167 -0
- package/templates/marketing/astro/src/components/Header.astro +378 -0
- package/templates/marketing/astro/src/components/Logo.astro +30 -0
- package/templates/marketing/astro/src/components/ThemeSelector.astro +64 -0
- package/templates/marketing/astro/src/components/blocks/BentoFeatures.astro +209 -0
- package/templates/marketing/astro/src/components/blocks/FeatureShowcase.astro +102 -0
- package/templates/marketing/astro/src/components/blocks/FinalCTA.astro +82 -0
- package/templates/marketing/astro/src/components/blocks/IndustryTabs.astro +177 -0
- package/templates/marketing/astro/src/components/blocks/LogoBanner.astro +95 -0
- package/templates/marketing/astro/src/components/blocks/PricingTable.astro +176 -0
- package/templates/marketing/astro/src/components/blocks/ProofBanner.astro +56 -0
- package/templates/marketing/astro/src/components/blocks/TestimonialsGrid.astro +106 -0
- package/templates/marketing/astro/src/components/blocks/TrustColumns.astro +88 -0
- package/templates/marketing/astro/src/components/heros/AnimatedMockup.astro +711 -0
- package/templates/marketing/astro/src/components/heros/ProductShowcaseHero.astro +111 -0
- package/templates/marketing/astro/src/layouts/Layout.astro +37 -0
- package/templates/marketing/astro/src/lib/utils.ts +6 -0
- package/templates/marketing/astro/src/pages/index.astro +163 -0
- package/templates/marketing/astro/src/styles/globals.css.hbs +353 -0
- package/templates/marketing/astro/tsconfig.json.hbs +11 -0
- package/templates/marketing/nextjs/package.json.hbs +6 -1
- package/templates/marketing/nextjs/src/app/layout.tsx.hbs +19 -5
- package/templates/marketing/nextjs/src/app/page.tsx.hbs +160 -164
- package/templates/marketing/nextjs/src/components/Footer/index.tsx +188 -0
- package/templates/marketing/nextjs/src/components/Header/MegaMenu.tsx +117 -0
- package/templates/marketing/nextjs/src/components/Header/MobileMenu.tsx +178 -0
- package/templates/marketing/nextjs/src/components/Header/index.tsx +172 -0
- package/templates/marketing/nextjs/src/components/Logo.tsx +46 -0
- package/templates/marketing/nextjs/src/components/ThemeProvider.tsx +8 -0
- package/templates/marketing/nextjs/src/components/ThemeSelector.tsx +69 -0
- package/templates/marketing/nextjs/src/components/blocks/BentoFeatures.tsx +249 -0
- package/templates/marketing/nextjs/src/components/blocks/FeatureShowcase.tsx +110 -0
- package/templates/marketing/nextjs/src/components/blocks/FinalCTA.tsx +91 -0
- package/templates/marketing/nextjs/src/components/blocks/IndustryTabs.tsx +137 -0
- package/templates/marketing/nextjs/src/components/blocks/LogoBanner.tsx +80 -0
- package/templates/marketing/nextjs/src/components/blocks/PricingTable.tsx +210 -0
- package/templates/marketing/nextjs/src/components/blocks/ProofBanner.tsx +72 -0
- package/templates/marketing/nextjs/src/components/blocks/TestimonialsGrid.tsx +119 -0
- package/templates/marketing/nextjs/src/components/blocks/TrustColumns.tsx +110 -0
- package/templates/marketing/nextjs/src/components/blocks/index.ts +9 -0
- package/templates/marketing/nextjs/src/components/heros/AnimatedMockup.tsx +242 -0
- package/templates/marketing/nextjs/src/components/heros/ProductShowcaseHero.tsx +84 -0
- package/templates/marketing/nextjs/src/components/heros/index.ts +2 -0
- package/templates/marketing/nextjs/src/lib/utils.ts +6 -0
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Logo {
|
|
3
|
+
name: string
|
|
4
|
+
initials?: string
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface Props {
|
|
8
|
+
heading?: string
|
|
9
|
+
logos?: Logo[]
|
|
10
|
+
style?: "scroll" | "grid"
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const defaultLogos: Logo[] = [
|
|
14
|
+
{ name: "TechFlow Inc", initials: "TF" },
|
|
15
|
+
{ name: "Acme Corp", initials: "AC" },
|
|
16
|
+
{ name: "Evergreen HQ", initials: "EH" },
|
|
17
|
+
{ name: "Atlas Network", initials: "AN" },
|
|
18
|
+
{ name: "Beacon Digital", initials: "BD" },
|
|
19
|
+
{ name: "Cascade Systems", initials: "CS" },
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
const {
|
|
23
|
+
heading = "Trusted by fast-growing companies everywhere",
|
|
24
|
+
logos = defaultLogos,
|
|
25
|
+
style = "scroll",
|
|
26
|
+
} = Astro.props
|
|
27
|
+
|
|
28
|
+
const displayLogos = logos.length > 0 ? logos : defaultLogos
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
<section class="py-12 md:py-16 border-y border-border/50">
|
|
32
|
+
<div class="container mx-auto px-4">
|
|
33
|
+
{heading && (
|
|
34
|
+
<p class="text-center text-sm text-muted-foreground mb-8 uppercase tracking-wider">
|
|
35
|
+
{heading}
|
|
36
|
+
</p>
|
|
37
|
+
)}
|
|
38
|
+
|
|
39
|
+
{style === "scroll" ? (
|
|
40
|
+
<div class="logo-scroll-container">
|
|
41
|
+
<div class="logo-scroll-track">
|
|
42
|
+
{[...displayLogos, ...displayLogos].map((logo, index) => (
|
|
43
|
+
<div class="logo-item flex items-center justify-center px-6 md:px-8 grayscale hover:grayscale-0 transition-all duration-300">
|
|
44
|
+
<div class="flex items-center gap-2">
|
|
45
|
+
<span class="w-8 h-8 rounded bg-muted flex items-center justify-center text-xs font-bold text-foreground">
|
|
46
|
+
{logo.initials || logo.name.slice(0, 2).toUpperCase()}
|
|
47
|
+
</span>
|
|
48
|
+
<span class="text-sm font-medium text-muted-foreground hidden md:block">
|
|
49
|
+
{logo.name}
|
|
50
|
+
</span>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
))}
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
) : (
|
|
57
|
+
<div class="grid grid-cols-3 md:grid-cols-6 gap-8 items-center justify-items-center">
|
|
58
|
+
{displayLogos.map((logo) => (
|
|
59
|
+
<div class="logo-item flex items-center justify-center px-6 md:px-8 grayscale hover:grayscale-0 transition-all duration-300">
|
|
60
|
+
<div class="flex items-center gap-2">
|
|
61
|
+
<span class="w-8 h-8 rounded bg-muted flex items-center justify-center text-xs font-bold text-foreground">
|
|
62
|
+
{logo.initials || logo.name.slice(0, 2).toUpperCase()}
|
|
63
|
+
</span>
|
|
64
|
+
<span class="text-sm font-medium text-muted-foreground hidden md:block">
|
|
65
|
+
{logo.name}
|
|
66
|
+
</span>
|
|
67
|
+
</div>
|
|
68
|
+
</div>
|
|
69
|
+
))}
|
|
70
|
+
</div>
|
|
71
|
+
)}
|
|
72
|
+
</div>
|
|
73
|
+
</section>
|
|
74
|
+
|
|
75
|
+
<style>
|
|
76
|
+
.logo-scroll-container {
|
|
77
|
+
overflow: hidden;
|
|
78
|
+
mask-image: linear-gradient(to right, transparent, black 10%, black 90%, transparent);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.logo-scroll-track {
|
|
82
|
+
display: flex;
|
|
83
|
+
animation: scroll 30s linear infinite;
|
|
84
|
+
width: max-content;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@keyframes scroll {
|
|
88
|
+
0% { transform: translateX(0); }
|
|
89
|
+
100% { transform: translateX(-50%); }
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.logo-scroll-container:hover .logo-scroll-track {
|
|
93
|
+
animation-play-state: paused;
|
|
94
|
+
}
|
|
95
|
+
</style>
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Check, X } from "lucide-astro"
|
|
3
|
+
|
|
4
|
+
interface PricingFeature {
|
|
5
|
+
feature: string
|
|
6
|
+
included: boolean
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface PricingPlan {
|
|
10
|
+
name: string
|
|
11
|
+
price: string
|
|
12
|
+
description: string
|
|
13
|
+
featured?: boolean
|
|
14
|
+
features: PricingFeature[]
|
|
15
|
+
link: {
|
|
16
|
+
label: string
|
|
17
|
+
href: string
|
|
18
|
+
variant: "default" | "outline"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface Props {
|
|
23
|
+
heading?: string
|
|
24
|
+
subheading?: string
|
|
25
|
+
plans?: PricingPlan[]
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const defaultPlans: PricingPlan[] = [
|
|
29
|
+
{
|
|
30
|
+
name: "Free",
|
|
31
|
+
price: "$0/mo",
|
|
32
|
+
description: "Perfect for trying SaaSify.",
|
|
33
|
+
features: [
|
|
34
|
+
{ feature: "Up to 3 users", included: true },
|
|
35
|
+
{ feature: "Basic features", included: true },
|
|
36
|
+
{ feature: "Community support", included: true },
|
|
37
|
+
],
|
|
38
|
+
link: { label: "Get started free", href: "/sign-up", variant: "outline" },
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
name: "Pro",
|
|
42
|
+
price: "$29/mo",
|
|
43
|
+
description: "For small teams getting started.",
|
|
44
|
+
featured: true,
|
|
45
|
+
features: [
|
|
46
|
+
{ feature: "Up to 10 users", included: true },
|
|
47
|
+
{ feature: "Advanced features", included: true },
|
|
48
|
+
{ feature: "Integrations", included: true },
|
|
49
|
+
{ feature: "Priority support", included: true },
|
|
50
|
+
],
|
|
51
|
+
link: { label: "Get Pro", href: "/sign-up", variant: "default" },
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
name: "Business",
|
|
55
|
+
price: "$99/mo",
|
|
56
|
+
description: "For teams ready to scale.",
|
|
57
|
+
features: [
|
|
58
|
+
{ feature: "Unlimited users", included: true },
|
|
59
|
+
{ feature: "All features", included: true },
|
|
60
|
+
{ feature: "API access", included: true },
|
|
61
|
+
{ feature: "Dedicated support", included: true },
|
|
62
|
+
],
|
|
63
|
+
link: { label: "Get Business", href: "/sign-up", variant: "outline" },
|
|
64
|
+
},
|
|
65
|
+
]
|
|
66
|
+
|
|
67
|
+
const {
|
|
68
|
+
heading = "Simple, transparent pricing",
|
|
69
|
+
subheading = "Start free, upgrade as your team grows. No hidden fees.",
|
|
70
|
+
plans = defaultPlans,
|
|
71
|
+
} = Astro.props
|
|
72
|
+
|
|
73
|
+
const displayPlans = plans.length > 0 ? plans : defaultPlans
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
<section class="py-16 md:py-24">
|
|
77
|
+
<div class="container mx-auto px-4">
|
|
78
|
+
<!-- Header -->
|
|
79
|
+
{(heading || subheading) && (
|
|
80
|
+
<div class="text-center mb-12 md:mb-16 max-w-3xl mx-auto">
|
|
81
|
+
{heading && (
|
|
82
|
+
<h2 class="text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight mb-4">
|
|
83
|
+
{heading}
|
|
84
|
+
</h2>
|
|
85
|
+
)}
|
|
86
|
+
{subheading && (
|
|
87
|
+
<p class="text-lg md:text-xl text-muted-foreground">
|
|
88
|
+
{subheading}
|
|
89
|
+
</p>
|
|
90
|
+
)}
|
|
91
|
+
</div>
|
|
92
|
+
)}
|
|
93
|
+
|
|
94
|
+
<!-- Pricing Cards -->
|
|
95
|
+
<div class="grid md:grid-cols-3 gap-6 lg:gap-8 max-w-5xl mx-auto">
|
|
96
|
+
{displayPlans.map((plan) => (
|
|
97
|
+
<div
|
|
98
|
+
class:list={[
|
|
99
|
+
"relative rounded-2xl p-6 md:p-8 flex flex-col",
|
|
100
|
+
plan.featured
|
|
101
|
+
? "bg-primary text-primary-foreground border-2 border-primary"
|
|
102
|
+
: "bg-card border border-border"
|
|
103
|
+
]}
|
|
104
|
+
>
|
|
105
|
+
{plan.featured && (
|
|
106
|
+
<span class="absolute -top-3 left-1/2 -translate-x-1/2 px-3 py-1 text-xs font-medium rounded-full bg-background text-foreground">
|
|
107
|
+
Most Popular
|
|
108
|
+
</span>
|
|
109
|
+
)}
|
|
110
|
+
|
|
111
|
+
<!-- Plan header -->
|
|
112
|
+
<div class="mb-6">
|
|
113
|
+
<h3 class:list={["text-lg font-semibold mb-2", plan.featured ? "text-primary-foreground" : "text-foreground"]}>
|
|
114
|
+
{plan.name}
|
|
115
|
+
</h3>
|
|
116
|
+
<div class:list={["text-4xl font-bold mb-2", plan.featured ? "text-primary-foreground" : "text-foreground"]}>
|
|
117
|
+
{plan.price}
|
|
118
|
+
</div>
|
|
119
|
+
<p class:list={["text-sm", plan.featured ? "text-primary-foreground/80" : "text-muted-foreground"]}>
|
|
120
|
+
{plan.description}
|
|
121
|
+
</p>
|
|
122
|
+
</div>
|
|
123
|
+
|
|
124
|
+
<!-- Features -->
|
|
125
|
+
<ul class="space-y-3 mb-8 flex-1">
|
|
126
|
+
{plan.features.map((feature) => (
|
|
127
|
+
<li class="flex items-center gap-3">
|
|
128
|
+
{feature.included ? (
|
|
129
|
+
<Check class:list={["h-4 w-4", plan.featured ? "text-primary-foreground" : "text-primary"]} />
|
|
130
|
+
) : (
|
|
131
|
+
<X class:list={["h-4 w-4", plan.featured ? "text-primary-foreground/50" : "text-muted-foreground"]} />
|
|
132
|
+
)}
|
|
133
|
+
<span
|
|
134
|
+
class:list={[
|
|
135
|
+
"text-sm",
|
|
136
|
+
plan.featured
|
|
137
|
+
? feature.included ? "text-primary-foreground" : "text-primary-foreground/50"
|
|
138
|
+
: feature.included ? "text-foreground" : "text-muted-foreground"
|
|
139
|
+
]}
|
|
140
|
+
>
|
|
141
|
+
{feature.feature}
|
|
142
|
+
</span>
|
|
143
|
+
</li>
|
|
144
|
+
))}
|
|
145
|
+
</ul>
|
|
146
|
+
|
|
147
|
+
<!-- CTA -->
|
|
148
|
+
<a
|
|
149
|
+
href={plan.link.href}
|
|
150
|
+
class:list={[
|
|
151
|
+
"w-full inline-flex items-center justify-center px-6 py-3 text-sm font-medium rounded-md transition-colors",
|
|
152
|
+
plan.featured
|
|
153
|
+
? "bg-background text-foreground hover:bg-background/90"
|
|
154
|
+
: plan.link.variant === "default"
|
|
155
|
+
? "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
156
|
+
: "border border-border bg-background hover:bg-muted"
|
|
157
|
+
]}
|
|
158
|
+
>
|
|
159
|
+
{plan.link.label}
|
|
160
|
+
</a>
|
|
161
|
+
</div>
|
|
162
|
+
))}
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<!-- View all link -->
|
|
166
|
+
<div class="text-center mt-8">
|
|
167
|
+
<a
|
|
168
|
+
href="/pricing"
|
|
169
|
+
class="inline-flex items-center gap-2 text-sm font-medium text-primary hover:underline"
|
|
170
|
+
>
|
|
171
|
+
View full comparison
|
|
172
|
+
<span aria-hidden="true">→</span>
|
|
173
|
+
</a>
|
|
174
|
+
</div>
|
|
175
|
+
</div>
|
|
176
|
+
</section>
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface ProofBannerLink {
|
|
3
|
+
label: string
|
|
4
|
+
href: string
|
|
5
|
+
variant: "default" | "outline"
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
headline?: string
|
|
10
|
+
subtext?: string
|
|
11
|
+
links?: ProofBannerLink[]
|
|
12
|
+
style?: "centered" | "left"
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const {
|
|
16
|
+
headline = "Transform how your team works, collaborates, and grows",
|
|
17
|
+
subtext = "Every interaction feeds into a powerful platform that powers personalized experiences, seamless collaboration, and intelligent automation across every touchpoint.",
|
|
18
|
+
links = [
|
|
19
|
+
{ label: "Start free trial", href: "/sign-up", variant: "default" },
|
|
20
|
+
{ label: "Book a demo", href: "/contact", variant: "outline" },
|
|
21
|
+
],
|
|
22
|
+
style = "centered",
|
|
23
|
+
} = Astro.props
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
<section class="py-16 md:py-24">
|
|
27
|
+
<div class="container mx-auto px-4">
|
|
28
|
+
<div class:list={["max-w-4xl", style === "centered" ? "mx-auto text-center" : ""]}>
|
|
29
|
+
<h2 class="text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight mb-6">
|
|
30
|
+
{headline}
|
|
31
|
+
</h2>
|
|
32
|
+
{subtext && (
|
|
33
|
+
<p class="text-lg md:text-xl text-muted-foreground mb-8 max-w-3xl mx-auto">
|
|
34
|
+
{subtext}
|
|
35
|
+
</p>
|
|
36
|
+
)}
|
|
37
|
+
{links && links.length > 0 && (
|
|
38
|
+
<div class:list={["flex flex-wrap gap-4", style === "centered" ? "justify-center" : ""]}>
|
|
39
|
+
{links.map((link) => (
|
|
40
|
+
<a
|
|
41
|
+
href={link.href}
|
|
42
|
+
class:list={[
|
|
43
|
+
"inline-flex items-center justify-center px-6 py-3 text-sm font-medium rounded-md transition-colors",
|
|
44
|
+
link.variant === "default"
|
|
45
|
+
? "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
46
|
+
: "border border-border bg-background hover:bg-muted"
|
|
47
|
+
]}
|
|
48
|
+
>
|
|
49
|
+
{link.label}
|
|
50
|
+
</a>
|
|
51
|
+
))}
|
|
52
|
+
</div>
|
|
53
|
+
)}
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</section>
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
---
|
|
2
|
+
interface Testimonial {
|
|
3
|
+
stat: string
|
|
4
|
+
statLabel: string
|
|
5
|
+
quote: string
|
|
6
|
+
author: string
|
|
7
|
+
company: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
heading?: string
|
|
12
|
+
subheading?: string
|
|
13
|
+
testimonials?: Testimonial[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const defaultTestimonials: Testimonial[] = [
|
|
17
|
+
{
|
|
18
|
+
stat: "94%",
|
|
19
|
+
statLabel: "Faster onboarding",
|
|
20
|
+
quote: "We got our entire team onboarded in under a day. The intuitive interface and powerful integrations saved us weeks of setup time.",
|
|
21
|
+
author: "Sarah Chen",
|
|
22
|
+
company: "TechFlow Inc",
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
stat: "3x",
|
|
26
|
+
statLabel: "Productivity",
|
|
27
|
+
quote: "Our team is shipping features faster than ever. The automation tools eliminated hours of manual work every week.",
|
|
28
|
+
author: "Marcus Rivera",
|
|
29
|
+
company: "Beacon Digital",
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
stat: "40%",
|
|
33
|
+
statLabel: "Cost reduction",
|
|
34
|
+
quote: "We consolidated five different tools into SaaSify. The ROI was immediate and our team loves having everything in one place.",
|
|
35
|
+
author: "David Kim",
|
|
36
|
+
company: "Cascade Systems",
|
|
37
|
+
},
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
const {
|
|
41
|
+
heading = "Loved by teams at companies of all sizes",
|
|
42
|
+
subheading = "See how leading teams use SaaSify to drive growth and productivity.",
|
|
43
|
+
testimonials = defaultTestimonials,
|
|
44
|
+
} = Astro.props
|
|
45
|
+
|
|
46
|
+
const displayTestimonials = testimonials.length > 0 ? testimonials : defaultTestimonials
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
<section class="py-16 md:py-24">
|
|
50
|
+
<div class="container mx-auto px-4">
|
|
51
|
+
<!-- Header -->
|
|
52
|
+
{(heading || subheading) && (
|
|
53
|
+
<div class="text-center mb-12 md:mb-16 max-w-3xl mx-auto">
|
|
54
|
+
{heading && (
|
|
55
|
+
<h2 class="text-3xl md:text-4xl lg:text-5xl font-bold tracking-tight mb-4">
|
|
56
|
+
{heading}
|
|
57
|
+
</h2>
|
|
58
|
+
)}
|
|
59
|
+
{subheading && (
|
|
60
|
+
<p class="text-lg md:text-xl text-muted-foreground">
|
|
61
|
+
{subheading}
|
|
62
|
+
</p>
|
|
63
|
+
)}
|
|
64
|
+
</div>
|
|
65
|
+
)}
|
|
66
|
+
|
|
67
|
+
<!-- Testimonials Grid -->
|
|
68
|
+
<div class="grid md:grid-cols-3 gap-6 lg:gap-8">
|
|
69
|
+
{displayTestimonials.map((testimonial) => (
|
|
70
|
+
<div class="relative bg-card border border-border rounded-2xl p-6 md:p-8">
|
|
71
|
+
<!-- Stat -->
|
|
72
|
+
<div class="mb-6">
|
|
73
|
+
<div class="text-4xl md:text-5xl font-bold text-primary mb-1">
|
|
74
|
+
{testimonial.stat}
|
|
75
|
+
</div>
|
|
76
|
+
<p class="text-sm font-medium text-muted-foreground">
|
|
77
|
+
{testimonial.statLabel}
|
|
78
|
+
</p>
|
|
79
|
+
</div>
|
|
80
|
+
|
|
81
|
+
<!-- Quote -->
|
|
82
|
+
<blockquote class="text-foreground mb-6">
|
|
83
|
+
"{testimonial.quote}"
|
|
84
|
+
</blockquote>
|
|
85
|
+
|
|
86
|
+
<!-- Author -->
|
|
87
|
+
<div class="flex items-center gap-3">
|
|
88
|
+
<div class="w-10 h-10 rounded-full bg-muted flex items-center justify-center">
|
|
89
|
+
<span class="text-sm font-medium">
|
|
90
|
+
{testimonial.author.split(" ").map((n) => n[0]).join("")}
|
|
91
|
+
</span>
|
|
92
|
+
</div>
|
|
93
|
+
<div>
|
|
94
|
+
<p class="text-sm font-medium text-foreground">
|
|
95
|
+
{testimonial.author}
|
|
96
|
+
</p>
|
|
97
|
+
<p class="text-sm text-muted-foreground">
|
|
98
|
+
{testimonial.company}
|
|
99
|
+
</p>
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
</div>
|
|
103
|
+
))}
|
|
104
|
+
</div>
|
|
105
|
+
</div>
|
|
106
|
+
</section>
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
---
|
|
2
|
+
import { Zap, Plug, Database, Cloud, Shield, Lock, Award, Globe } from "lucide-astro"
|
|
3
|
+
|
|
4
|
+
interface TrustItem {
|
|
5
|
+
icon: string
|
|
6
|
+
text: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface TrustColumn {
|
|
10
|
+
label: string
|
|
11
|
+
heading: string
|
|
12
|
+
description: string
|
|
13
|
+
items: TrustItem[]
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
interface Props {
|
|
17
|
+
columns?: TrustColumn[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const defaultColumns: TrustColumn[] = [
|
|
21
|
+
{
|
|
22
|
+
label: "Integrations",
|
|
23
|
+
heading: "Connect anywhere",
|
|
24
|
+
description: "Plug in and get started immediately with pre-built connectors for every major platform.",
|
|
25
|
+
items: [
|
|
26
|
+
{ icon: "zap", text: "Go live in minutes" },
|
|
27
|
+
{ icon: "plug", text: "Pre-built connectors" },
|
|
28
|
+
{ icon: "database", text: "Complete data sync" },
|
|
29
|
+
{ icon: "cloud", text: "Cloud-native infrastructure" },
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
label: "Security & Compliance",
|
|
34
|
+
heading: "Enterprise-level security",
|
|
35
|
+
description: "Keep your data safe with encryption, granular access control, and compliance-ready infrastructure.",
|
|
36
|
+
items: [
|
|
37
|
+
{ icon: "shield", text: "SOC 2 Type II certified" },
|
|
38
|
+
{ icon: "lock", text: "End-to-end encryption" },
|
|
39
|
+
{ icon: "award", text: "Complete audit trails" },
|
|
40
|
+
{ icon: "globe", text: "GDPR compliant" },
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
const { columns = defaultColumns } = Astro.props
|
|
46
|
+
|
|
47
|
+
const displayColumns = columns.length > 0 ? columns : defaultColumns
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
<section class="py-16 md:py-24">
|
|
51
|
+
<div class="container mx-auto px-4">
|
|
52
|
+
<div class="grid md:grid-cols-2 gap-12 lg:gap-16">
|
|
53
|
+
{displayColumns.map((column) => (
|
|
54
|
+
<div>
|
|
55
|
+
<span class="inline-block text-sm font-medium text-primary mb-4">
|
|
56
|
+
{column.label}
|
|
57
|
+
</span>
|
|
58
|
+
<h2 class="text-2xl md:text-3xl font-bold tracking-tight mb-4">
|
|
59
|
+
{column.heading}
|
|
60
|
+
</h2>
|
|
61
|
+
<p class="text-muted-foreground mb-8">
|
|
62
|
+
{column.description}
|
|
63
|
+
</p>
|
|
64
|
+
|
|
65
|
+
<ul class="space-y-4">
|
|
66
|
+
{column.items.map((item) => (
|
|
67
|
+
<li class="flex items-center gap-3">
|
|
68
|
+
<div class="flex h-8 w-8 shrink-0 items-center justify-center rounded-lg bg-primary/10">
|
|
69
|
+
{item.icon === "zap" && <Zap class="h-4 w-4 text-primary" />}
|
|
70
|
+
{item.icon === "plug" && <Plug class="h-4 w-4 text-primary" />}
|
|
71
|
+
{item.icon === "database" && <Database class="h-4 w-4 text-primary" />}
|
|
72
|
+
{item.icon === "cloud" && <Cloud class="h-4 w-4 text-primary" />}
|
|
73
|
+
{item.icon === "shield" && <Shield class="h-4 w-4 text-primary" />}
|
|
74
|
+
{item.icon === "lock" && <Lock class="h-4 w-4 text-primary" />}
|
|
75
|
+
{item.icon === "award" && <Award class="h-4 w-4 text-primary" />}
|
|
76
|
+
{item.icon === "globe" && <Globe class="h-4 w-4 text-primary" />}
|
|
77
|
+
</div>
|
|
78
|
+
<span class="text-sm font-medium">
|
|
79
|
+
{item.text}
|
|
80
|
+
</span>
|
|
81
|
+
</li>
|
|
82
|
+
))}
|
|
83
|
+
</ul>
|
|
84
|
+
</div>
|
|
85
|
+
))}
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</section>
|