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,242 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import { useEffect, useState } from "react"
|
|
4
|
+
import { cn } from "@/lib/utils"
|
|
5
|
+
|
|
6
|
+
interface MockupState {
|
|
7
|
+
id: number
|
|
8
|
+
label: string
|
|
9
|
+
sidebarActive: string
|
|
10
|
+
previewTitle: string
|
|
11
|
+
previewDescription: string
|
|
12
|
+
previewCategory: string
|
|
13
|
+
previewStatus: "draft" | "published" | "featured"
|
|
14
|
+
previewUrl?: string
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
const mockupStates: MockupState[] = [
|
|
18
|
+
{
|
|
19
|
+
id: 1,
|
|
20
|
+
label: "Setup & styling",
|
|
21
|
+
sidebarActive: "templates",
|
|
22
|
+
previewTitle: "Atlas Directory",
|
|
23
|
+
previewDescription: "Apply your brand, typography, and layout in minutes.",
|
|
24
|
+
previewCategory: "Design systems",
|
|
25
|
+
previewStatus: "draft",
|
|
26
|
+
previewUrl: "atlas.directory/home",
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
id: 2,
|
|
30
|
+
label: "Plans & pricing",
|
|
31
|
+
sidebarActive: "billing",
|
|
32
|
+
previewTitle: "Pro Listing Plan",
|
|
33
|
+
previewDescription: "Recurring billing, featured placements, and add-ons configured.",
|
|
34
|
+
previewCategory: "Monetization",
|
|
35
|
+
previewStatus: "draft",
|
|
36
|
+
previewUrl: "atlas.directory/billing",
|
|
37
|
+
},
|
|
38
|
+
{
|
|
39
|
+
id: 3,
|
|
40
|
+
label: "SEO & publishing",
|
|
41
|
+
sidebarActive: "seo",
|
|
42
|
+
previewTitle: "Atlas Directory",
|
|
43
|
+
previewDescription: "Schema, sitemap, and custom domain are ready to publish.",
|
|
44
|
+
previewCategory: "SEO & domains",
|
|
45
|
+
previewStatus: "published",
|
|
46
|
+
previewUrl: "atlas.directory/launch",
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: 4,
|
|
50
|
+
label: "Payouts live",
|
|
51
|
+
sidebarActive: "overview",
|
|
52
|
+
previewTitle: "Atlas Directory",
|
|
53
|
+
previewDescription: "Subscribers active, payouts scheduled to Stripe, featured slots sold.",
|
|
54
|
+
previewCategory: "Revenue",
|
|
55
|
+
previewStatus: "featured",
|
|
56
|
+
previewUrl: "atlas.directory/analytics",
|
|
57
|
+
},
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
interface SidebarItemProps {
|
|
61
|
+
icon: string
|
|
62
|
+
label: string
|
|
63
|
+
active?: boolean
|
|
64
|
+
badge?: number
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function SidebarItem({ icon, label, active, badge }: SidebarItemProps) {
|
|
68
|
+
return (
|
|
69
|
+
<div className={cn("sidebar-item", active && "sidebar-item--active")}>
|
|
70
|
+
<span className="sidebar-icon">{icon}</span>
|
|
71
|
+
<span className="sidebar-label">{label}</span>
|
|
72
|
+
{badge && <span className="sidebar-badge">{badge}</span>}
|
|
73
|
+
</div>
|
|
74
|
+
)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
export function AnimatedMockup() {
|
|
78
|
+
const [currentState, setCurrentState] = useState(0)
|
|
79
|
+
const [isPaused, setIsPaused] = useState(false)
|
|
80
|
+
|
|
81
|
+
useEffect(() => {
|
|
82
|
+
if (isPaused) return
|
|
83
|
+
|
|
84
|
+
const interval = setInterval(() => {
|
|
85
|
+
setCurrentState((prev) => (prev + 1) % mockupStates.length)
|
|
86
|
+
}, 3000)
|
|
87
|
+
|
|
88
|
+
return () => clearInterval(interval)
|
|
89
|
+
}, [isPaused])
|
|
90
|
+
|
|
91
|
+
const state = mockupStates[currentState]
|
|
92
|
+
|
|
93
|
+
return (
|
|
94
|
+
<div
|
|
95
|
+
className="mockup-wrapper"
|
|
96
|
+
onMouseEnter={() => setIsPaused(true)}
|
|
97
|
+
onMouseLeave={() => setIsPaused(false)}
|
|
98
|
+
>
|
|
99
|
+
{/* Browser Chrome */}
|
|
100
|
+
<div className="mockup-chrome">
|
|
101
|
+
<div className="mockup-chrome-dots">
|
|
102
|
+
<span className="dot dot-red" />
|
|
103
|
+
<span className="dot dot-yellow" />
|
|
104
|
+
<span className="dot dot-green" />
|
|
105
|
+
</div>
|
|
106
|
+
<div className="mockup-chrome-title">SaaSify</div>
|
|
107
|
+
<div className="mockup-chrome-actions" />
|
|
108
|
+
</div>
|
|
109
|
+
|
|
110
|
+
{/* App Content */}
|
|
111
|
+
<div className="mockup-content">
|
|
112
|
+
{/* Sidebar */}
|
|
113
|
+
<div className="mockup-sidebar">
|
|
114
|
+
<div className="sidebar-header">
|
|
115
|
+
<div className="sidebar-logo">
|
|
116
|
+
<span className="logo-icon">D</span>
|
|
117
|
+
<span className="logo-text">My Directory</span>
|
|
118
|
+
</div>
|
|
119
|
+
</div>
|
|
120
|
+
<nav className="sidebar-nav">
|
|
121
|
+
<SidebarItem icon="📊" label="Overview" active={state.sidebarActive === "overview"} />
|
|
122
|
+
<SidebarItem icon="🖼️" label="Templates" active={state.sidebarActive === "templates"} />
|
|
123
|
+
<SidebarItem
|
|
124
|
+
icon="📋"
|
|
125
|
+
label="Listings"
|
|
126
|
+
active={state.sidebarActive === "listings"}
|
|
127
|
+
badge={24}
|
|
128
|
+
/>
|
|
129
|
+
<SidebarItem
|
|
130
|
+
icon="💳"
|
|
131
|
+
label="Plans & Billing"
|
|
132
|
+
active={state.sidebarActive === "billing"}
|
|
133
|
+
/>
|
|
134
|
+
<SidebarItem
|
|
135
|
+
icon="⚡"
|
|
136
|
+
label="Automations"
|
|
137
|
+
active={state.sidebarActive === "automations"}
|
|
138
|
+
/>
|
|
139
|
+
<SidebarItem icon="🔎" label="SEO" active={state.sidebarActive === "seo"} />
|
|
140
|
+
<SidebarItem icon="⚙️" label="Settings" active={state.sidebarActive === "settings"} />
|
|
141
|
+
</nav>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
{/* Main Content Area */}
|
|
145
|
+
<div className="mockup-main">
|
|
146
|
+
{/* Header */}
|
|
147
|
+
<div className="main-header">
|
|
148
|
+
<div className="header-title">
|
|
149
|
+
<h2>{state.label}</h2>
|
|
150
|
+
<span className="header-breadcrumb">SaaSify / {state.previewTitle}</span>
|
|
151
|
+
</div>
|
|
152
|
+
<div className="header-actions">
|
|
153
|
+
<button
|
|
154
|
+
type="button"
|
|
155
|
+
className={cn(
|
|
156
|
+
"action-btn",
|
|
157
|
+
state.previewStatus === "published" && "action-btn--success",
|
|
158
|
+
state.previewStatus === "featured" && "action-btn--featured"
|
|
159
|
+
)}
|
|
160
|
+
>
|
|
161
|
+
{state.previewStatus === "draft" && "Save Draft"}
|
|
162
|
+
{state.previewStatus === "published" && "✓ Published"}
|
|
163
|
+
{state.previewStatus === "featured" && "⭐ Featured"}
|
|
164
|
+
</button>
|
|
165
|
+
</div>
|
|
166
|
+
</div>
|
|
167
|
+
|
|
168
|
+
{/* Split View: Editor + Preview */}
|
|
169
|
+
<div className="main-split">
|
|
170
|
+
{/* Editor Panel */}
|
|
171
|
+
<div className="editor-panel">
|
|
172
|
+
<div className="editor-section">
|
|
173
|
+
<span className="editor-label">Listing Name</span>
|
|
174
|
+
<div className="editor-input">
|
|
175
|
+
<span className="input-text">{state.previewTitle}</span>
|
|
176
|
+
<span className="input-cursor" />
|
|
177
|
+
</div>
|
|
178
|
+
</div>
|
|
179
|
+
<div className="editor-section">
|
|
180
|
+
<span className="editor-label">Category</span>
|
|
181
|
+
<div className="editor-select">
|
|
182
|
+
<span>{state.previewCategory}</span>
|
|
183
|
+
<span className="select-arrow">▼</span>
|
|
184
|
+
</div>
|
|
185
|
+
</div>
|
|
186
|
+
<div className="editor-section">
|
|
187
|
+
<span className="editor-label">Description</span>
|
|
188
|
+
<div className="editor-textarea">
|
|
189
|
+
<span className={cn("textarea-text", state.id >= 2 && "textarea-text--complete")}>
|
|
190
|
+
{state.previewDescription}
|
|
191
|
+
</span>
|
|
192
|
+
</div>
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
{/* Preview Panel */}
|
|
197
|
+
<div className="preview-panel">
|
|
198
|
+
<div className="preview-header">
|
|
199
|
+
<span className="preview-label">Live Preview</span>
|
|
200
|
+
<span className="preview-url">{state.previewUrl ?? "saasify.app/live"}</span>
|
|
201
|
+
</div>
|
|
202
|
+
<div className="preview-card">
|
|
203
|
+
{state.previewStatus === "featured" && (
|
|
204
|
+
<div className="preview-badge">⭐ Featured</div>
|
|
205
|
+
)}
|
|
206
|
+
<div className="preview-image">
|
|
207
|
+
<div className="preview-image-placeholder">
|
|
208
|
+
<span>🏢</span>
|
|
209
|
+
</div>
|
|
210
|
+
</div>
|
|
211
|
+
<div className="preview-content">
|
|
212
|
+
<span className="preview-category-tag">{state.previewCategory}</span>
|
|
213
|
+
<h3 className="preview-title">{state.previewTitle}</h3>
|
|
214
|
+
<p className="preview-description">{state.previewDescription}</p>
|
|
215
|
+
<div className="preview-meta">
|
|
216
|
+
<span className="meta-rating">★★★★★</span>
|
|
217
|
+
<span className="meta-reviews">24 reviews</span>
|
|
218
|
+
</div>
|
|
219
|
+
</div>
|
|
220
|
+
</div>
|
|
221
|
+
</div>
|
|
222
|
+
</div>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
{/* State Indicator */}
|
|
227
|
+
<div className="mockup-indicators">
|
|
228
|
+
{mockupStates.map((s, i) => (
|
|
229
|
+
<button
|
|
230
|
+
type="button"
|
|
231
|
+
key={s.id}
|
|
232
|
+
onClick={() => setCurrentState(i)}
|
|
233
|
+
className={cn("indicator", i === currentState && "indicator--active")}
|
|
234
|
+
>
|
|
235
|
+
<span className="indicator-dot" />
|
|
236
|
+
<span className="indicator-label">{s.label}</span>
|
|
237
|
+
</button>
|
|
238
|
+
))}
|
|
239
|
+
</div>
|
|
240
|
+
</div>
|
|
241
|
+
)
|
|
242
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"use client"
|
|
2
|
+
|
|
3
|
+
import Link from "next/link"
|
|
4
|
+
import Image from "next/image"
|
|
5
|
+
import { AnimatedMockup } from "./AnimatedMockup"
|
|
6
|
+
import { cn } from "@/lib/utils"
|
|
7
|
+
|
|
8
|
+
interface HeroLink {
|
|
9
|
+
label: string
|
|
10
|
+
href: string
|
|
11
|
+
variant: "default" | "outline"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
interface ProductShowcaseHeroProps {
|
|
15
|
+
headline: string
|
|
16
|
+
description: string
|
|
17
|
+
links?: HeroLink[]
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function ProductShowcaseHero({
|
|
21
|
+
headline = "The modern platform for growing teams",
|
|
22
|
+
description = "Streamline workflows, boost productivity, and scale your business with one powerful platform.",
|
|
23
|
+
links = [
|
|
24
|
+
{ label: "Start free trial", href: "/sign-up", variant: "default" },
|
|
25
|
+
{ label: "Watch demo", href: "/demo", variant: "outline" },
|
|
26
|
+
],
|
|
27
|
+
}: ProductShowcaseHeroProps) {
|
|
28
|
+
return (
|
|
29
|
+
<div className="relative overflow-hidden">
|
|
30
|
+
{/* Hero Content - Left Aligned */}
|
|
31
|
+
<div className="container mx-auto px-4 pt-8 pb-16 md:pt-16 md:pb-24">
|
|
32
|
+
<div className="max-w-2xl">
|
|
33
|
+
<h1 className="text-4xl font-bold tracking-tight text-foreground sm:text-5xl md:text-6xl">
|
|
34
|
+
{headline}
|
|
35
|
+
</h1>
|
|
36
|
+
<p className="mt-6 text-lg text-muted-foreground md:text-xl">
|
|
37
|
+
{description}
|
|
38
|
+
</p>
|
|
39
|
+
{links && links.length > 0 && (
|
|
40
|
+
<div className="mt-8 flex flex-wrap gap-4">
|
|
41
|
+
{links.map((link) => (
|
|
42
|
+
<Link
|
|
43
|
+
key={link.href}
|
|
44
|
+
href={link.href}
|
|
45
|
+
className={cn(
|
|
46
|
+
"inline-flex items-center justify-center px-6 py-3 text-sm font-medium rounded-md transition-colors",
|
|
47
|
+
link.variant === "default"
|
|
48
|
+
? "bg-primary text-primary-foreground hover:bg-primary/90"
|
|
49
|
+
: "border border-border bg-background hover:bg-muted"
|
|
50
|
+
)}
|
|
51
|
+
>
|
|
52
|
+
{link.label}
|
|
53
|
+
</Link>
|
|
54
|
+
))}
|
|
55
|
+
</div>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
{/* Product Mockup Section */}
|
|
61
|
+
<div className="container mx-auto px-4">
|
|
62
|
+
<div className="hero-showcase">
|
|
63
|
+
{/* Background Image */}
|
|
64
|
+
<div className="hero-bg-image">
|
|
65
|
+
<Image
|
|
66
|
+
src="/media/hero-bg.png"
|
|
67
|
+
alt=""
|
|
68
|
+
fill
|
|
69
|
+
sizes="(max-width: 1280px) 100vw, 1280px"
|
|
70
|
+
className="object-cover"
|
|
71
|
+
priority
|
|
72
|
+
quality={75}
|
|
73
|
+
/>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
{/* Mockup - centered within background */}
|
|
77
|
+
<div className="hero-mockup-centered">
|
|
78
|
+
<AnimatedMockup />
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
)
|
|
84
|
+
}
|